Switch-Toolbox/File_Format_Library/FileFormats/Texture/TPL.cs

412 lines
14 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Toolbox;
using System.Windows.Forms;
using Toolbox.Library;
using Toolbox.Library.Forms;
using Toolbox.Library.IO;
namespace FirstPlugin
{
2019-08-04 17:31:16 +00:00
public class TPL : TreeNodeFile, IFileFormat, ITextureIconLoader
{
public FileType FileType { get; set; } = FileType.Image;
public bool CanSave { get; set; }
public string[] Description { get; set; } = new string[] { "TPL" };
public string[] Extension { get; set; } = new string[] { "*.tpl" };
public string FileName { get; set; }
public string FilePath { get; set; }
public IFileInfo IFileInfo { get; set; }
public bool Identify(System.IO.Stream stream)
{
using (var reader = new FileReader(stream, true))
{
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
2019-08-04 17:31:16 +00:00
return reader.ReadUInt32() == 0x0020AF30 || Utils.GetExtension(FileName) == ".tpl";
}
}
public Type[] Types
{
get
{
List<Type> types = new List<Type>();
return types.ToArray();
}
}
2019-08-04 17:31:16 +00:00
public List<STGenericTexture> IconTextureList
{
get
{
List<STGenericTexture> textures = new List<STGenericTexture>();
foreach (STGenericTexture node in Nodes)
textures.Add(node);
return textures;
}
set { }
}
2019-08-04 16:21:28 +00:00
public List<ImageHeader> ImageHeaders = new List<ImageHeader>();
public List<PaletteHeader> PaletteHeaders = new List<PaletteHeader>();
public void Load(System.IO.Stream stream)
{
Text = FileName;
2019-08-04 16:21:28 +00:00
using (var reader = new FileReader(stream))
{
2019-08-04 17:31:16 +00:00
reader.SetByteOrder(true);
2019-08-04 16:21:28 +00:00
uint Identifier = reader.ReadUInt32();
2019-08-04 17:31:16 +00:00
//TPL has multiple versions i assume? Some games like F Zero use a custom one so try that
if (Identifier != 0x0020AF30)
2019-08-04 16:21:28 +00:00
{
2019-08-04 17:31:16 +00:00
reader.Position = 0;
uint ImageCount = reader.ReadUInt32();
Console.WriteLine("ImageCount" + ImageCount);
for (int i = 0; i < ImageCount; i++)
{
reader.SeekBegin(4 + (i * 0x10));
uint format = reader.ReadUInt32();
uint offset = reader.ReadUInt32();
uint width = reader.ReadUInt16();
uint height = reader.ReadUInt16();
uint mipCount = reader.ReadUInt16();
ushort unknown = reader.ReadUInt16();
if (format == 256)
break;
Console.WriteLine(offset);
Console.WriteLine(format);
2019-08-04 16:21:28 +00:00
2019-08-04 17:31:16 +00:00
var GXFormat = (Decode_Gamecube.TextureFormats)format;
2019-08-04 16:21:28 +00:00
2019-08-04 17:31:16 +00:00
//Now create a wrapper
var texWrapper = new TplTextureWrapper();
texWrapper.Text = $"Texture {i}";
texWrapper.ImageKey = "Texture";
texWrapper.SelectedImageKey = "Texture";
texWrapper.Format = Decode_Gamecube.ToGenericFormat(GXFormat);
texWrapper.Width = width;
texWrapper.Height = height;
texWrapper.MipCount = mipCount;
texWrapper.ImageData = reader.getSection(offset, (uint)Decode_Gamecube.GetDataSize(GXFormat, (int)width, (int)height));
texWrapper.PlatformSwizzle = PlatformSwizzle.Platform_Gamecube;
Nodes.Add(texWrapper);
}
}
else
{
uint ImageCount = reader.ReadUInt32();
uint ImageOffsetTable = reader.ReadUInt32();
for (int i = 0; i < ImageCount; i++)
2019-08-04 16:21:28 +00:00
{
2019-08-04 17:31:16 +00:00
reader.SeekBegin(ImageOffsetTable + (i * 8));
uint ImageHeaderOffset = reader.ReadUInt32();
uint PaletteHeaderOffset = reader.ReadUInt32();
2019-08-04 16:21:28 +00:00
reader.SeekBegin(ImageHeaderOffset);
var image = new ImageHeader();
image.Read(reader);
ImageHeaders.Add(image);
2019-08-04 17:31:16 +00:00
2019-08-04 17:45:11 +00:00
var GXFormat = (Decode_Gamecube.TextureFormats)image.Format;
Console.WriteLine($"ImageOffset {image.ImageOffset}");
//Now create a wrapper
var texWrapper = new TplTextureWrapper();
texWrapper.Text = $"Texture {i}";
texWrapper.ImageKey = "Texture";
texWrapper.SelectedImageKey = "Texture";
texWrapper.Format = Decode_Gamecube.ToGenericFormat(GXFormat);
texWrapper.Width = image.Width;
texWrapper.Height = image.Height;
texWrapper.MipCount = 1;
texWrapper.PlatformSwizzle = PlatformSwizzle.Platform_Gamecube;
texWrapper.ImageData = reader.getSection(image.ImageOffset,
(uint)Decode_Gamecube.GetDataSize(GXFormat, (int)image.Width, (int)image.Height));
2019-08-04 17:31:16 +00:00
//Palette is sometimes unused to check
if (PaletteHeaderOffset != 0)
{
reader.SeekBegin(PaletteHeaderOffset);
var palette = new PaletteHeader();
palette.Read(reader);
PaletteHeaders.Add(palette);
2019-08-04 17:45:11 +00:00
var GXPaletteFormat = (Decode_Gamecube.PaletteFormats)image.Format;
2019-08-04 17:31:16 +00:00
2019-08-04 17:45:11 +00:00
texWrapper.SetPaletteData(palette.Data, Decode_Gamecube.ToGenericPaletteFormat(GXPaletteFormat));
}
Nodes.Add(texWrapper);
2019-08-04 16:21:28 +00:00
}
2019-08-04 17:31:16 +00:00
}
}
}
public class TplTextureWrapper : STGenericTexture
{
public byte[] ImageData { get; set; }
2019-08-04 16:21:28 +00:00
2019-08-04 17:31:16 +00:00
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
2019-08-04 16:21:28 +00:00
{
2019-08-04 17:31:16 +00:00
TEX_FORMAT.I4,
TEX_FORMAT.I8,
TEX_FORMAT.IA4,
TEX_FORMAT.IA8,
TEX_FORMAT.RGB565,
TEX_FORMAT.RGB5A3,
TEX_FORMAT.RGBA32,
TEX_FORMAT.C4,
TEX_FORMAT.C8,
TEX_FORMAT.C14X2,
TEX_FORMAT.CMPR,
};
}
}
public override bool CanEdit { get; set; } = false;
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
}
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
return ImageData;
}
public override void OnClick(TreeView treeView)
{
ImageEditorBase editor = (ImageEditorBase)LibraryGUI.GetActiveContent(typeof(ImageEditorBase));
if (editor == null)
{
editor = new ImageEditorBase();
editor.Dock = DockStyle.Fill;
LibraryGUI.LoadEditor(editor);
2019-08-04 16:21:28 +00:00
}
2019-08-04 17:31:16 +00:00
editor.LoadProperties(GenericProperties);
editor.LoadImage(this);
2019-08-04 16:21:28 +00:00
}
}
2019-08-04 16:21:28 +00:00
public class PaletteHeader
{
public ushort EntryCount { get; set; }
public byte Unpacked { get; set; }
public uint PaletteFormat { get; set; }
public uint PaletteDataOffset { get; set; }
2019-08-04 17:45:11 +00:00
public byte[] Data;
2019-08-04 16:21:28 +00:00
public void Read(FileReader reader)
{
EntryCount = reader.ReadUInt16();
Unpacked = reader.ReadByte();
PaletteFormat = reader.ReadUInt32();
PaletteDataOffset = reader.ReadUInt32();
2019-08-04 17:45:11 +00:00
using (reader.TemporarySeek(PaletteDataOffset, SeekOrigin.Begin))
{
Data = reader.ReadBytes(EntryCount * 2);
}
2019-08-04 16:21:28 +00:00
}
public void Write(FileWriter writer)
{
writer.Write(EntryCount);
writer.Write(Unpacked);
writer.Write(PaletteFormat);
writer.Write(PaletteDataOffset);
}
}
public class ImageHeader
{
public ushort Width { get; set; }
public ushort Height { get; set; }
public uint Format { get; set; }
public uint ImageOffset { get; set; }
public uint WrapS { get; set; }
public uint WrapT { get; set; }
public uint MinFilter { get; set; }
public uint MagFilter { get; set; }
public float LODBias { get; set; }
public bool EdgeLODEnable { get; set; }
public byte MinLOD { get; set; }
public byte MaxLOD { get; set; }
public byte Unpacked { get; set; }
public void Read(FileReader reader)
{
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
Format = reader.ReadUInt32();
ImageOffset = reader.ReadUInt32();
WrapS = reader.ReadUInt32();
WrapT = reader.ReadUInt32();
MinFilter = reader.ReadUInt32();
MagFilter = reader.ReadUInt32();
LODBias = reader.ReadSingle();
EdgeLODEnable = reader.ReadBoolean();
MinLOD = reader.ReadByte();
MaxLOD = reader.ReadByte();
Unpacked = reader.ReadByte();
}
public void Write(FileWriter writer)
{
writer.Write(Width);
writer.Write(Height);
writer.Write(Format);
writer.Write(ImageOffset);
writer.Write(WrapS);
writer.Write(WrapT);
writer.Write(MinFilter);
writer.Write(MagFilter);
writer.Write(LODBias);
writer.Write(EdgeLODEnable);
writer.Write(MinLOD);
writer.Write(MaxLOD);
writer.Write(Unpacked);
}
}
public void Unload()
{
}
public byte[] Save()
{
MemoryStream mem = new MemoryStream();
return mem.ToArray();
}
public class TPL_Texture : STGenericTexture
{
private libWiiSharp.TPL ParentTPL;
private int TextureIndex { get; set; }
private TextureProperties properties;
public class TextureProperties
{
private libWiiSharp.TPL ParentTPL;
private int TextureIndex { get; set; }
public libWiiSharp.TPL_TextureFormat TextureFormat
{
get { return ParentTPL.GetTextureFormat(TextureIndex); }
}
public libWiiSharp.TPL_PaletteFormat PaletteFormat
{
get { return ParentTPL.GetPaletteFormat(TextureIndex); }
}
public int Width
{
get { return ParentTPL.GetImageWidth(TextureIndex); }
}
public int Height
{
get { return ParentTPL.GetImageHeight(TextureIndex); }
}
public TextureProperties(libWiiSharp.TPL tpl, int index)
{
ParentTPL = tpl;
TextureIndex = index;
}
}
public TPL_Texture(libWiiSharp.TPL tpl, int index)
{
ParentTPL = tpl;
TextureIndex = index;
Width = tpl.GetImageWidth(index);
Height = tpl.GetImageHeight(index);
MipCount = 1;
Text = $"Image {index}";
Format = TEX_FORMAT.R8G8B8A8_UNORM;
SelectedImageKey = "texture";
ImageKey = "texture";
properties = new TextureProperties(tpl, index);
}
public override bool CanEdit { get; set; } = false;
public override TEX_FORMAT[] SupportedFormats
{
get
{
return new TEX_FORMAT[]
{
TEX_FORMAT.R8G8B8A8_UNORM,
};
}
}
public override void SetImageData(System.Drawing.Bitmap bitmap, int ArrayLevel)
{
}
public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
{
return ImageUtilty.ConvertBgraToRgba(ParentTPL.ExtractTextureByteArray(TextureIndex));
}
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.LoadProperties(properties);
editor.LoadImage(this);
}
}
}
}