1
0
mirror of synced 2024-12-01 02:27:22 +01:00
Switch-Toolbox/File_Format_Library/FileFormats/Texture/XTX.cs
2023-06-18 19:20:26 -04:00

714 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Drawing;
using System.Linq;
using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.IO;
using Toolbox.Library.Forms;
using Syroot.NintenTools.NSW.Bntx.GFX;
namespace FirstPlugin
{
public class XTX : TreeNodeFile, IFileFormat, IContextMenuNode, ITextureContainer
{
public FileType FileType { get; set; } = FileType.Image;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "XTX" };
public string[] Extension { get; set; } = new string[] { "*.xtx", "*.z" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(Stream stream)
{
using (var reader = new FileReader(stream, true))
{
return reader.CheckSignature(4, "DFvN");
}
}
public bool DisplayIcons => false; //Astc decoding is slow and the UI has loading issues atm
public List<STGenericTexture> TextureList
{
get
{
List<STGenericTexture> textures = new List<STGenericTexture>();
foreach (STGenericTexture node in Nodes)
textures.Add(node);
return textures;
}
set { }
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
public void Load(System.IO.Stream stream)
{
CanSave = true;
Text = FileName;
LoadFile(stream);
for (int i = 0; i < TextureInfos.Count; i++) {
string name = Path.GetFileNameWithoutExtension(FileName);
TextureInfos[i].Text = TextureInfos.Count == 1 ? name : $"{name}_image{i}";
}
}
public ToolStripItem[] GetContextMenuItems()
{
return new ToolStripItem[]
{
new ToolStripMenuItem("Save", null, Save, Keys.Control | Keys.S),
new ToolStripMenuItem("Export All", null, ExportAllAction, Keys.Control | Keys.E),
};
}
private void Save(object sender, EventArgs args)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.DefaultExt = "xtx";
sfd.Filter = "Supported Formats|*.xtx;";
sfd.FileName = FileName;
if (sfd.ShowDialog() == DialogResult.OK)
{
STFileSaver.SaveFileFormat(this, sfd.FileName);
}
}
protected void ExportAllAction(object sender, EventArgs e)
{
if (Nodes.Count <= 0)
return;
string formats = FileFilters.XTX;
string[] forms = formats.Split('|');
List<string> Formats = new List<string>();
for (int i = 0; i < forms.Length; i++)
{
if (i > 1 || i == (forms.Length - 1)) //Skip lines with all extensions
{
if (!forms[i].StartsWith("*"))
Formats.Add(forms[i]);
}
}
FolderSelectDialog sfd = new FolderSelectDialog();
if (sfd.ShowDialog() == DialogResult.OK)
{
string folderPath = sfd.SelectedPath;
BatchFormatExport form = new BatchFormatExport(Formats);
if (form.ShowDialog() == DialogResult.OK)
{
string extension = form.GetSelectedExtension();
extension.Replace(" ", string.Empty);
foreach (STGenericTexture node in Nodes)
{
((STGenericTexture)node).Export($"{folderPath}\\{node.Text}{extension}");
}
}
}
}
public void Unload()
{
}
public override void OnAfterAdded()
{
if (Nodes.Count > 0 && this.TreeView != null)
this.TreeView.SelectedNode = Nodes[0];
}
public void Save(System.IO.Stream stream)
{
SaveFile(new FileWriter(stream, true));
}
public enum XTXImageFormat : uint
{
NVN_FORMAT_RGBA8 = 0x00000025,
NVN_FORMAT_RGBA8_SRGB = 0x00000038,
NVN_FORMAT_RGB10A2 = 0x0000003d,
NVN_FORMAT_RGB565 = 0x0000003c,
NVN_FORMAT_RGB5A1 = 0x0000003b,
NVN_FORMAT_RGBA4 = 0x00000039,
NVN_FORMAT_R8 = 0x00000001,
NVN_FORMAT_RG8 = 0x0000000d,
DXT1 = 0x00000042,
DXT3 = 0x00000043,
DXT5 = 0x00000044,
BC4U = 0x00000049,
BC4S = 0x0000004a,
BC5U = 0x0000004b,
BC5S = 0x0000004c,
BC6U = 0x00000050,
BC7U = 0x0000004d,
BGRA8 = 0x0000006d,
//Same order as this https://github.com/aboood40091/BNTX-Editor/blob/master/globals.py
//However SRGB goes after unorm
ASTC_4x4_UNORM = 0x00000079,
ASTC_5x4_UNORM = 0x0000007A,
ASTC_5x5_UNORM = 0x0000007B,
ASTC_6x5_UNORM = 0x0000007C,
ASTC_6x6_UNORM = 0x0000007D,
ASTC_8x5_UNORM = 0x0000007E,
ASTC_8x6_UNORM = 0x0000007F,
ASTC_8x8_UNORM = 0x00000080,
ASTC_10x5_UNORM = 0x00000081,
ASTC_10x6_UNORM = 0x00000082,
ASTC_10x8_UNORM = 0x00000083,
ASTC_10x10_UNORM = 0x00000084,
ASTC_12x10_UNORM = 0x00000085,
ASTC_12x12_UNORM = 0x00000086,
ASTC_4x4_SRGB = 0x00000087,
ASTC_5x4_SRGB = 0x00000088,
ASTC_5x5_SRGB = 0x00000089,
ASTC_6x5_SRGB = 0x0000008A,
ASTC_6x6_SRGB = 0x0000008B,
ASTC_8x5_SRGB = 0x0000008C,
ASTC_8x6_SRGB = 0x0000008D,
ASTC_8x8_SRGB = 0x0000008E,
ASTC_10x5_SRGB = 0x0000008F,
ASTC_10x6_SRGB = 0x00000090,
ASTC_10x8_SRGB = 0x00000091,
ASTC_10x10_SRGB = 0x00000092,
ASTC_12x10_SRGB = 0x00000093,
ASTC_12x12_SRGB = 0x00000094,
};
public uint HeaderSize { get; set; }
public uint MajorVersion { get; set; }
public uint MinorVersion { get; set; }
public List<BlockHeader> Blocks { get; set; }
public List<TextureInfo> TextureInfos { get; set; }
public List<byte[]> TextureBlocks { get; set; }
private const int texHeadBlkType = 2;
private const int dataBlkType = 3;
public void LoadFile(Stream data)
{
Blocks = new List<BlockHeader>();
TextureInfos = new List<TextureInfo>();
TextureBlocks = new List<byte[]>();
FileReader reader = new FileReader(data);
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "DFvN")
throw new Exception($"Invalid signature {Signature}! Expected DFvN.");
HeaderSize = reader.ReadUInt32();
MajorVersion = reader.ReadUInt32();
MinorVersion = reader.ReadUInt32();
uint TextureBlockType = 2;
uint DataBlockType = 3;
reader.Seek(HeaderSize, SeekOrigin.Begin);
bool blockB = false;
bool blockC = false;
uint ImageInfo = 0;
uint images = 0;
while (reader.Position < reader.BaseStream.Length)
{
BlockHeader blockHeader = new BlockHeader();
blockHeader.Read(reader);
Blocks.Add(blockHeader);
if ((uint)blockHeader.BlockType == TextureBlockType)
{
ImageInfo += 1;
blockB = true;
TextureInfo textureInfo = new TextureInfo();
textureInfo.Read(new FileReader(blockHeader.Data));
textureInfo.Text = "Texture " + ImageInfo;
TextureInfos.Add(textureInfo);
}
if ((uint)blockHeader.BlockType == DataBlockType)
{
images += 1;
blockC = true;
TextureBlocks.Add(blockHeader.Data);
}
}
int curTex = 0;
foreach (var tex in TextureInfos) {
tex.ImageData = TextureBlocks[curTex++];
Nodes.Add(tex);
}
}
public void SaveFile(FileWriter writer)
{
int Alignment = 512;
uint TextureInfoType = 2;
uint TextureBlockType = 3;
SetupBlockSaving(TextureBlockType);
writer.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
writer.WriteSignature("DFvN");
writer.Write(HeaderSize);
writer.Write(MajorVersion);
writer.Write(MinorVersion);
writer.Seek(HeaderSize, SeekOrigin.Begin);
int curTexBlock = 0;
int curTexImage = 0;
foreach (var block in Blocks)
{
if (block.BlockType == TextureBlockType)
{
block.Data = TextureInfos[curTexImage].ImageData;
block.WriteHeader(writer);
block.WriteBlock(writer, 512);
curTexImage++;
}
else if (block.BlockType == TextureInfoType)
{
block.Data = TextureInfos[curTexImage].Write();
block.WriteHeader(writer);
block.WriteBlock(writer);
}
else
{
block.WriteHeader(writer);
block.WriteBlock(writer);
}
}
writer.Close();
writer.Dispose();
}
private void SetupBlockSaving(uint TextureBlockType)
{
int curTex = 0;
foreach (var block in Blocks)
{
if (block.BlockType == TextureBlockType)
{
block.Data = TextureInfos[curTex].ImageData;
}
}
}
public class BlockHeader
{
public uint BlockSize { get; set; }
public UInt64 DataSize { get; set; }
public uint BlockType { get; set; }
public uint GlobalBlockIndex { get; set; }
public uint IncBlockTypeIndex { get; set; }
public long DataOffset;
public byte[] Data;
public void Read(FileReader reader)
{
var pos = reader.Position;
string Signature = reader.ReadString(4, Encoding.ASCII);
if (Signature != "HBvN")
throw new Exception($"Invalid signature {Signature}! Expected HBvN.");
BlockSize = reader.ReadUInt32();
DataSize = reader.ReadUInt64();
DataOffset = reader.ReadInt64();
BlockType = reader.ReadUInt32();
GlobalBlockIndex = reader.ReadUInt32();
IncBlockTypeIndex = reader.ReadUInt32();
reader.Seek((int)pos + DataOffset, SeekOrigin.Begin);
Data = reader.ReadBytes((int)DataSize);
}
private long headerPos = 0;
public void WriteHeader(FileWriter writer)
{
headerPos = writer.Position;
writer.WriteSignature("HBvN");
writer.Write(BlockSize);
writer.Write((ulong)Data.Length);
writer.Write((ulong)DataOffset);
writer.Write(BlockType);
writer.Write(GlobalBlockIndex);
writer.Write(IncBlockTypeIndex);
}
public void WriteBlock(FileWriter writer, int DataAlignment = 0)
{
//From the block size goto where the data will start
writer.Seek((int)(BlockSize + headerPos), SeekOrigin.Begin);
//Add alignment if necessary
if (DataAlignment != 0)
writer.Align(DataAlignment);
var blockPos = writer.Position;
//Satisfy the offset
using (writer.TemporarySeek(headerPos + 16, SeekOrigin.Begin))
{
//Offset starts from the block header
writer.Write(blockPos - headerPos);
}
writer.Write(Data);
//Set the total size
uint TotalDataSize =(uint)(writer.Position - blockPos);
using (writer.TemporarySeek(headerPos + 8, SeekOrigin.Begin)) {
writer.Write((ulong)TotalDataSize);
}
}
}
public class TextureInfo : STGenericTexture
{
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.BC1_UNORM,
TEX_FORMAT.BC2_UNORM,
TEX_FORMAT.BC3_UNORM,
TEX_FORMAT.BC4_UNORM,
TEX_FORMAT.BC5_UNORM,
TEX_FORMAT.R8_UNORM,
TEX_FORMAT.R8G8_UNORM,
TEX_FORMAT.R8G8_UNORM,
TEX_FORMAT.R10G10B10A2_UNORM,
TEX_FORMAT.B5G6R5_UNORM,
TEX_FORMAT.B5G5R5A1_UNORM,
TEX_FORMAT.B4G4R4A4_UNORM,
TEX_FORMAT.R8G8B8A8_UNORM,
TEX_FORMAT.R8G8B8A8_UNORM_SRGB,
};
}
}
public override bool CanEdit { get; set; } = true;
public UInt64 DataSize { get; set; }
public uint Alignment { get; set; }
public uint Target { get; set; }
public XTXImageFormat XTXFormat { get; set; }
public uint SliceSize { get; set; }
public uint[] MipOffsets { get; set; }
public byte[] ImageData;
public uint TextureLayout1;
public uint TextureLayout2;
public uint BlockHeightLog2;
public uint Boolean;
public override string ExportFilter => FileFilters.XTX;
public override string ReplaceFilter => FileFilters.XTX;
public TextureInfo()
{
CanExport = true;
CanReplace = true;
}
public void Read(FileReader reader)
{
DataSize = reader.ReadUInt64();
Alignment = reader.ReadUInt32();
Width = reader.ReadUInt32();
Height = reader.ReadUInt32();
Depth = reader.ReadUInt32();
Target = reader.ReadUInt32();
XTXFormat = reader.ReadEnum<XTXImageFormat>(true);
MipCount = reader.ReadUInt32();
SliceSize = reader.ReadUInt32();
MipOffsets = reader.ReadUInt32s(17);
TextureLayout1 = reader.ReadUInt32();
TextureLayout2 = reader.ReadUInt32();
Boolean = reader.ReadUInt32();
BlockHeightLog2 = TextureLayout1 & 7;
Format = ConvertFormat(XTXFormat);
ArrayCount = (uint)(DataSize / SliceSize);
}
public byte[] Write()
{
TextureLayout1 = (uint)BlockHeightLog2;
MemoryStream mem = new MemoryStream();
FileWriter writer = new FileWriter(mem);
writer.Write((ulong)DataSize);
writer.Write(Alignment);
writer.Write(Width);
writer.Write(Height);
writer.Write(Depth);
writer.Write(Target);
writer.Write(XTXFormat, true);
writer.Write(MipCount);
writer.Write(SliceSize);
writer.Write(MipOffsets);
writer.Write(TextureLayout1);
writer.Write(TextureLayout2);
writer.Write(Boolean);
writer.Close();
writer.Dispose();
return mem.ToArray();
}
public override void Export(string FileName)
{
Export(FileName);
}
public override void Replace(string FileName)
{
var tex = new TextureData();
tex.Replace(FileName, MipCount, 0, Format);
//If it's null, the operation is cancelled
if (tex.Texture == null)
return;
var surfacesNew = tex.GetSurfaces();
var surfaces = GetSurfaces();
ImageData = tex.Texture.TextureData[0][0];
Width = tex.Texture.Width;
Height = tex.Texture.Height;
MipCount = tex.Texture.MipCount;
TextureLayout1 = tex.Texture.textureLayout;
TextureLayout2 = tex.Texture.textureLayout2;
BlockHeightLog2 = tex.Texture.BlockHeightLog2;
Format = tex.Format;
XTXFormat = ConvertFromGenericFormat(tex.Format);
uint[] mips = TegraX1Swizzle.GenerateMipSizes(tex.Format, tex.Width, tex.Height, tex.Depth, tex.ArrayCount, tex.MipCount)[0];
MipOffsets = new uint[17];
for (int i = 0; i < mips.Length; i++)
MipOffsets[i] = mips[i];
surfacesNew.Clear();
surfaces.Clear();
UpdateEditor();
}
public override void OnClick(TreeView treeview)
{
UpdateEditor();
}
public void UpdateEditor()
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
}
editor.Text = Text;
editor.LoadImage(this);
editor.LoadProperties(GenericProperties);
}
public static XTXImageFormat ConvertFromGenericFormat(TEX_FORMAT Format)
{
switch (Format)
{
case TEX_FORMAT.BC1_UNORM: return XTXImageFormat.DXT1;
case TEX_FORMAT.BC2_UNORM: return XTXImageFormat.DXT3;
case TEX_FORMAT.BC3_UNORM: return XTXImageFormat.DXT5;
case TEX_FORMAT.BC4_UNORM: return XTXImageFormat.BC4U;
case TEX_FORMAT.BC4_SNORM: return XTXImageFormat.BC4S;
case TEX_FORMAT.BC5_UNORM: return XTXImageFormat.BC5U;
case TEX_FORMAT.BC7_UNORM: return XTXImageFormat.BC7U;
case TEX_FORMAT.BC6H_UF16: return XTXImageFormat.BC6U;
case TEX_FORMAT.R8_UNORM: return XTXImageFormat.NVN_FORMAT_R8;
case TEX_FORMAT.R8G8_UNORM: return XTXImageFormat.NVN_FORMAT_RG8;
case TEX_FORMAT.R10G10B10A2_UNORM: return XTXImageFormat.NVN_FORMAT_RGB10A2;
case TEX_FORMAT.B5G6R5_UNORM: return XTXImageFormat.NVN_FORMAT_RGB565;
case TEX_FORMAT.B5G5R5A1_UNORM: return XTXImageFormat.NVN_FORMAT_RGB5A1;
case TEX_FORMAT.B4G4R4A4_UNORM: return XTXImageFormat.NVN_FORMAT_RGBA4;
case TEX_FORMAT.R8G8B8A8_UNORM: return XTXImageFormat.NVN_FORMAT_RGBA8;
case TEX_FORMAT.R8G8B8A8_UNORM_SRGB: return XTXImageFormat.NVN_FORMAT_RGBA8_SRGB;
case TEX_FORMAT.ASTC_4x4_UNORM: return XTXImageFormat.ASTC_4x4_UNORM;
case TEX_FORMAT.ASTC_5x4_UNORM: return XTXImageFormat.ASTC_5x4_UNORM;
case TEX_FORMAT.ASTC_5x5_UNORM: return XTXImageFormat.ASTC_5x5_UNORM;
case TEX_FORMAT.ASTC_6x5_UNORM: return XTXImageFormat.ASTC_6x5_UNORM;
case TEX_FORMAT.ASTC_6x6_UNORM: return XTXImageFormat.ASTC_6x6_UNORM;
case TEX_FORMAT.ASTC_8x5_UNORM: return XTXImageFormat.ASTC_8x5_UNORM;
case TEX_FORMAT.ASTC_8x6_UNORM: return XTXImageFormat.ASTC_8x6_UNORM;
case TEX_FORMAT.ASTC_8x8_UNORM: return XTXImageFormat.ASTC_8x8_UNORM;
case TEX_FORMAT.ASTC_10x5_UNORM: return XTXImageFormat.ASTC_10x5_UNORM;
case TEX_FORMAT.ASTC_10x6_UNORM: return XTXImageFormat.ASTC_10x6_UNORM;
case TEX_FORMAT.ASTC_10x10_UNORM: return XTXImageFormat.ASTC_10x10_UNORM;
case TEX_FORMAT.ASTC_12x10_UNORM: return XTXImageFormat.ASTC_12x10_UNORM;
case TEX_FORMAT.ASTC_12x12_UNORM: return XTXImageFormat.ASTC_12x12_UNORM;
case TEX_FORMAT.ASTC_4x4_SRGB: return XTXImageFormat.ASTC_4x4_SRGB;
case TEX_FORMAT.ASTC_5x4_SRGB: return XTXImageFormat.ASTC_5x4_SRGB;
case TEX_FORMAT.ASTC_5x5_SRGB: return XTXImageFormat.ASTC_5x5_SRGB;
case TEX_FORMAT.ASTC_6x5_SRGB: return XTXImageFormat.ASTC_6x5_SRGB;
case TEX_FORMAT.ASTC_6x6_SRGB: return XTXImageFormat.ASTC_6x6_SRGB;
case TEX_FORMAT.ASTC_8x5_SRGB: return XTXImageFormat.ASTC_8x5_SRGB;
case TEX_FORMAT.ASTC_8x6_SRGB: return XTXImageFormat.ASTC_8x6_SRGB;
case TEX_FORMAT.ASTC_8x8_SRGB: return XTXImageFormat.ASTC_8x8_SRGB;
case TEX_FORMAT.ASTC_10x5_SRGB: return XTXImageFormat.ASTC_10x5_SRGB;
case TEX_FORMAT.ASTC_10x6_SRGB: return XTXImageFormat.ASTC_10x6_SRGB;
case TEX_FORMAT.ASTC_10x10_SRGB: return XTXImageFormat.ASTC_10x10_SRGB;
case TEX_FORMAT.ASTC_12x10_SRGB: return XTXImageFormat.ASTC_12x10_SRGB;
case TEX_FORMAT.ASTC_12x12_SRGB: return XTXImageFormat.ASTC_12x12_SRGB;
default:
throw new Exception($"Cannot convert format {Format}");
}
}
public static TEX_FORMAT ConvertFormat(uint Format)
{
return ConvertFormat((XTXImageFormat)Format);
}
public static TEX_FORMAT ConvertFormat(XTXImageFormat Format)
{
switch (Format)
{
case XTXImageFormat.BGRA8: return TEX_FORMAT.B8G8R8A8_UNORM;
case XTXImageFormat.DXT1: return TEX_FORMAT.BC1_UNORM;
case XTXImageFormat.DXT3: return TEX_FORMAT.BC2_UNORM;
case XTXImageFormat.DXT5: return TEX_FORMAT.BC3_UNORM;
case XTXImageFormat.BC4U: return TEX_FORMAT.BC4_UNORM;
case XTXImageFormat.BC4S: return TEX_FORMAT.BC4_SNORM;
case XTXImageFormat.BC5U: return TEX_FORMAT.BC5_UNORM;
case XTXImageFormat.BC5S: return TEX_FORMAT.BC5_SNORM;
case XTXImageFormat.BC7U: return TEX_FORMAT.BC7_UNORM;
case XTXImageFormat.BC6U: return TEX_FORMAT.BC6H_UF16;
case XTXImageFormat.NVN_FORMAT_R8: return TEX_FORMAT.R8_UNORM;
case XTXImageFormat.NVN_FORMAT_RG8: return TEX_FORMAT.R8G8_UNORM;
case XTXImageFormat.NVN_FORMAT_RGB10A2: return TEX_FORMAT.R10G10B10A2_UNORM;
case XTXImageFormat.NVN_FORMAT_RGB565: return TEX_FORMAT.B5G6R5_UNORM;
case XTXImageFormat.NVN_FORMAT_RGB5A1: return TEX_FORMAT.B5G5R5A1_UNORM;
case XTXImageFormat.NVN_FORMAT_RGBA4: return TEX_FORMAT.B4G4R4A4_UNORM;
case XTXImageFormat.NVN_FORMAT_RGBA8: return TEX_FORMAT.R8G8B8A8_UNORM;
case XTXImageFormat.NVN_FORMAT_RGBA8_SRGB: return TEX_FORMAT.R8G8B8A8_UNORM_SRGB;
case XTXImageFormat.ASTC_4x4_UNORM: return TEX_FORMAT.ASTC_4x4_UNORM;
case XTXImageFormat.ASTC_5x4_UNORM: return TEX_FORMAT.ASTC_5x4_UNORM;
case XTXImageFormat.ASTC_5x5_UNORM: return TEX_FORMAT.ASTC_5x5_UNORM;
case XTXImageFormat.ASTC_6x5_UNORM: return TEX_FORMAT.ASTC_6x5_UNORM;
case XTXImageFormat.ASTC_6x6_UNORM: return TEX_FORMAT.ASTC_6x6_UNORM;
case XTXImageFormat.ASTC_8x5_UNORM: return TEX_FORMAT.ASTC_8x5_UNORM;
case XTXImageFormat.ASTC_8x6_UNORM: return TEX_FORMAT.ASTC_8x6_UNORM;
case XTXImageFormat.ASTC_8x8_UNORM: return TEX_FORMAT.ASTC_8x8_UNORM;
case XTXImageFormat.ASTC_10x5_UNORM: return TEX_FORMAT.ASTC_10x5_UNORM;
case XTXImageFormat.ASTC_10x6_UNORM: return TEX_FORMAT.ASTC_10x6_UNORM;
case XTXImageFormat.ASTC_10x10_UNORM: return TEX_FORMAT.ASTC_10x10_UNORM;
case XTXImageFormat.ASTC_12x10_UNORM: return TEX_FORMAT.ASTC_12x10_UNORM;
case XTXImageFormat.ASTC_12x12_UNORM: return TEX_FORMAT.ASTC_12x12_UNORM;
case XTXImageFormat.ASTC_4x4_SRGB: return TEX_FORMAT.ASTC_4x4_SRGB;
case XTXImageFormat.ASTC_5x4_SRGB: return TEX_FORMAT.ASTC_5x4_SRGB;
case XTXImageFormat.ASTC_5x5_SRGB: return TEX_FORMAT.ASTC_5x5_SRGB;
case XTXImageFormat.ASTC_6x5_SRGB: return TEX_FORMAT.ASTC_6x5_SRGB;
case XTXImageFormat.ASTC_6x6_SRGB: return TEX_FORMAT.ASTC_6x6_SRGB;
case XTXImageFormat.ASTC_8x5_SRGB: return TEX_FORMAT.ASTC_8x5_SRGB;
case XTXImageFormat.ASTC_8x6_SRGB: return TEX_FORMAT.ASTC_8x6_SRGB;
case XTXImageFormat.ASTC_8x8_SRGB: return TEX_FORMAT.ASTC_8x8_SRGB;
case XTXImageFormat.ASTC_10x5_SRGB: return TEX_FORMAT.ASTC_10x5_SRGB;
case XTXImageFormat.ASTC_10x6_SRGB: return TEX_FORMAT.ASTC_10x6_SRGB;
case XTXImageFormat.ASTC_10x10_SRGB: return TEX_FORMAT.ASTC_10x10_SRGB;
case XTXImageFormat.ASTC_12x10_SRGB: return TEX_FORMAT.ASTC_12x10_SRGB;
case XTXImageFormat.ASTC_12x12_SRGB: return TEX_FORMAT.ASTC_12x12_SRGB;
default:
throw new Exception($"Cannot convert format {Format}");
}
}
public override void SetImageData(Bitmap bitmap, int ArrayLevel)
{
if (bitmap == null)
return; //Image is likely disposed and not needed to be applied
MipCount = GenerateMipCount(bitmap.Width, bitmap.Height);
XTXFormat = ConvertFromGenericFormat(Format);
var tex = new Syroot.NintenTools.NSW.Bntx.Texture();
tex.Height = (uint)bitmap.Height;
tex.Width = (uint)bitmap.Width;
tex.Format = TextureData.GenericToBntxSurfaceFormat(Format);
tex.Name = Text;
tex.Path = "";
tex.TextureData = new List<List<byte[]>>();
STChannelType[] channels = SetChannelsByFormat(Format);
tex.sparseBinding = 0; //false
tex.sparseResidency = 0; //false
tex.Flags = 0;
tex.Swizzle = 0;
tex.textureLayout = 0;
tex.Regs = new uint[0];
tex.AccessFlags = AccessFlags.Texture;
tex.ArrayLength = (uint)ArrayLevel;
tex.MipCount = MipCount;
tex.Depth = Depth;
tex.Dim = Syroot.NintenTools.NSW.Bntx.GFX.Dim.Dim2D;
tex.TileMode = Syroot.NintenTools.NSW.Bntx.GFX.TileMode.Default;
tex.textureLayout2 = 0x010007;
tex.SurfaceDim = Syroot.NintenTools.NSW.Bntx.GFX.SurfaceDim.Dim2D;
tex.SampleCount = 1;
tex.Pitch = 32;
tex.MipOffsets = new long[tex.MipCount];
var mipmaps = TextureImporterSettings.SwizzleSurfaceMipMaps(tex,
GenerateMipsAndCompress(bitmap, MipCount, Format), MipCount);
ImageData = Utils.CombineByteArray(mipmaps.ToArray());
}
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
{
return TegraX1Swizzle.GetImageData(this, ImageData, ArrayLevel, MipLevel, DepthLevel, BlockHeightLog2, (int)Target);
}
}
}
}