mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-22 12:33:12 +00:00
Merge branch 'master' of https://github.com/KillzXGaming/Switch-Toolbox
This commit is contained in:
commit
c204608f9b
8 changed files with 232 additions and 118 deletions
|
@ -1048,6 +1048,7 @@ namespace Toolbox.Library.Forms
|
||||||
var panel = new STPanel() { Dock = DockStyle.Fill };
|
var panel = new STPanel() { Dock = DockStyle.Fill };
|
||||||
panel.Controls.Add(searchForm);
|
panel.Controls.Add(searchForm);
|
||||||
form.AddControl(panel);
|
form.AddControl(panel);
|
||||||
|
form.Text = "Search Window";
|
||||||
form.Show(this);
|
form.Show(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
this.listViewModeCB = new Toolbox.Library.Forms.STComboBox();
|
this.listViewModeCB = new Toolbox.Library.Forms.STComboBox();
|
||||||
this.lblFoundEntries = new Toolbox.Library.Forms.STLabel();
|
this.lblFoundEntries = new Toolbox.Library.Forms.STLabel();
|
||||||
this.chkUpdateDoubleClick = new Toolbox.Library.Forms.STCheckBox();
|
this.chkUpdateDoubleClick = new Toolbox.Library.Forms.STCheckBox();
|
||||||
|
this.chkAllowWildcards = new Toolbox.Library.Forms.STCheckBox();
|
||||||
|
this.chkOpenWithDoubleClick = new Toolbox.Library.Forms.STCheckBox();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// listViewCustom1
|
// listViewCustom1
|
||||||
|
@ -50,6 +52,7 @@
|
||||||
this.listViewCustom1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
this.listViewCustom1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||||
this.columnHeader1});
|
this.columnHeader1});
|
||||||
this.listViewCustom1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
this.listViewCustom1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||||
|
this.listViewCustom1.HideSelection = false;
|
||||||
this.listViewCustom1.Location = new System.Drawing.Point(5, 77);
|
this.listViewCustom1.Location = new System.Drawing.Point(5, 77);
|
||||||
this.listViewCustom1.Name = "listViewCustom1";
|
this.listViewCustom1.Name = "listViewCustom1";
|
||||||
this.listViewCustom1.OwnerDraw = true;
|
this.listViewCustom1.OwnerDraw = true;
|
||||||
|
@ -88,7 +91,7 @@
|
||||||
// chkSearchSubNodes
|
// chkSearchSubNodes
|
||||||
//
|
//
|
||||||
this.chkSearchSubNodes.AutoSize = true;
|
this.chkSearchSubNodes.AutoSize = true;
|
||||||
this.chkSearchSubNodes.Location = new System.Drawing.Point(195, 31);
|
this.chkSearchSubNodes.Location = new System.Drawing.Point(8, 54);
|
||||||
this.chkSearchSubNodes.Name = "chkSearchSubNodes";
|
this.chkSearchSubNodes.Name = "chkSearchSubNodes";
|
||||||
this.chkSearchSubNodes.Size = new System.Drawing.Size(111, 17);
|
this.chkSearchSubNodes.Size = new System.Drawing.Size(111, 17);
|
||||||
this.chkSearchSubNodes.TabIndex = 14;
|
this.chkSearchSubNodes.TabIndex = 14;
|
||||||
|
@ -118,7 +121,7 @@
|
||||||
// chkAutoSearch
|
// chkAutoSearch
|
||||||
//
|
//
|
||||||
this.chkAutoSearch.AutoSize = true;
|
this.chkAutoSearch.AutoSize = true;
|
||||||
this.chkAutoSearch.Location = new System.Drawing.Point(100, 31);
|
this.chkAutoSearch.Location = new System.Drawing.Point(207, 31);
|
||||||
this.chkAutoSearch.Name = "chkAutoSearch";
|
this.chkAutoSearch.Name = "chkAutoSearch";
|
||||||
this.chkAutoSearch.Size = new System.Drawing.Size(85, 17);
|
this.chkAutoSearch.Size = new System.Drawing.Size(85, 17);
|
||||||
this.chkAutoSearch.TabIndex = 17;
|
this.chkAutoSearch.TabIndex = 17;
|
||||||
|
@ -132,6 +135,7 @@
|
||||||
this.listViewModeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid;
|
this.listViewModeCB.BorderStyle = System.Windows.Forms.ButtonBorderStyle.Solid;
|
||||||
this.listViewModeCB.ButtonColor = System.Drawing.Color.Empty;
|
this.listViewModeCB.ButtonColor = System.Drawing.Color.Empty;
|
||||||
this.listViewModeCB.FormattingEnabled = true;
|
this.listViewModeCB.FormattingEnabled = true;
|
||||||
|
this.listViewModeCB.IsReadOnly = false;
|
||||||
this.listViewModeCB.Location = new System.Drawing.Point(5, 346);
|
this.listViewModeCB.Location = new System.Drawing.Point(5, 346);
|
||||||
this.listViewModeCB.Name = "listViewModeCB";
|
this.listViewModeCB.Name = "listViewModeCB";
|
||||||
this.listViewModeCB.Size = new System.Drawing.Size(143, 21);
|
this.listViewModeCB.Size = new System.Drawing.Size(143, 21);
|
||||||
|
@ -151,17 +155,39 @@
|
||||||
// chkUpdateDoubleClick
|
// chkUpdateDoubleClick
|
||||||
//
|
//
|
||||||
this.chkUpdateDoubleClick.AutoSize = true;
|
this.chkUpdateDoubleClick.AutoSize = true;
|
||||||
this.chkUpdateDoubleClick.Location = new System.Drawing.Point(8, 54);
|
this.chkUpdateDoubleClick.Location = new System.Drawing.Point(125, 54);
|
||||||
this.chkUpdateDoubleClick.Name = "chkUpdateDoubleClick";
|
this.chkUpdateDoubleClick.Name = "chkUpdateDoubleClick";
|
||||||
this.chkUpdateDoubleClick.Size = new System.Drawing.Size(138, 17);
|
this.chkUpdateDoubleClick.Size = new System.Drawing.Size(134, 17);
|
||||||
this.chkUpdateDoubleClick.TabIndex = 20;
|
this.chkUpdateDoubleClick.TabIndex = 20;
|
||||||
this.chkUpdateDoubleClick.Text = "Update by Double Click";
|
this.chkUpdateDoubleClick.Text = "Select on Double Click";
|
||||||
this.chkUpdateDoubleClick.UseVisualStyleBackColor = true;
|
this.chkUpdateDoubleClick.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// chkAllowWildcards
|
||||||
|
//
|
||||||
|
this.chkAllowWildcards.AutoSize = true;
|
||||||
|
this.chkAllowWildcards.Location = new System.Drawing.Point(100, 31);
|
||||||
|
this.chkAllowWildcards.Name = "chkAllowWildcards";
|
||||||
|
this.chkAllowWildcards.Size = new System.Drawing.Size(101, 17);
|
||||||
|
this.chkAllowWildcards.TabIndex = 21;
|
||||||
|
this.chkAllowWildcards.Text = "Allow Wildcards";
|
||||||
|
this.chkAllowWildcards.UseVisualStyleBackColor = true;
|
||||||
|
this.chkAllowWildcards.CheckedChanged += new System.EventHandler(this.chkAllowWildcards_CheckedChanged);
|
||||||
|
//
|
||||||
|
// chkOpenWithDoubleClick
|
||||||
|
//
|
||||||
|
this.chkOpenWithDoubleClick.Location = new System.Drawing.Point(269, 54);
|
||||||
|
this.chkOpenWithDoubleClick.Name = "chkOpenWithDoubleClick";
|
||||||
|
this.chkOpenWithDoubleClick.Size = new System.Drawing.Size(136, 17);
|
||||||
|
this.chkOpenWithDoubleClick.TabIndex = 0;
|
||||||
|
this.chkOpenWithDoubleClick.Text = "Open by Double Click";
|
||||||
|
this.chkOpenWithDoubleClick.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
// SearchNodePanel
|
// SearchNodePanel
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.Controls.Add(this.chkOpenWithDoubleClick);
|
||||||
|
this.Controls.Add(this.chkAllowWildcards);
|
||||||
this.Controls.Add(this.chkUpdateDoubleClick);
|
this.Controls.Add(this.chkUpdateDoubleClick);
|
||||||
this.Controls.Add(this.lblFoundEntries);
|
this.Controls.Add(this.lblFoundEntries);
|
||||||
this.Controls.Add(this.listViewModeCB);
|
this.Controls.Add(this.listViewModeCB);
|
||||||
|
@ -192,5 +218,7 @@
|
||||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||||
private STLabel lblFoundEntries;
|
private STLabel lblFoundEntries;
|
||||||
private STCheckBox chkUpdateDoubleClick;
|
private STCheckBox chkUpdateDoubleClick;
|
||||||
|
private STCheckBox chkAllowWildcards;
|
||||||
|
private STCheckBox chkOpenWithDoubleClick;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ using System.Data;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
@ -18,6 +19,8 @@ namespace Toolbox.Library.Forms
|
||||||
private bool MatchCase => chkMatchCase.Checked;
|
private bool MatchCase => chkMatchCase.Checked;
|
||||||
private bool SearchSubNodes => chkSearchSubNodes.Checked;
|
private bool SearchSubNodes => chkSearchSubNodes.Checked;
|
||||||
private bool UpdateDoubleClick => chkUpdateDoubleClick.Checked;
|
private bool UpdateDoubleClick => chkUpdateDoubleClick.Checked;
|
||||||
|
private bool OpenDoubleClick => chkOpenWithDoubleClick.Checked;
|
||||||
|
private bool AllowWildcards => chkAllowWildcards.Checked;
|
||||||
|
|
||||||
private List<TreeNode> TreenodeLookup = new List<TreeNode>();
|
private List<TreeNode> TreenodeLookup = new List<TreeNode>();
|
||||||
|
|
||||||
|
@ -67,21 +70,21 @@ namespace Toolbox.Library.Forms
|
||||||
TreenodeLookup.Clear();
|
TreenodeLookup.Clear();
|
||||||
|
|
||||||
foreach (TreeNode node in treeView.Nodes)
|
foreach (TreeNode node in treeView.Nodes)
|
||||||
RecurvsiveTreeNodeSearch(node, text);
|
RecursiveTreeNodeSearch(node, text);
|
||||||
|
|
||||||
listViewCustom1.EndUpdate();
|
listViewCustom1.EndUpdate();
|
||||||
|
|
||||||
lblFoundEntries.Text = $"Found Entries {TreenodeLookup.Count} of {TotalNodeCount}";
|
lblFoundEntries.Text = $"Found Entries {TreenodeLookup.Count} of {TotalNodeCount}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecurvsiveTreeNodeSearch(TreeNode parentNode, string text)
|
private static String WildCardToRegular(String query)
|
||||||
{
|
{
|
||||||
bool HasText = false;
|
return Regex.Escape(query).Replace("\\?", ".").Replace("\\*", ".*")+".*";
|
||||||
|
}
|
||||||
|
|
||||||
if (MatchCase)
|
private void RecursiveTreeNodeSearch(TreeNode parentNode, string text)
|
||||||
HasText = parentNode.Text.IndexOf(text, StringComparison.Ordinal) >= 0;
|
{
|
||||||
else
|
bool HasText = Regex.IsMatch(parentNode.Text, AllowWildcards ? WildCardToRegular(text) : text, MatchCase ? RegexOptions.None : RegexOptions.IgnoreCase);
|
||||||
HasText = parentNode.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0;
|
|
||||||
|
|
||||||
if (HasText)
|
if (HasText)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +111,7 @@ namespace Toolbox.Library.Forms
|
||||||
if (SearchSubNodes)
|
if (SearchSubNodes)
|
||||||
{
|
{
|
||||||
foreach (TreeNode node in parentNode.Nodes)
|
foreach (TreeNode node in parentNode.Nodes)
|
||||||
RecurvsiveTreeNodeSearch(node, text);
|
RecursiveTreeNodeSearch(node, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
TotalNodeCount++;
|
TotalNodeCount++;
|
||||||
|
@ -123,6 +126,14 @@ namespace Toolbox.Library.Forms
|
||||||
treeView.SelectedNode = TreenodeLookup[index];
|
treeView.SelectedNode = TreenodeLookup[index];
|
||||||
treeView.Refresh();
|
treeView.Refresh();
|
||||||
}
|
}
|
||||||
|
if (listViewCustom1.SelectedItems.Count > 0 && OpenDoubleClick)
|
||||||
|
{
|
||||||
|
int index = listViewCustom1.SelectedIndices[0];
|
||||||
|
if (TreenodeLookup[index] is TreeNodeCustom)
|
||||||
|
((TreeNodeCustom)TreenodeLookup[index]).OnDoubleMouseClick(treeView);
|
||||||
|
if (TreenodeLookup[index].Tag != null && TreenodeLookup[index].Tag is TreeNodeCustom)
|
||||||
|
((TreeNodeCustom)TreenodeLookup[index].Tag).OnDoubleMouseClick(treeView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listViewModeCB_SelectedIndexChanged(object sender, EventArgs e)
|
private void listViewModeCB_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
@ -152,5 +163,9 @@ namespace Toolbox.Library.Forms
|
||||||
treeView.SelectedNode = TreenodeLookup[index];
|
treeView.SelectedNode = TreenodeLookup[index];
|
||||||
treeView.Refresh();
|
treeView.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void chkAllowWildcards_CheckedChanged(object sender, EventArgs e) {
|
||||||
|
UpdateSearchResults(searchTB.Text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -8,6 +9,48 @@ namespace Toolbox.Library
|
||||||
{
|
{
|
||||||
public class TegraX1Swizzle
|
public class TegraX1Swizzle
|
||||||
{
|
{
|
||||||
|
// Swizzle code and surface calculations are performed using an efficient Rust implementation.
|
||||||
|
// C# code can call the Rust code using the library's C API.
|
||||||
|
// Documentation, code, and tests for the tegra_swizzle Rust library can be found here:
|
||||||
|
// https://github.com/ScanMountGoat/nutexb_swizzle
|
||||||
|
|
||||||
|
// TODO: Find a cleaner way to support both 32 and 64 bit binaries.
|
||||||
|
// 64 Bit.
|
||||||
|
[DllImport("tegra_swizzle_x64", EntryPoint = "deswizzle_block_linear")]
|
||||||
|
private static unsafe extern void DeswizzleBlockLinearX64(ulong width, ulong height, ulong depth, byte* source, ulong sourceLength,
|
||||||
|
byte[] destination, ulong destinationLength, ulong blockHeight, ulong bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x64", EntryPoint = "swizzle_block_linear")]
|
||||||
|
private static unsafe extern void SwizzleBlockLinearX64(ulong width, ulong height, ulong depth, byte* source, ulong sourceLength,
|
||||||
|
byte[] destination, ulong destinationLength, ulong blockHeight, ulong bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x64", EntryPoint = "swizzled_surface_size")]
|
||||||
|
private static extern ulong GetSurfaceSizeX64(ulong width, ulong height, ulong depth, ulong blockHeight, ulong bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x64", EntryPoint = "block_height_mip0")]
|
||||||
|
private static extern ulong BlockHeightMip0X64(ulong height);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x64", EntryPoint = "mip_block_height")]
|
||||||
|
private static extern ulong MipBlockHeightX64(ulong mipHeight, ulong blockHeightMip0);
|
||||||
|
|
||||||
|
// 32 Bit.
|
||||||
|
[DllImport("tegra_swizzle_x86", EntryPoint = "deswizzle_block_linear")]
|
||||||
|
private static unsafe extern void DeswizzleBlockLinearX86(uint width, uint height, uint depth, byte* source, uint sourceLength,
|
||||||
|
byte[] destination, uint destinationLength, uint blockHeight, uint bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x86", EntryPoint = "swizzle_block_linear")]
|
||||||
|
private static unsafe extern void SwizzleBlockLinearX86(uint width, uint height, uint depth, byte* source, uint sourceLength,
|
||||||
|
byte[] destination, uint destinationLength, uint blockHeight, uint bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x86", EntryPoint = "swizzled_surface_size")]
|
||||||
|
private static extern uint GetSurfaceSizeX86(uint width, uint height, uint depth, uint blockHeight, uint bytesPerPixel);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x86", EntryPoint = "block_height_mip0")]
|
||||||
|
private static extern uint BlockHeightMip0X86(uint height);
|
||||||
|
|
||||||
|
[DllImport("tegra_swizzle_x86", EntryPoint = "mip_block_height")]
|
||||||
|
private static extern uint MipBlockHeightX86(uint mipHeight, uint blockHeightMip0);
|
||||||
|
|
||||||
public static List<uint[]> GenerateMipSizes(TEX_FORMAT Format, uint Width, uint Height, uint Depth, uint SurfaceCount, uint MipCount, uint ImageSize)
|
public static List<uint[]> GenerateMipSizes(TEX_FORMAT Format, uint Width, uint Height, uint Depth, uint SurfaceCount, uint MipCount, uint ImageSize)
|
||||||
{
|
{
|
||||||
List<uint[]> MipMapSizes = new List<uint[]>();
|
List<uint[]> MipMapSizes = new List<uint[]>();
|
||||||
|
@ -17,7 +60,7 @@ namespace Toolbox.Library
|
||||||
uint blkHeight = STGenericTexture.GetBlockHeight(Format);
|
uint blkHeight = STGenericTexture.GetBlockHeight(Format);
|
||||||
uint blkDepth = STGenericTexture.GetBlockDepth(Format);
|
uint blkDepth = STGenericTexture.GetBlockDepth(Format);
|
||||||
|
|
||||||
uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
|
uint blockHeight = GetBlockHeight(DIV_ROUND_UP(Height, blkHeight));
|
||||||
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
||||||
|
|
||||||
uint Pitch = 0;
|
uint Pitch = 0;
|
||||||
|
@ -41,7 +84,7 @@ namespace Toolbox.Library
|
||||||
uint height = (uint)Math.Max(1, Height >> mipLevel);
|
uint height = (uint)Math.Max(1, Height >> mipLevel);
|
||||||
uint depth = (uint)Math.Max(1, Depth >> mipLevel);
|
uint depth = (uint)Math.Max(1, Depth >> mipLevel);
|
||||||
|
|
||||||
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
|
uint size = DIV_ROUND_UP(width, blkWidth) * DIV_ROUND_UP(height, blkHeight) * bpp;
|
||||||
MipOffsets[mipLevel] = size;
|
MipOffsets[mipLevel] = size;
|
||||||
}
|
}
|
||||||
ArrayOffset += (uint)(ImageSize / ArrayCount);
|
ArrayOffset += (uint)(ImageSize / ArrayCount);
|
||||||
|
@ -56,7 +99,7 @@ namespace Toolbox.Library
|
||||||
{
|
{
|
||||||
uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
|
uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
|
||||||
uint blkDepth = STGenericTexture.GetBlockDepth(texture.Format);
|
uint blkDepth = STGenericTexture.GetBlockDepth(texture.Format);
|
||||||
uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(texture.Height, blkHeight));
|
uint blockHeight = GetBlockHeight(DIV_ROUND_UP(texture.Height, blkHeight));
|
||||||
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
||||||
return GetImageData(texture, ImageData, ArrayLevel, MipLevel, DepthLevel, BlockHeightLog2, target, LinearTileMode);
|
return GetImageData(texture, ImageData, ArrayLevel, MipLevel, DepthLevel, BlockHeightLog2, target, LinearTileMode);
|
||||||
}
|
}
|
||||||
|
@ -67,10 +110,7 @@ namespace Toolbox.Library
|
||||||
uint blkWidth = STGenericTexture.GetBlockWidth(texture.Format);
|
uint blkWidth = STGenericTexture.GetBlockWidth(texture.Format);
|
||||||
uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
|
uint blkHeight = STGenericTexture.GetBlockHeight(texture.Format);
|
||||||
uint blkDepth = STGenericTexture.GetBlockDepth(texture.Format);
|
uint blkDepth = STGenericTexture.GetBlockDepth(texture.Format);
|
||||||
uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(texture.Height, blkHeight));
|
|
||||||
|
|
||||||
uint Pitch = 0;
|
|
||||||
uint DataAlignment = 512;
|
|
||||||
uint TileMode = 0;
|
uint TileMode = 0;
|
||||||
if (LinearTileMode)
|
if (LinearTileMode)
|
||||||
TileMode = 1;
|
TileMode = 1;
|
||||||
|
@ -78,57 +118,48 @@ namespace Toolbox.Library
|
||||||
if (texture.Depth > 1)
|
if (texture.Depth > 1)
|
||||||
numDepth = texture.Depth;
|
numDepth = texture.Depth;
|
||||||
|
|
||||||
int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;
|
var blockHeightMip0 = GetBlockHeight(DIV_ROUND_UP(texture.Height, blkHeight));
|
||||||
|
|
||||||
uint ArrayOffset = 0;
|
uint arrayOffset = 0;
|
||||||
|
// TODO: Why is depth done like this?
|
||||||
for (int depthLevel = 0; depthLevel < numDepth; depthLevel++)
|
for (int depthLevel = 0; depthLevel < numDepth; depthLevel++)
|
||||||
{
|
{
|
||||||
for (int arrayLevel = 0; arrayLevel < texture.ArrayCount; arrayLevel++)
|
for (int arrayLevel = 0; arrayLevel < texture.ArrayCount; arrayLevel++)
|
||||||
{
|
{
|
||||||
uint SurfaceSize = 0;
|
var mipOffset = 0u;
|
||||||
int blockHeightShift = 0;
|
|
||||||
|
|
||||||
List<uint> MipOffsets = new List<uint>();
|
|
||||||
|
|
||||||
for (int mipLevel = 0; mipLevel < texture.MipCount; mipLevel++)
|
for (int mipLevel = 0; mipLevel < texture.MipCount; mipLevel++)
|
||||||
{
|
{
|
||||||
uint width = (uint)Math.Max(1, texture.Width >> mipLevel);
|
uint width = Math.Max(1, texture.Width >> mipLevel);
|
||||||
uint height = (uint)Math.Max(1, texture.Height >> mipLevel);
|
uint height = Math.Max(1, texture.Height >> mipLevel);
|
||||||
uint depth = (uint)Math.Max(1, texture.Depth >> mipLevel);
|
uint depth = Math.Max(1, texture.Depth >> mipLevel);
|
||||||
|
|
||||||
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
|
uint widthInBlocks = DIV_ROUND_UP(width, blkWidth);
|
||||||
|
uint heightInBlocks = DIV_ROUND_UP(height, blkHeight);
|
||||||
|
uint depthInBlocks = DIV_ROUND_UP(depth, blkDepth);
|
||||||
|
|
||||||
Console.WriteLine($"size " + size);
|
// tegra_swizzle only allows block heights supported by the TRM (1,2,4,8,16,32).
|
||||||
|
var mipBlockHeightLog2 = (int)Math.Log(GetMipBlockHeight(heightInBlocks, blockHeightMip0), 2);
|
||||||
|
var mipBlockHeight = 1 << Math.Max(Math.Min(mipBlockHeightLog2, 5), 0);
|
||||||
|
|
||||||
if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
|
uint mipSize;
|
||||||
blockHeightShift += 1;
|
if (Environment.Is64BitProcess)
|
||||||
|
mipSize = (uint)GetSurfaceSizeX64(widthInBlocks, heightInBlocks, depthInBlocks, (ulong)mipBlockHeight, bpp);
|
||||||
|
else
|
||||||
|
mipSize = (uint)GetSurfaceSizeX86(widthInBlocks, heightInBlocks, depthInBlocks, (uint)mipBlockHeight, bpp);
|
||||||
|
|
||||||
uint width__ = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
|
// TODO: Avoid this copy.
|
||||||
uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);
|
byte[] mipData = Utils.SubArray(ImageData, arrayOffset + mipOffset, mipSize);
|
||||||
|
|
||||||
//Calculate the mip size instead
|
|
||||||
byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
|
|
||||||
SurfaceSize += (uint)AlignedData.Length;
|
|
||||||
MipOffsets.Add(SurfaceSize);
|
|
||||||
|
|
||||||
//Get the first mip offset and current one and the total image size
|
|
||||||
int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / texture.ArrayCount);
|
|
||||||
|
|
||||||
byte[] data_ = Utils.SubArray(ImageData, ArrayOffset + MipOffsets[mipLevel], (uint)msize);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Pitch = TegraX1Swizzle.round_up(width__ * bpp, 64);
|
|
||||||
SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);
|
|
||||||
|
|
||||||
byte[] result = TegraX1Swizzle.deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
|
|
||||||
//Create a copy and use that to remove uneeded data
|
|
||||||
byte[] result_ = new byte[size];
|
|
||||||
Array.Copy(result, 0, result_, 0, size);
|
|
||||||
result = null;
|
|
||||||
|
|
||||||
if (ArrayLevel == arrayLevel && MipLevel == mipLevel && DepthLevel == depthLevel)
|
if (ArrayLevel == arrayLevel && MipLevel == mipLevel && DepthLevel == depthLevel)
|
||||||
return result_;
|
{
|
||||||
|
// The set of swizzled addresses is at least as big as the set of linear addresses.
|
||||||
|
// When defined appropriately, we only require a single memory allocation for the output.
|
||||||
|
byte[] result = deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, mipBlockHeightLog2, mipData);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -137,29 +168,102 @@ namespace Toolbox.Library
|
||||||
|
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mipOffset += mipSize;
|
||||||
}
|
}
|
||||||
ArrayOffset += (uint)(ImageData.Length / texture.ArrayCount);
|
|
||||||
|
arrayOffset += (uint)(ImageData.Length / texture.ArrayCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static unsafe byte[] SwizzleDeswizzleBlockLinear(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth,
|
||||||
|
uint bpp, int blockHeightLog2, byte[] data, bool deswizzle)
|
||||||
|
{
|
||||||
|
// This function expects the surface dimensions in blocks rather than pixels for block compressed formats.
|
||||||
|
// This ensures the bytes per pixel parameter is used correctly.
|
||||||
|
width = DIV_ROUND_UP(width, blkWidth);
|
||||||
|
height = DIV_ROUND_UP(height, blkHeight);
|
||||||
|
depth = DIV_ROUND_UP(depth, blkDepth);
|
||||||
|
|
||||||
|
// tegra_swizzle only allows block heights supported by the TRM (1,2,4,8,16,32).
|
||||||
|
var blockHeight = (ulong)(1 << Math.Max(Math.Min(blockHeightLog2, 5), 0));
|
||||||
|
|
||||||
|
if (deswizzle)
|
||||||
|
{
|
||||||
|
var output = new byte[width * height * bpp];
|
||||||
|
|
||||||
|
fixed (byte* dataPtr = data)
|
||||||
|
{
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
DeswizzleBlockLinearX64(width, height, depth, dataPtr, (ulong)data.Length, output, (ulong)output.Length, blockHeight, bpp);
|
||||||
|
else
|
||||||
|
DeswizzleBlockLinearX86(width, height, depth, dataPtr, (uint)data.Length, output, (uint)output.Length, (uint)blockHeight, bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulong surfaceSize;
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
surfaceSize = GetSurfaceSizeX64(width, height, depth, blockHeight, bpp);
|
||||||
|
else
|
||||||
|
surfaceSize = GetSurfaceSizeX86(width, height, depth, (uint)blockHeight, bpp);
|
||||||
|
|
||||||
|
var output = new byte[surfaceSize];
|
||||||
|
|
||||||
|
fixed (byte* dataPtr = data)
|
||||||
|
{
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
SwizzleBlockLinearX64(width, height, depth, dataPtr, (ulong)data.Length, output, (ulong)output.Length, blockHeight, bpp);
|
||||||
|
else
|
||||||
|
SwizzleBlockLinearX86(width, height, depth, dataPtr, (uint)data.Length, output, (uint)output.Length, (uint)blockHeight, bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint GetBlockHeight(uint heightInBytes)
|
||||||
|
{
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
return (uint)BlockHeightMip0X64(heightInBytes);
|
||||||
|
else
|
||||||
|
return BlockHeightMip0X86(heightInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint GetMipBlockHeight(uint mipHeightInBytes, uint blockHeightMip0)
|
||||||
|
{
|
||||||
|
if (Environment.Is64BitProcess)
|
||||||
|
return (uint)MipBlockHeightX64(mipHeightInBytes, blockHeightMip0);
|
||||||
|
else
|
||||||
|
return MipBlockHeightX86(mipHeightInBytes, blockHeightMip0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] deswizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data)
|
||||||
|
{
|
||||||
|
if (tileMode == 1)
|
||||||
|
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, true);
|
||||||
|
else
|
||||||
|
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] swizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data)
|
||||||
|
{
|
||||||
|
if (tileMode == 1)
|
||||||
|
return SwizzlePitchLinear(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, blockHeightLog2, data, false);
|
||||||
|
else
|
||||||
|
return SwizzleDeswizzleBlockLinear(width, height, depth, blkWidth, blkHeight, blkDepth, bpp, blockHeightLog2, data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------
|
/*---------------------------------------
|
||||||
*
|
*
|
||||||
* Code ported from AboodXD's BNTX Extractor https://github.com/aboood40091/BNTX-Extractor/blob/master/swizzle.py
|
* Code ported from AboodXD's BNTX Extractor https://github.com/aboood40091/BNTX-Extractor/blob/master/swizzle.py
|
||||||
*
|
*
|
||||||
*---------------------------------------*/
|
*---------------------------------------*/
|
||||||
|
|
||||||
public static uint GetBlockHeight(uint height)
|
|
||||||
{
|
|
||||||
uint blockHeight = pow2_round_up(height / 8);
|
|
||||||
if (blockHeight > 16)
|
|
||||||
blockHeight = 16;
|
|
||||||
|
|
||||||
return blockHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint DIV_ROUND_UP(uint n, uint d)
|
public static uint DIV_ROUND_UP(uint n, uint d)
|
||||||
{
|
{
|
||||||
return (n + d - 1) / d;
|
return (n + d - 1) / d;
|
||||||
|
@ -179,32 +283,23 @@ namespace Toolbox.Library
|
||||||
return x + 1;
|
return x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] _swizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int blockHeightLog2, byte[] data, int toSwizzle)
|
private static byte[] SwizzlePitchLinear(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, int blockHeightLog2, byte[] data, bool deswizzle)
|
||||||
{
|
{
|
||||||
uint block_height = (uint)(1 << blockHeightLog2);
|
// TODO: Investigate doing this more efficiently in Rust.
|
||||||
|
|
||||||
Console.WriteLine($"Swizzle {width} {height} {blkWidth} {blkHeight} {roundPitch} {bpp} {tileMode} {blockHeightLog2} {data.Length} {toSwizzle}");
|
|
||||||
|
|
||||||
width = DIV_ROUND_UP(width, blkWidth);
|
width = DIV_ROUND_UP(width, blkWidth);
|
||||||
height = DIV_ROUND_UP(height, blkHeight);
|
height = DIV_ROUND_UP(height, blkHeight);
|
||||||
depth = DIV_ROUND_UP(depth, blkDepth);
|
depth = DIV_ROUND_UP(depth, blkDepth);
|
||||||
|
|
||||||
uint pitch;
|
uint pitch;
|
||||||
uint surfSize;
|
uint surfSize;
|
||||||
if (tileMode == 1)
|
|
||||||
{
|
|
||||||
pitch = width * bpp;
|
|
||||||
|
|
||||||
if (roundPitch == 1)
|
pitch = width * bpp;
|
||||||
pitch = round_up(pitch, 32);
|
|
||||||
|
if (roundPitch == 1)
|
||||||
|
pitch = round_up(pitch, 32);
|
||||||
|
|
||||||
|
surfSize = pitch * height;
|
||||||
|
|
||||||
surfSize = pitch * height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pitch = round_up(width * bpp, 64);
|
|
||||||
surfSize = pitch * round_up(height, block_height * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] result = new byte[surfSize];
|
byte[] result = new byte[surfSize];
|
||||||
|
|
||||||
|
@ -215,16 +310,13 @@ namespace Toolbox.Library
|
||||||
uint pos;
|
uint pos;
|
||||||
uint pos_;
|
uint pos_;
|
||||||
|
|
||||||
if (tileMode == 1)
|
pos = y * pitch + x * bpp;
|
||||||
pos = y * pitch + x * bpp;
|
|
||||||
else
|
|
||||||
pos = getAddrBlockLinear(x, y, width, bpp, 0, block_height);
|
|
||||||
|
|
||||||
pos_ = (y * width + x) * bpp;
|
pos_ = (y * width + x) * bpp;
|
||||||
|
|
||||||
if (pos + bpp <= surfSize)
|
if (pos + bpp <= surfSize)
|
||||||
{
|
{
|
||||||
if (toSwizzle == 0)
|
if (!deswizzle)
|
||||||
Array.Copy(data, pos, result, pos_, bpp);
|
Array.Copy(data, pos, result, pos_, bpp);
|
||||||
else
|
else
|
||||||
Array.Copy(data, pos_, result, pos, bpp);
|
Array.Copy(data, pos_, result, pos, bpp);
|
||||||
|
@ -233,35 +325,5 @@ namespace Toolbox.Library
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] deswizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight, uint blkDepth, int roundPitch, uint bpp, uint tileMode, int size_range, byte[] data)
|
|
||||||
{
|
|
||||||
return _swizzle(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, tileMode, size_range, data, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] swizzle(uint width, uint height, uint depth, uint blkWidth, uint blkHeight,uint blkDepth, int roundPitch, uint bpp, uint tileMode, int size_range, byte[] data)
|
|
||||||
{
|
|
||||||
return _swizzle(width, height, depth, blkWidth, blkHeight, blkDepth, roundPitch, bpp, tileMode, size_range, data, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint getAddrBlockLinear(uint x, uint y, uint width, uint bytes_per_pixel, uint base_address, uint block_height)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
From Tega X1 TRM
|
|
||||||
*/
|
|
||||||
uint image_width_in_gobs = DIV_ROUND_UP(width * bytes_per_pixel, 64);
|
|
||||||
|
|
||||||
|
|
||||||
uint GOB_address = (base_address
|
|
||||||
+ (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs
|
|
||||||
+ (x * bytes_per_pixel / 64) * 512 * block_height
|
|
||||||
+ (y % (8 * block_height) / 8) * 512);
|
|
||||||
|
|
||||||
x *= bytes_per_pixel;
|
|
||||||
|
|
||||||
uint Address = (GOB_address + ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64
|
|
||||||
+ ((x % 32) / 16) * 32 + (y % 2) * 16 + (x % 16));
|
|
||||||
return Address;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -635,6 +635,12 @@
|
||||||
<None Include="Shader\LevelEditor\LightingGraphics.frag">
|
<None Include="Shader\LevelEditor\LightingGraphics.frag">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<Content Include="tegra_swizzle_x64.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="tegra_swizzle_x86.dll">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="x64\DirectXTexNetImpl.dll">
|
<Content Include="x64\DirectXTexNetImpl.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
BIN
Toolbox/tegra_swizzle_x64.dll
Normal file
BIN
Toolbox/tegra_swizzle_x64.dll
Normal file
Binary file not shown.
BIN
Toolbox/tegra_swizzle_x86.dll
Normal file
BIN
Toolbox/tegra_swizzle_x86.dll
Normal file
Binary file not shown.
|
@ -37,6 +37,8 @@ after_build:
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\x86"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\x86"
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\ZstdNet.dll"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\ZstdNet.dll"
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\DirectXTexNet.dll"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\DirectXTexNet.dll"
|
||||||
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\tegra_swizzle_x64.dll"
|
||||||
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\tegra_swizzle_x86.dll"
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\DirectXTexNet.xml"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\DirectXTexNet.xml"
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\runtimes"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\runtimes"
|
||||||
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\Version.txt"
|
- 7z a "Toolbox-Latest.zip" "%APPVEYOR_BUILD_FOLDER%\Toolbox\bin\Release\Version.txt"
|
||||||
|
|
Loading…
Reference in a new issue