Many improvements and new formats.
Add in nutexb file format. While not finished, it can preview and export them. Batch exporting for nuteb (tools menu). Rework GTX code. This is WIP and not finished. Add XTX code. Unifnished atm. Add saving for wii u and include fmat exporting. Proper error handling for assimp and texture swizzling.
This commit is contained in:
parent
b5ba944b69
commit
f51dd17f94
@ -153,6 +153,12 @@ namespace FirstPlugin
|
||||
resFile.SceneAnims.Clear();
|
||||
resFile.ShapeAnims.Clear();
|
||||
resFile.BoneVisibilityAnims.Clear();
|
||||
resFile.ModelDict.Clear();
|
||||
resFile.SkeletalAnimDict.Clear();
|
||||
resFile.MaterialAnimDict.Clear();
|
||||
resFile.SceneAnimDict.Clear();
|
||||
resFile.ShapeAnimDict.Clear();
|
||||
resFile.BoneVisibilityAnimDict.Clear();
|
||||
|
||||
|
||||
int CurMdl = 0;
|
||||
@ -195,39 +201,22 @@ namespace FirstPlugin
|
||||
private void SaveWiiU(MemoryStream mem)
|
||||
{
|
||||
var resFileU = bfres.ResFileNode.resFileU;
|
||||
resFileU.Models.Clear();
|
||||
// resFileU.SkeletalAnims.Clear();
|
||||
// resFileU.SceneAnims.Clear();
|
||||
// resFileU.ShapeAnims.Clear();
|
||||
// resFileU.BoneVisibilityAnims.Clear();
|
||||
// resFileU.Textures.Clear();
|
||||
|
||||
resFileU.Save(mem);
|
||||
|
||||
int CurMdl = 0;
|
||||
foreach (FMDL model in bfres.models)
|
||||
if (EditorRoot.Nodes.ContainsKey("FMDL"))
|
||||
{
|
||||
resFileU.Models[CurMdl].Shapes.Clear();
|
||||
resFileU.Models[CurMdl].VertexBuffers.Clear();
|
||||
resFileU.Models[CurMdl].Materials.Clear();
|
||||
|
||||
int i = 0;
|
||||
var duplicates = model.shapes.GroupBy(c => c.Text).Where(g => g.Skip(1).Any()).SelectMany(c => c);
|
||||
foreach (var shape in duplicates)
|
||||
shape.Text += i++;
|
||||
|
||||
foreach (FSHP shape in model.shapes)
|
||||
{
|
||||
CheckMissingTextures(shape);
|
||||
BfresWiiU.SetShape(shape, shape.ShapeU);
|
||||
|
||||
resFileU.Models[CurMdl].Shapes.Add(shape.Text, shape.ShapeU);
|
||||
resFileU.Models[CurMdl].VertexBuffers.Add(shape.VertexBufferU);
|
||||
shape.ShapeU.VertexBufferIndex = (ushort)(resFileU.Models[CurMdl].VertexBuffers.Count - 1);
|
||||
|
||||
SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
|
||||
}
|
||||
foreach (FMAT mat in model.materials.Values)
|
||||
{
|
||||
BfresWiiU.SetMaterial(mat, mat.MaterialU);
|
||||
resFileU.Models[CurMdl].Materials.Add(mat.Text, mat.MaterialU);
|
||||
}
|
||||
CurMdl++;
|
||||
foreach (FMDL model in EditorRoot.Nodes["FMDL"].Nodes)
|
||||
resFileU.Models.Add(model.Text, BfresWiiU.SetModel(model));
|
||||
}
|
||||
ErrorCheck();
|
||||
resFileU.Save(mem);
|
||||
}
|
||||
|
||||
public static void SetShaderAssignAttributes(FMAT.ShaderAssign shd, FSHP shape)
|
||||
@ -298,6 +287,8 @@ namespace FirstPlugin
|
||||
foreach (FMDL model in bfres.models)
|
||||
{
|
||||
foreach (FSHP shp in model.shapes)
|
||||
{
|
||||
if (!IsWiiU)
|
||||
{
|
||||
Syroot.NintenTools.NSW.Bfres.VertexBuffer vtx = shp.VertexBuffer;
|
||||
Syroot.NintenTools.NSW.Bfres.Material mat = shp.GetMaterial().Material;
|
||||
@ -314,6 +305,28 @@ namespace FirstPlugin
|
||||
MessageBox.Show($"Error! Sampler {mat.SamplerDict.GetKey(att)} is unlinked!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Syroot.NintenTools.Bfres.VertexBuffer vtx = shp.VertexBufferU;
|
||||
Syroot.NintenTools.Bfres.Material mat = shp.GetMaterial().MaterialU;
|
||||
Syroot.NintenTools.Bfres.ShaderAssign shdr = mat.ShaderAssign;
|
||||
|
||||
for (int att = 0; att < vtx.Attributes.Count; att++)
|
||||
{
|
||||
if (!shdr.AttribAssigns.ContainsKey(vtx.Attributes[att].Name))
|
||||
MessageBox.Show($"Error! Attribute {vtx.Attributes[att].Name} is unlinked!");
|
||||
}
|
||||
for (int att = 0; att < mat.TextureRefs.Count; att++)
|
||||
{
|
||||
string samp = "";
|
||||
mat.Samplers.TryGetKey(mat.Samplers[att], out samp);
|
||||
if (!shdr.SamplerAssigns.ContainsKey(samp)) //mat.SamplerDict[att]
|
||||
MessageBox.Show($"Error! Sampler {samp} is unlinked!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// ErrorList errorList = new ErrorList();
|
||||
// errorList.LoadList(Errors);
|
||||
|
@ -100,6 +100,9 @@ namespace Bfres.Structs
|
||||
|
||||
public void SetActiveGame()
|
||||
{
|
||||
Runtime.activeGame = Runtime.ActiveGame.SMO;
|
||||
return;
|
||||
|
||||
string ShaderName = shaderassign.ShaderArchive;
|
||||
string ShaderModel = shaderassign.ShaderModel;
|
||||
|
||||
@ -140,6 +143,9 @@ namespace Bfres.Structs
|
||||
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (BFRES.IsWiiU)
|
||||
MaterialU.Export(sfd.FileName, GetResFileU());
|
||||
else
|
||||
Material.Export(sfd.FileName, GetResFile());
|
||||
}
|
||||
}
|
||||
@ -149,13 +155,21 @@ namespace Bfres.Structs
|
||||
ofd.Filter = "Supported Formats|*.bfmat;";
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (BFRES.IsWiiU)
|
||||
{
|
||||
MaterialU.Import(ofd.FileName, GetResFileU());
|
||||
MaterialU.Name = Text;
|
||||
BfresWiiU.ReadMaterial(this, MaterialU);
|
||||
}
|
||||
else
|
||||
{
|
||||
Material.Import(ofd.FileName);
|
||||
Material.Name = Text;
|
||||
|
||||
BfresSwitch.ReadMaterial(this, Material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, float[]> anims = new Dictionary<string, float[]>();
|
||||
public Dictionary<string, int> Samplers = new Dictionary<string, int>();
|
||||
|
@ -356,13 +356,6 @@ namespace Bfres.Structs
|
||||
//Function addes shapes, vertices and meshes
|
||||
public void AddOjects(string FileName, bool Replace = true)
|
||||
{
|
||||
if (Replace)
|
||||
{
|
||||
shapes.Clear();
|
||||
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
}
|
||||
|
||||
int MatStartIndex = materials.Count;
|
||||
string ext = System.IO.Path.GetExtension(FileName);
|
||||
ext = ext.ToLower();
|
||||
@ -372,6 +365,12 @@ namespace Bfres.Structs
|
||||
case ".bfobj":
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
|
||||
if (Replace)
|
||||
{
|
||||
shapes.Clear();
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
}
|
||||
|
||||
Shape shpS = new Shape();
|
||||
VertexBuffer vertexBuffer = new VertexBuffer();
|
||||
shpS.Import(FileName, vertexBuffer);
|
||||
@ -385,12 +384,17 @@ namespace Bfres.Structs
|
||||
break;
|
||||
case ".bfmdl":
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
|
||||
if (Replace)
|
||||
{
|
||||
shapes.Clear();
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
}
|
||||
|
||||
Model mdl = new Model();
|
||||
mdl.Import(FileName, GetResFile());
|
||||
mdl.Name = Text;
|
||||
shapes.Clear();
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
foreach (Shape shp in mdl.Shapes)
|
||||
{
|
||||
FSHP shape = new FSHP();
|
||||
@ -415,6 +419,12 @@ namespace Bfres.Structs
|
||||
csvsettings.SetModelAttributes(csvModel.objects[0]);
|
||||
if (csvsettings.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (Replace)
|
||||
{
|
||||
shapes.Clear();
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
}
|
||||
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
|
||||
foreach (STGenericObject obj in csvModel.objects)
|
||||
@ -452,13 +462,15 @@ namespace Bfres.Structs
|
||||
return;
|
||||
}
|
||||
BfresModelImportSettings settings = new BfresModelImportSettings();
|
||||
|
||||
if (BFRES.IsWiiU)
|
||||
settings.DisableMaterialEdits();
|
||||
|
||||
settings.SetModelAttributes(assimp.objects[0]);
|
||||
if (settings.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
if (Replace)
|
||||
{
|
||||
shapes.Clear();
|
||||
Nodes["FshpFolder"].Nodes.Clear();
|
||||
}
|
||||
|
||||
Cursor.Current = Cursors.WaitCursor;
|
||||
if (!BFRES.IsWiiU && Replace)
|
||||
{
|
||||
@ -466,18 +478,24 @@ namespace Bfres.Structs
|
||||
Nodes["FmatFolder"].Nodes.Clear();
|
||||
MatStartIndex = 0;
|
||||
}
|
||||
|
||||
if (!BFRES.IsWiiU)
|
||||
{
|
||||
foreach (STGenericMaterial mat in assimp.materials)
|
||||
{
|
||||
FMAT fmat = new FMAT();
|
||||
fmat.Material = new Material();
|
||||
if (settings.ExternalMaterialPath != string.Empty)
|
||||
{
|
||||
if (!BFRES.IsWiiU)
|
||||
{
|
||||
fmat.Material = new Material();
|
||||
fmat.Material.Import(settings.ExternalMaterialPath);
|
||||
fmat.ReadMaterial(fmat.Material);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmat.MaterialU = new ResU.Material();
|
||||
fmat.MaterialU.Import(settings.ExternalMaterialPath, GetResFileU());
|
||||
BfresWiiU.ReadMaterial(fmat, fmat.MaterialU);
|
||||
}
|
||||
}
|
||||
|
||||
fmat.Text = mat.Text;
|
||||
//Setup placeholder textures
|
||||
@ -558,17 +576,26 @@ namespace Bfres.Structs
|
||||
}
|
||||
}
|
||||
}
|
||||
fmat.Material.Name = Text;
|
||||
fmat.SetMaterial(fmat.Material);
|
||||
|
||||
List<string> keyList = new List<string>(materials.Keys);
|
||||
fmat.Text = Utils.RenameDuplicateString(keyList, fmat.Text);
|
||||
|
||||
materials.Add(fmat.Text, fmat);
|
||||
Nodes["FmatFolder"].Nodes.Add(fmat);
|
||||
|
||||
if (BFRES.IsWiiU)
|
||||
{
|
||||
fmat.MaterialU.Name = Text;
|
||||
fmat.SetMaterial(fmat.MaterialU);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmat.Material.Name = Text;
|
||||
fmat.SetMaterial(fmat.Material);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (STGenericObject obj in assimp.objects)
|
||||
{
|
||||
FSHP shape = new FSHP();
|
||||
@ -579,9 +606,6 @@ namespace Bfres.Structs
|
||||
shape.boneIndx = obj.BoneIndex;
|
||||
shape.MaterialIndex = obj.MaterialIndex + MatStartIndex;
|
||||
|
||||
if (BFRES.IsWiiU)
|
||||
shape.MaterialIndex = 0;
|
||||
|
||||
shape.Text = obj.ObjectName;
|
||||
shape.lodMeshes = obj.lodMeshes;
|
||||
shape.CreateNewBoundingBoxes();
|
||||
|
@ -61,8 +61,8 @@ namespace Bfres.Structs
|
||||
public SceneAnim SceneAnim;
|
||||
public FSCN()
|
||||
{
|
||||
ImageKey = "skeletonAnimation";
|
||||
SelectedImageKey = "skeletonAnimation";
|
||||
ImageKey = "sceneAnimation";
|
||||
SelectedImageKey = "sceneAnimation";
|
||||
|
||||
ContextMenu = new ContextMenu();
|
||||
MenuItem export = new MenuItem("Export");
|
||||
@ -81,7 +81,7 @@ namespace Bfres.Structs
|
||||
private void Export(object sender, EventArgs args)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.Filter = "Supported Formats|*.bfska;";
|
||||
sfd.Filter = "Supported Formats|*.bfscn;";
|
||||
sfd.FileName = Text;
|
||||
sfd.DefaultExt = ".bfska";
|
||||
|
||||
@ -93,7 +93,7 @@ namespace Bfres.Structs
|
||||
private void Replace(object sender, EventArgs args)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Filter = "Supported Formats|*.bfska;";
|
||||
ofd.Filter = "Supported Formats|*.bfscn;";
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
@ -109,10 +109,6 @@ namespace Bfres.Structs
|
||||
//If has models
|
||||
if (Nodes.ContainsKey("FMDL"))
|
||||
{
|
||||
if (Nodes["FMDL"].Nodes.ContainsKey("FshpFolder"))
|
||||
{
|
||||
|
||||
}
|
||||
LibraryGUI.Instance.LoadViewport(Viewport.Instance);
|
||||
Viewport.Instance.gL_ControlModern1.MainDrawable = BFRESRender;
|
||||
|
||||
@ -266,9 +262,9 @@ namespace Bfres.Structs
|
||||
if (resFile.MaterialAnims.Count > 0)
|
||||
AddMaterialAnims(resFile);
|
||||
if (resFile.ShapeAnims.Count > 0)
|
||||
Nodes.Add(new FshpaFolder());
|
||||
AddShapeAnims(resFile);
|
||||
if (resFile.BoneVisibilityAnims.Count > 0)
|
||||
Nodes.Add(new FbnvFolder());
|
||||
AddBoneVisAnims(resFile);
|
||||
if (resFile.SceneAnims.Count > 0)
|
||||
AddSceneAnims(resFile);
|
||||
if (resFile.ExternalFiles.Count > 0)
|
||||
@ -276,6 +272,9 @@ namespace Bfres.Structs
|
||||
}
|
||||
private void AddFTEXTextures(ResU.ResFile resFile)
|
||||
{
|
||||
MessageBox.Show("Note! Textures are disabled atm.");
|
||||
return;
|
||||
|
||||
FTEXContainer ftexContainer = new FTEXContainer();
|
||||
Nodes.Add(ftexContainer);
|
||||
foreach (ResU.Texture tex in resFile.Textures.Values)
|
||||
@ -340,5 +339,29 @@ namespace Bfres.Structs
|
||||
fmaaFolder.Nodes.Add(materialAnim);
|
||||
}
|
||||
}
|
||||
private void AddShapeAnims(ResFile resFile)
|
||||
{
|
||||
FshpaFolder fshaFolder = new FshpaFolder();
|
||||
Nodes.Add(fshaFolder);
|
||||
foreach (var fsha in resFile.ShapeAnims)
|
||||
{
|
||||
FSHA shapeAnim = new FSHA();
|
||||
shapeAnim.Text = fsha.Name;
|
||||
shapeAnim.Read(fsha);
|
||||
fshaFolder.Nodes.Add(shapeAnim);
|
||||
}
|
||||
}
|
||||
private void AddBoneVisAnims(ResFile resFile)
|
||||
{
|
||||
FbnvFolder fbnvFolder = new FbnvFolder();
|
||||
Nodes.Add(fbnvFolder);
|
||||
foreach (var fbnv in resFile.BoneVisibilityAnims)
|
||||
{
|
||||
FBNV boneVis = new FBNV();
|
||||
boneVis.Text = fbnv.Name;
|
||||
boneVis.Read(fbnv);
|
||||
fbnvFolder.Nodes.Add(boneVis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,16 @@ namespace FirstPlugin
|
||||
public static Model SetModel(FMDL fmdl)
|
||||
{
|
||||
Model model = new Model();
|
||||
model.Name = fmdl.Text;
|
||||
model.Shapes = new List<Shape>();
|
||||
model.VertexBuffers = new List<VertexBuffer>();
|
||||
model.Materials = new List<Material>();
|
||||
model.UserData = new List<UserData>();
|
||||
model.Skeleton = new Skeleton();
|
||||
model.Skeleton = fmdl.Skeleton.node.Skeleton;
|
||||
model.ShapeDict = new ResDict();
|
||||
model.MaterialDict = new ResDict();
|
||||
model.UserDataDict = new ResDict();
|
||||
|
||||
int i = 0;
|
||||
var duplicates = fmdl.shapes.GroupBy(c => c.Text).Where(g => g.Skip(1).Any()).SelectMany(c => c);
|
||||
@ -33,13 +43,13 @@ namespace FirstPlugin
|
||||
|
||||
model.Shapes.Add(shape.Shape);
|
||||
model.VertexBuffers.Add(shape.VertexBuffer);
|
||||
|
||||
shape.Shape.VertexBufferIndex = (ushort)(model.VertexBuffers.Count - 1);
|
||||
|
||||
BFRES.SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
|
||||
}
|
||||
foreach (FMAT mat in fmdl.materials.Values)
|
||||
{
|
||||
|
||||
SetMaterial(mat, mat.Material);
|
||||
model.Materials.Add(mat.Material);
|
||||
}
|
||||
|
@ -19,6 +19,41 @@ namespace FirstPlugin
|
||||
{
|
||||
public static class BfresWiiU
|
||||
{
|
||||
public static Model SetModel(FMDL fmdl)
|
||||
{
|
||||
Model model = new Model();
|
||||
model.Name = fmdl.Text;
|
||||
model.Shapes = new ResDict<Shape>();
|
||||
model.VertexBuffers = new List<VertexBuffer>();
|
||||
model.Materials = new ResDict<Material>();
|
||||
model.UserData = new ResDict<UserData>();
|
||||
model.Skeleton = new Skeleton();
|
||||
model.Skeleton = fmdl.Skeleton.node.SkeletonU;
|
||||
|
||||
int i = 0;
|
||||
var duplicates = fmdl.shapes.GroupBy(c => c.Text).Where(g => g.Skip(1).Any()).SelectMany(c => c);
|
||||
foreach (var shape in duplicates)
|
||||
shape.Text += i++;
|
||||
|
||||
foreach (FMAT mat in fmdl.materials.Values)
|
||||
{
|
||||
SetMaterial(mat, mat.MaterialU);
|
||||
model.Materials.Add(mat.Text, mat.MaterialU);
|
||||
}
|
||||
foreach (FSHP shape in fmdl.shapes)
|
||||
{
|
||||
BFRES.CheckMissingTextures(shape);
|
||||
SetShape(shape, shape.ShapeU);
|
||||
shape.ShapeU.SubMeshBoundingNodes = new List<BoundingNode>();
|
||||
|
||||
model.Shapes.Add(shape.Text, shape.ShapeU);
|
||||
model.VertexBuffers.Add(shape.VertexBufferU);
|
||||
shape.ShapeU.VertexBufferIndex = (ushort)(model.VertexBuffers.Count - 1);
|
||||
|
||||
BFRES.SetShaderAssignAttributes(shape.GetMaterial().shaderassign, shape);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
public static void Read(BFRESRender renderer, ResFile resFile, TreeNode ResFileNode)
|
||||
{
|
||||
int CurMdl = 0;
|
||||
|
@ -17,6 +17,7 @@ using Switch_Toolbox.Library;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using Smash_Forge.Rendering;
|
||||
using Switch_Toolbox.Library.Forms;
|
||||
using Switch_Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
@ -145,7 +146,7 @@ namespace FirstPlugin
|
||||
class MenuExt : IFileMenuExtension
|
||||
{
|
||||
public ToolStripItemDark[] NewFileMenuExtensions => null;
|
||||
public ToolStripItemDark[] ToolsMenuExtensions => null;
|
||||
public ToolStripItemDark[] ToolsMenuExtensions => newFileExt;
|
||||
public ToolStripItemDark[] TitleBarExtensions => null;
|
||||
public ToolStripItemDark[] CompressionMenuExtensions => null;
|
||||
public ToolStripItemDark[] ExperimentalMenuExtensions => null;
|
||||
@ -153,9 +154,80 @@ namespace FirstPlugin
|
||||
ToolStripItemDark[] newFileExt = new ToolStripItemDark[1];
|
||||
public MenuExt()
|
||||
{
|
||||
newFileExt[0] = new ToolStripItemDark("BNTX ");
|
||||
newFileExt[0] = new ToolStripItemDark("Extract BNTX");
|
||||
newFileExt[0].Click += Export;
|
||||
}
|
||||
private void Export(object sender, EventArgs args)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Multiselect = true;
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
foreach (string file in ofd.FileNames)
|
||||
{
|
||||
FileReader reader = new FileReader(ofd.FileName);
|
||||
reader.Seek(16, SeekOrigin.Begin);
|
||||
int offsetName = reader.ReadInt32();
|
||||
|
||||
reader.Seek(offsetName, SeekOrigin.Begin);
|
||||
string Name = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
|
||||
|
||||
Console.WriteLine(file + " " + Name);
|
||||
|
||||
reader.Close();
|
||||
reader.Dispose();
|
||||
|
||||
// System.IO.File.Move(file, Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
byte[] ByteBuffer = File.ReadAllBytes(ofd.FileName);
|
||||
byte[] StringBytes = Encoding.UTF8.GetBytes("BNTX");
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
byte byt = reader.ReadByte();
|
||||
|
||||
if (byt == 0x42)
|
||||
{
|
||||
reader.Seek(-1, SeekOrigin.Current);
|
||||
int TryRdMagic = reader.ReadInt32();
|
||||
if (TryRdMagic == 0x424E5458)
|
||||
{
|
||||
reader.ByteOrder = Syroot.BinaryData.ByteOrder.LittleEndian;
|
||||
|
||||
long BNTXpos = reader.Position - 4;
|
||||
Console.WriteLine("String was found at offset {0}", reader.Position);
|
||||
|
||||
reader.Seek(BNTXpos + 16, SeekOrigin.Begin);
|
||||
int offsetName = reader.ReadInt32();
|
||||
|
||||
reader.Seek(BNTXpos + offsetName, SeekOrigin.Begin);
|
||||
string Name = reader.ReadString();
|
||||
|
||||
reader.Seek(BNTXpos + 28, SeekOrigin.Begin);
|
||||
int size = reader.ReadInt32();
|
||||
|
||||
reader.Seek(BNTXpos, SeekOrigin.Begin);
|
||||
|
||||
File.WriteAllBytes(Name + ".bntx", reader.ReadBytes(size));
|
||||
reader.ByteOrder = Syroot.BinaryData.ByteOrder.BigEndian;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
BinaryTextureContainer bntx;
|
||||
|
||||
@ -1250,6 +1322,8 @@ namespace FirstPlugin
|
||||
{
|
||||
mipmaps.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
uint blk_dim = Formats.blk_dims((uint)((int)tex.Format >> 8));
|
||||
uint blkWidth = blk_dim >> 4;
|
||||
uint blkHeight = blk_dim & 0xF;
|
||||
@ -1277,7 +1351,6 @@ namespace FirstPlugin
|
||||
//Create a copy and use that to remove uneeded data
|
||||
byte[] result_ = new byte[size];
|
||||
Array.Copy(result, 0, result_, 0, size);
|
||||
|
||||
mips.Add(result_);
|
||||
|
||||
}
|
||||
@ -1285,6 +1358,12 @@ namespace FirstPlugin
|
||||
}
|
||||
|
||||
Texture = tex;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MessageBox.Show($"Failed to swizzle texture {Text}! Exception: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap DisplayTexture(int DisplayMipIndex = 0, int ArrayIndex = 0)
|
||||
|
@ -170,8 +170,15 @@ namespace FirstPlugin
|
||||
format = (int)tex.Format;
|
||||
int swizzle = (int)tex.Swizzle;
|
||||
int pitch = (int)tex.Pitch;
|
||||
uint bpp = GTX.surfaceGetBitsPerPixel((uint)format) >> 3;
|
||||
|
||||
renderedTex.data = GTX.swizzleBC(tex.Data, renderedTex.width, renderedTex.height, format, (int)tex.TileMode, pitch, swizzle);
|
||||
GTX.GX2Surface surf = new GTX.GX2Surface();
|
||||
surf.bpp = bpp;
|
||||
|
||||
for (int surfaceLevel = 0; surfaceLevel < tex.ArrayLength; surfaceLevel++)
|
||||
{
|
||||
}
|
||||
GTX.Decode(surf, tex.MipData);
|
||||
}
|
||||
|
||||
public void Export(string FileName, bool ExportSurfaceLevel = false,
|
||||
|
@ -91,12 +91,80 @@ namespace FirstPlugin
|
||||
public int swizzle;
|
||||
public int alignment;
|
||||
public int pitch;
|
||||
public uint bpp;
|
||||
|
||||
public byte[] data;
|
||||
|
||||
public int[] mipOffset;
|
||||
};
|
||||
|
||||
public static int m_configFlags = 4;
|
||||
public static int ADDR_OK = 0;
|
||||
|
||||
public static int expPitch = 0;
|
||||
public static int expHeight = 0;
|
||||
public static int expNumSlices = 0;
|
||||
|
||||
public class surfaceIn
|
||||
{
|
||||
public int size = 0;
|
||||
public int tileMode = 0;
|
||||
public int format = 0;
|
||||
public int bpp = 0;
|
||||
public int numSamples = 0;
|
||||
public int width = 0;
|
||||
public int height = 0;
|
||||
public int numSlices = 0;
|
||||
public int slice = 0;
|
||||
public int mipLevel = 0;
|
||||
public Flags flags = new Flags();
|
||||
public int numFrags = 0;
|
||||
public TileInfo tileType = new TileInfo();
|
||||
public int tileIndex = 0;
|
||||
}
|
||||
public class surfaceOut
|
||||
{
|
||||
public int size = 0;
|
||||
public int pitch = 0;
|
||||
public int height = 0;
|
||||
public int depth = 0;
|
||||
public int surfSize = 0;
|
||||
public int tileMode = 0;
|
||||
public int baseAlign = 0;
|
||||
public int pitchAlign = 0;
|
||||
public int heightAlign = 0;
|
||||
public int depthAlign = 0;
|
||||
public int bpp = 0;
|
||||
public int pixelPitch = 0;
|
||||
public int pixelHeight = 0;
|
||||
public int pixelBits = 0;
|
||||
public int sliceSize = 0;
|
||||
public int pitchTileMax = 0;
|
||||
public int heightTileMax = 0;
|
||||
public int sliceTileMax = 0;
|
||||
public int pTileInfo = 0;
|
||||
public TileInfo tileType = new TileInfo();
|
||||
public int tileIndex = 0;
|
||||
}
|
||||
|
||||
public class Flags
|
||||
{
|
||||
public uint value = 0;
|
||||
}
|
||||
|
||||
public class TileInfo
|
||||
{
|
||||
public int banks = 0;
|
||||
public int bankWidth = 0;
|
||||
public int bankHeight = 0;
|
||||
public int macroAspectRatio = 0;
|
||||
public int tileSplitBytes = 0;
|
||||
public int pipeConfig = 0;
|
||||
}
|
||||
|
||||
static surfaceIn pIn = new surfaceIn();
|
||||
static surfaceOut pOut = new surfaceOut();
|
||||
|
||||
public enum GX2SurfaceDimension
|
||||
{
|
||||
GX2_SURFACE_DIM_1D = 0x0,
|
||||
@ -388,24 +456,47 @@ namespace FirstPlugin
|
||||
ADDR_FMT_RESERVED_63 = 0x3F,
|
||||
};
|
||||
|
||||
private static byte[] formatHwInfo = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x08, 0x03, 0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
||||
0x10, 0x0B, 0x00, 0x01, 0x10, 0x01, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
||||
0x10, 0x03, 0x00, 0x01, 0x20, 0x03, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
||||
0x20, 0x03, 0x00, 0x01, 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01,
|
||||
0x40, 0x05, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00,
|
||||
0x40, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00,
|
||||
0x10, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
|
||||
0x60, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01,
|
||||
0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
public static List<byte[]> Decode(GX2Surface tex, byte[] MipData)
|
||||
{
|
||||
var surfInfo = getSurfaceInfo((GX2SurfaceFormat)tex.format, tex.width, tex.height, tex.depth, (uint)tex.dim, (uint)tex.tileMode, (uint)tex.aa, 0);
|
||||
if (surfInfo.depth != 1)
|
||||
throw new Exception("Unsupported Depth!");
|
||||
|
||||
List<byte[]> result = new List<byte[]>();
|
||||
for (int mipLevel = 0; mipLevel < tex.numMips; mipLevel++)
|
||||
{
|
||||
int size;
|
||||
if (IsFormatBCN((GX2SurfaceFormat)tex.format))
|
||||
size = ((Math.Max(1, tex.width >> mipLevel) + 3) >> 2) * ((Math.Max(1, tex.height >> mipLevel) + 3) >> 2) * (int)tex.bpp;
|
||||
else
|
||||
size = Math.Max(1, tex.width >> mipLevel) * Math.Max(1, tex.height >> mipLevel) * (int)tex.bpp;
|
||||
|
||||
byte[] data;
|
||||
if (mipLevel == 0)
|
||||
{
|
||||
data = new byte[surfInfo.surfSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
int mipOffset;
|
||||
if (mipLevel == 1)
|
||||
mipOffset = tex.mipOffset[mipLevel - 1] - surfInfo.surfSize;
|
||||
else
|
||||
mipOffset = tex.mipOffset[mipLevel - 1];
|
||||
|
||||
surfInfo = getSurfaceInfo((GX2SurfaceFormat)tex.format, tex.width, tex.height, tex.depth, (uint)tex.dim, (uint)tex.tileMode, (uint)tex.aa, mipLevel);
|
||||
|
||||
data = new byte[surfInfo.surfSize - mipOffset];
|
||||
Array.Copy(MipData, mipOffset, data, 0, surfInfo.surfSize);
|
||||
}
|
||||
byte[] deswizzled = deswizzle(Math.Max(1, (uint)tex.width >> mipLevel), Math.Max(1, (uint)tex.height >> mipLevel), (uint)surfInfo.height, (uint)tex.format,
|
||||
(uint)surfInfo.tileMode, (uint)tex.swizzle, (uint)surfInfo.pitch, (uint)surfInfo.bpp, data);
|
||||
//Create a copy and use that to remove uneeded data
|
||||
byte[] result_ = new byte[size];
|
||||
Array.Copy(deswizzled, 0, result_, 0, size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -430,24 +521,231 @@ namespace FirstPlugin
|
||||
{ FORMAT_INVALID, GX2_SURFACE_FORMAT_INVALID, 0, 0xFFFFFFFF, 0x00, nullptr, 0x00, 0 }
|
||||
};*/
|
||||
|
||||
|
||||
public static byte[] swizzleBC(byte[] data, int width, int height, int format, int tileMode, int pitch, int swizzle)
|
||||
public static bool IsFormatBCN(GX2SurfaceFormat Format)
|
||||
{
|
||||
GX2Surface sur = new GX2Surface();
|
||||
sur.width = width;
|
||||
sur.height = height;
|
||||
sur.tileMode = tileMode;
|
||||
sur.format = format;
|
||||
sur.swizzle = swizzle;
|
||||
sur.pitch = pitch;
|
||||
sur.data = data;
|
||||
sur.imageSize = data.Length;
|
||||
//return swizzleBC(sur);
|
||||
return swizzleSurface(sur, (GX2SurfaceFormat)sur.format != GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM &
|
||||
(GX2SurfaceFormat)sur.format != GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB);
|
||||
switch (Format)
|
||||
{
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM:
|
||||
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getBPP(int i)
|
||||
public static byte[] deswizzle(uint width, uint height, uint height_, uint format_, uint tileMode, uint swizzle_,
|
||||
uint pitch, uint bpp, byte[] data)
|
||||
{
|
||||
return swizzleSurf(width, height, height_, format_, tileMode, swizzle_, pitch, bpp, data, 0);
|
||||
}
|
||||
public static byte[] swizzle(uint width, uint height, uint height_, uint format_, uint tileMode, uint swizzle_,
|
||||
uint pitch, uint bpp, byte[] data)
|
||||
{
|
||||
return swizzleSurf(width, height, height_, format_, tileMode, swizzle_, pitch, bpp, data, 1);
|
||||
}
|
||||
|
||||
static uint m_banks = 4;
|
||||
static uint m_banksBitcount = 2;
|
||||
static uint m_pipes = 2;
|
||||
static uint m_pipesBitcount = 1;
|
||||
static uint m_pipeInterleaveBytes = 256;
|
||||
static uint m_pipeInterleaveBytesBitcount = 8;
|
||||
static uint m_rowSize = 2048;
|
||||
static uint m_swapSize = 256;
|
||||
static uint m_splitSize = 2048;
|
||||
|
||||
static uint m_chipFamily = 2;
|
||||
|
||||
static uint MicroTilePixels = 64;
|
||||
|
||||
|
||||
private static byte[] swizzleSurf(uint width, uint height, uint height_, uint format, uint tileMode, uint swizzle_,
|
||||
uint pitch, uint bitsPerPixel, byte[] data, int swizzle)
|
||||
{
|
||||
byte[] result = new byte[data.Length];
|
||||
|
||||
uint bytesPerPixel = bitsPerPixel / 8;
|
||||
|
||||
uint pipeSwizzle, bankSwizzle, pos_;
|
||||
uint pos;
|
||||
|
||||
if (IsFormatBCN((GX2SurfaceFormat)format))
|
||||
{
|
||||
width = (width + 3) / 4;
|
||||
height = (height + 3) / 4;
|
||||
}
|
||||
|
||||
pipeSwizzle = (swizzle_ >> 8) & 1;
|
||||
bankSwizzle = (swizzle_ >> 9) & 3;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var tileGrp1 = new List<uint> { 0, 1 };
|
||||
var tileGrp2 = new List<uint> { 2, 3 };
|
||||
|
||||
|
||||
if (tileGrp1.Contains(tileMode))
|
||||
pos = (uint)(y * pitch + x) * bytesPerPixel;
|
||||
else if (tileGrp2.Contains(tileMode))
|
||||
{
|
||||
pos = computeSurfaceAddrFromCoordMicroTiled(x, y, bitsPerPixel, pitch, tileMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = computeSurfaceAddrFromCoordMacroTiled(x, y, bitsPerPixel, (int)pitch, (int)height_, (int)tileMode, (int)pipeSwizzle, (int)bankSwizzle);
|
||||
}
|
||||
pos = 0;
|
||||
|
||||
pos_ = (uint)(y * width + x) * bytesPerPixel;
|
||||
|
||||
if (pos_ + bytesPerPixel <= data.Length && pos + bytesPerPixel <= data.Length)
|
||||
{
|
||||
if (swizzle == 0)
|
||||
{
|
||||
for (int n = 0; n < bytesPerPixel; n++)
|
||||
result[pos_ + n] = data[(uint)pos + n];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int n = 0; n < bytesPerPixel; n++)
|
||||
result[(uint)pos + n] = data[pos_ + n];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] formatHwInfo = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x08, 0x03, 0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
||||
0x10, 0x0B, 0x00, 0x01, 0x10, 0x01, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
||||
0x10, 0x03, 0x00, 0x01, 0x20, 0x03, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
||||
0x20, 0x03, 0x00, 0x01, 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01,
|
||||
0x40, 0x05, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00,
|
||||
0x40, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00,
|
||||
0x10, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
|
||||
0x60, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01,
|
||||
0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
private static byte[] formatExInfo = {
|
||||
0x00, 0x01, 0x01, 0x03, 0x08, 0x01, 0x01, 0x03, 0x08, 0x01, 0x01, 0x03, 0x08, 0x01, 0x01, 0x03,
|
||||
0x00, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03,
|
||||
0x10, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03, 0x10, 0x01, 0x01, 0x03,
|
||||
0x10, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03,
|
||||
0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03,
|
||||
0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03,
|
||||
0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03,
|
||||
0x40, 0x01, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03,
|
||||
0x40, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03, 0x80, 0x01, 0x01, 0x03, 0x80, 0x01, 0x01, 0x03,
|
||||
0x00, 0x01, 0x01, 0x03, 0x01, 0x08, 0x01, 0x05, 0x01, 0x08, 0x01, 0x06, 0x10, 0x01, 0x01, 0x07,
|
||||
0x10, 0x01, 0x01, 0x08, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03, 0x20, 0x01, 0x01, 0x03,
|
||||
0x18, 0x03, 0x01, 0x04, 0x30, 0x03, 0x01, 0x04, 0x30, 0x03, 0x01, 0x04, 0x60, 0x03, 0x01, 0x04,
|
||||
0x60, 0x03, 0x01, 0x04, 0x40, 0x04, 0x04, 0x09, 0x80, 0x04, 0x04, 0x0A, 0x80, 0x04, 0x04, 0x0B,
|
||||
0x40, 0x04, 0x04, 0x0C, 0x40, 0x04, 0x04, 0x0D, 0x40, 0x04, 0x04, 0x0D, 0x40, 0x04, 0x04, 0x0D,
|
||||
0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03,
|
||||
0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x03,
|
||||
};
|
||||
|
||||
public static uint surfaceGetBitsPerPixel(uint surfaceFormat)
|
||||
{
|
||||
return formatHwInfo[(surfaceFormat & 0x35) + 4];
|
||||
}
|
||||
|
||||
private static uint computePipeFromCoordWoRotation(uint x, uint y)
|
||||
{
|
||||
return ((y >> 3) ^ (x >> 3)) & 1;
|
||||
}
|
||||
|
||||
private static uint computeBankFromCoordWoRotation(uint x, uint y)
|
||||
{
|
||||
return ((y >> 5) ^ (x >> 3)) & 1 | 2 * (((y >> 4) ^ (x >> 4)) & 1);
|
||||
}
|
||||
|
||||
private static bool isThickMacroTiled(uint tileMode)
|
||||
{
|
||||
var Grp1 = new List<uint> { 7, 11, 13, 15 };
|
||||
if (Grp1.Contains(tileMode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool isBankSwapped(uint tileMode)
|
||||
{
|
||||
var Grp1 = new List<uint> { 8, 9, 10, 11, 14, 15 };
|
||||
if (Grp1.Contains(tileMode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static uint computeMacroTileAspectRatio(uint tileMode)
|
||||
{
|
||||
var Grp1 = new List<uint> { 5, 9 };
|
||||
var Grp2 = new List<uint> { 6, 10 };
|
||||
|
||||
if (Grp1.Contains(tileMode))
|
||||
return 2;
|
||||
|
||||
if (Grp2.Contains(tileMode))
|
||||
return 4;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static uint computeSurfaceBankSwappedWidth(uint tileMode, uint bpp, uint pitch, uint numSamplers)
|
||||
{
|
||||
if (isBankSwapped(tileMode) == true)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static uint computeSurfaceAddrFromCoordMicroTiled(int x, int y, uint bpp, uint pitch, uint tileMode)
|
||||
{
|
||||
return 0; //Todo
|
||||
|
||||
/* uint microTileThickness = 1;
|
||||
|
||||
if (tileMode == 3)
|
||||
microTileThickness = 4;
|
||||
|
||||
uint microTileBytes = (MicroTilePixels * microTileThickness * bpp + 7) / 8;
|
||||
uint microTilesPerRow = pitch >> 3;
|
||||
uint microTileIndexX = (uint)x >> 3;
|
||||
uint microTileIndexY = (uint)y >> 3;
|
||||
|
||||
uint microTileOffset = microTileBytes * (microTileIndexX + microTileIndexY * microTilesPerRow);
|
||||
|
||||
uint pixelIndex = computePixelIndexWithinMicroTile(x, y, bpp, tileMode);
|
||||
|
||||
uint pixelOffset = bpp * pixelIndex;
|
||||
pixelOffset >>= 3;
|
||||
|
||||
return pixelOffset + microTileOffset;*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static int getBPP(int i)
|
||||
{
|
||||
switch ((GX2SurfaceFormat)i)
|
||||
{
|
||||
@ -471,90 +769,15 @@ namespace FirstPlugin
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static byte[] swizzleSurface(GX2Surface surface, bool isCompressed)
|
||||
{
|
||||
byte[] original = new byte[surface.data.Length];
|
||||
|
||||
surface.data.CopyTo(original, 0);
|
||||
|
||||
int swizzle = ((surface.swizzle >> 8) & 1) + (((surface.swizzle >> 9) & 3) << 1);
|
||||
int blockSize;
|
||||
int width = surface.width;
|
||||
int height = surface.height;
|
||||
|
||||
int format = getBPP(surface.format);
|
||||
Console.WriteLine(((GX2SurfaceFormat)surface.format).ToString());
|
||||
|
||||
if (isCompressed)
|
||||
private static uint computeSurfaceAddrFromCoordMacroTiled(int x, int y, uint bpp, int pitch,
|
||||
int height, int tileMode, int pipeSwizzle, int bankSwizzle)
|
||||
{
|
||||
width /= 4;
|
||||
height /= 4;
|
||||
|
||||
if ((GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM ||
|
||||
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB ||
|
||||
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM ||
|
||||
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM)
|
||||
{
|
||||
blockSize = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockSize = 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if ((GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM)
|
||||
{
|
||||
blockSize = format / 4;
|
||||
}
|
||||
else*/
|
||||
blockSize = format / 8;
|
||||
return 0; //Todo
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int pos = surfaceAddrFromCoordMacroTiled(x, y, format, surface.pitch, swizzle);
|
||||
int pos_ = (y * width + x) * blockSize;
|
||||
|
||||
for (int k = 0; k < blockSize; k++)
|
||||
{
|
||||
if (pos + k >= original.Length || pos_ + k >= surface.data.Length)
|
||||
{
|
||||
Console.WriteLine("Break Point " + pos_ + " " + pos);
|
||||
break;
|
||||
}
|
||||
surface.data[pos_ + k] = original[pos + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return surface.data;
|
||||
}
|
||||
|
||||
public static int surfaceAddrFromCoordMacroTiled(int x, int y, int bpp, int pitch, int swizzle)
|
||||
{
|
||||
int pixelIndex = computePixelIndexWithinMicroTile(x, y, bpp);
|
||||
int elemOffset = (bpp * pixelIndex) >> 3;
|
||||
|
||||
int pipe = computePipeFromCoordWoRotation(x, y);
|
||||
int bank = computeBankFromCoordWoRotation(x, y);
|
||||
int bankPipe = ((pipe + 2 * bank) ^ swizzle) % 9;
|
||||
|
||||
pipe = bankPipe % 2;
|
||||
bank = bankPipe / 2;
|
||||
|
||||
int macroTileBytes = (bpp * 512 + 7) >> 3;
|
||||
int macroTileOffset = (x / 32 + pitch / 32 * (y / 16)) * macroTileBytes;
|
||||
|
||||
int unk1 = elemOffset + (macroTileOffset >> 3);
|
||||
int unk2 = unk1 & ~0xFF;
|
||||
|
||||
return (unk2 << 3) | (0xFF & unk1) | (pipe << 8) | (bank << 9);
|
||||
}
|
||||
|
||||
public static int computePixelIndexWithinMicroTile(int x, int y, int bpp)
|
||||
private static int computePixelIndexWithinMicroTile(int x, int y, uint bpp)
|
||||
{
|
||||
int bits = ((x & 4) << 1) | ((y & 2) << 3) | ((y & 4) << 3);
|
||||
|
||||
@ -574,13 +797,13 @@ namespace FirstPlugin
|
||||
return bits;
|
||||
}
|
||||
|
||||
public static int getFormatBpp(int format)
|
||||
private static int getFormatBpp(int format)
|
||||
{
|
||||
int hwFormat = format & 0x3F;
|
||||
return formatHwInfo[hwFormat * 4];
|
||||
}
|
||||
|
||||
public static int computeSurfaceThickness(AddrTileMode tileMode)
|
||||
private static int computeSurfaceThickness(AddrTileMode tileMode)
|
||||
{
|
||||
switch (tileMode)
|
||||
{
|
||||
@ -602,7 +825,7 @@ namespace FirstPlugin
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int isThickMacroTiled(AddrTileMode tileMode)
|
||||
private static int isThickMacroTiled(AddrTileMode tileMode)
|
||||
{
|
||||
switch (tileMode)
|
||||
{
|
||||
@ -618,7 +841,7 @@ namespace FirstPlugin
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int isBankSwappedTileMode(AddrTileMode tileMode)
|
||||
private static int isBankSwappedTileMode(AddrTileMode tileMode)
|
||||
{
|
||||
switch (tileMode)
|
||||
{
|
||||
@ -635,7 +858,7 @@ namespace FirstPlugin
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int computeSurfaceRotationFromTileMode(AddrTileMode tileMode)
|
||||
private static int computeSurfaceRotationFromTileMode(AddrTileMode tileMode)
|
||||
{
|
||||
switch ((int)tileMode)
|
||||
{
|
||||
@ -662,13 +885,13 @@ namespace FirstPlugin
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int computePipeFromCoordWoRotation(int x, int y)
|
||||
private static int computePipeFromCoordWoRotation(int x, int y)
|
||||
{
|
||||
int pipe = ((y >> 3) ^ (x >> 3)) & 1;
|
||||
return pipe;
|
||||
}
|
||||
|
||||
public static int computeBankFromCoordWoRotation(int x, int y)
|
||||
private static int computeBankFromCoordWoRotation(int x, int y)
|
||||
{
|
||||
int bankBit0 = ((y / (16 * 2)) ^ (x >> 3)) & 1;
|
||||
int bank = bankBit0 | 2 * (((y / (8 * 2)) ^ (x >> 4)) & 1);
|
||||
@ -676,7 +899,7 @@ namespace FirstPlugin
|
||||
return bank;
|
||||
}
|
||||
|
||||
public static int computeMacroTileAspectRatio(AddrTileMode tileMode)
|
||||
private static int computeMacroTileAspectRatio(AddrTileMode tileMode)
|
||||
{
|
||||
switch (tileMode)
|
||||
{
|
||||
@ -701,7 +924,7 @@ namespace FirstPlugin
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static int computeSurfaceBankSwappedWidth(AddrTileMode tileMode, int bpp, int numSamples, int pitch, int pSlicesPerTile)
|
||||
private static int computeSurfaceBankSwappedWidth(AddrTileMode tileMode, int bpp, int numSamples, int pitch, int pSlicesPerTile)
|
||||
{
|
||||
int bankSwapWidth = 0;
|
||||
int numBanks = 4;
|
||||
@ -787,7 +1010,7 @@ namespace FirstPlugin
|
||||
return bankSwapWidth;
|
||||
}
|
||||
|
||||
public static int computePixelIndexWithinMicroTile(int x, int y, int z, int bpp, AddrTileMode tileMode, int microTileType)
|
||||
private static int computePixelIndexWithinMicroTile(int x, int y, int z, int bpp, AddrTileMode tileMode, int microTileType)
|
||||
{
|
||||
int pixelBit0 = 0;
|
||||
int pixelBit1 = 0;
|
||||
@ -903,7 +1126,7 @@ namespace FirstPlugin
|
||||
(pixelBit1 << 1);
|
||||
}
|
||||
|
||||
public static int surfaceAddrFromCoordMacroTiled(
|
||||
private static int surfaceAddrFromCoordMacroTiled(
|
||||
int x, int y, int slice, int sample, int bpp,
|
||||
int pitch, int height, int numSamples, AddrTileMode tileMode,
|
||||
int isDepth, int tileBase, int compBits,
|
||||
@ -1045,93 +1268,266 @@ namespace FirstPlugin
|
||||
return subOffset1 | subOffset2 | p4 | p5;
|
||||
}
|
||||
|
||||
public static byte[] swizzleBC(GX2Surface surface)
|
||||
private static int getFillSizeFieldsFlags()
|
||||
{
|
||||
//std::vector<u8> result;
|
||||
//List<byte> result = new List<byte>();
|
||||
return (m_configFlags >> 6) & 1;
|
||||
}
|
||||
|
||||
//result.resize(surface->imageSize);
|
||||
|
||||
//u8 *data = (u8*)surface->imagePtr;
|
||||
byte[] data = surface.data;
|
||||
byte[] result = new byte[surface.imageSize];
|
||||
|
||||
int width = surface.width / 4;
|
||||
int height = surface.height / 4;
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
private static void computeSurfaceInfo(surfaceIn aSurfIn, surfaceOut aSurfOut)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
//Todo!
|
||||
surfaceIn pIn = aSurfIn;
|
||||
surfaceOut pOut = aSurfOut;
|
||||
|
||||
int v4 = 0;
|
||||
int v6 = 0;
|
||||
int v7 = 0;
|
||||
int v8 = 0;
|
||||
int v10 = 0;
|
||||
int v11 = 0;
|
||||
int v12 = 0;
|
||||
int v18 = 0;
|
||||
|
||||
TileInfo tileInfoNull = new TileInfo();
|
||||
int sliceFlags = 0;
|
||||
int returnCode = 0;
|
||||
|
||||
if (getFillSizeFieldsFlags() == 1 && (pIn.size != 60 || pOut.size != 96))
|
||||
returnCode = 6;
|
||||
|
||||
if (pIn.bpp > 0x80)
|
||||
returnCode = 3;
|
||||
|
||||
if (returnCode == ADDR_OK)
|
||||
{
|
||||
int bpp = getFormatBpp(surface.format);
|
||||
int pos = 0;
|
||||
v18 = 0;
|
||||
|
||||
switch (surface.tileMode)
|
||||
|
||||
computeMipLevel();
|
||||
|
||||
int width = pIn.width;
|
||||
int height = pIn.height;
|
||||
int bpp = pIn.bpp;
|
||||
int expandX = 1;
|
||||
int expandY = 1;
|
||||
|
||||
}
|
||||
}
|
||||
private static void computeMipLevel()
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
uint slices = 0;
|
||||
uint height = 0;
|
||||
uint width = 0;
|
||||
uint hwlHandled = 0;
|
||||
|
||||
if ((49 <= pIn.format && 49 <= 55 && pIn.mipLevel != 49) || 49 <= ((pIn.flags.value >> 12) & 1))
|
||||
{
|
||||
// pos = surfaceAddrFromCoordLinear(
|
||||
// x, y, 0, 0, bpp,
|
||||
// surface->pitch, height, surface->depth, 0
|
||||
// );
|
||||
|
||||
//printf("Unsupported tilemode %d\n", surface->tileMode);
|
||||
//exit(1);
|
||||
pIn.width = powTwoAlign(pIn.width, 4);
|
||||
pIn.height = powTwoAlign(pIn.height, 4);
|
||||
}
|
||||
break;
|
||||
hwlHandled = hwlComputeMipLevel();
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
}
|
||||
private static uint hwlComputeMipLevel()
|
||||
{
|
||||
// pos = surfaceAddrFromCoordMicroTiled(
|
||||
// x, y, 0, bpp, surface->pitch, height,
|
||||
// surface->tileMode, 0, 0, 0, 0
|
||||
// );
|
||||
//This part might be wrong?
|
||||
uint handled = 0;
|
||||
|
||||
//printf("Unsupported tilemode %d\n", surface->tileMode);
|
||||
//exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (49 <= pIn.format && 49 <= 55)
|
||||
{
|
||||
pos = surfaceAddrFromCoordMacroTiled(
|
||||
x, y, 0, 0, bpp, surface.pitch, height,
|
||||
1, (AddrTileMode)surface.tileMode, 0, 0, 0,
|
||||
(surface.swizzle >> 8) & 1,
|
||||
(surface.swizzle >> 9) & 3
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int q = y * width + x;
|
||||
switch (surface.format)
|
||||
if (pIn.mipLevel != 0)
|
||||
{
|
||||
case 0x31:
|
||||
case 0x34:
|
||||
case 0x234:
|
||||
case 0x431:
|
||||
int width = pIn.width;
|
||||
int height = pIn.height;
|
||||
int slices = pIn.numSlices;
|
||||
|
||||
if (((pIn.flags.value >> 12) & 1) != 0)
|
||||
{
|
||||
System.Array.Copy(data, pos, result, q * 8, 8);
|
||||
//memcpy(result.data() + q*8, data+pos, 8);
|
||||
}
|
||||
break;
|
||||
int widtha = width >> pIn.mipLevel;
|
||||
int heighta = height >> pIn.mipLevel;
|
||||
|
||||
default:
|
||||
if (((pIn.flags.value >> 4) & 1) == 0)
|
||||
slices >>= pIn.mipLevel;
|
||||
|
||||
width = Math.Max(1, widtha);
|
||||
height = Math.Max(1, heighta);
|
||||
slices = Math.Max(1, slices);
|
||||
}
|
||||
|
||||
pIn.width = nextPow2(width);
|
||||
pIn.height = nextPow2(height);
|
||||
pIn.numSlices = slices;
|
||||
|
||||
handled = 1;
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
private static int nextPow2(int dim)
|
||||
{
|
||||
System.Array.Copy(data, pos, result, q * 16, 16);
|
||||
//memcpy(result.data() + q*16, data+pos, 16);
|
||||
uint newDim = 1;
|
||||
if (newDim <= 0x7FFFFFFF)
|
||||
{
|
||||
while (newDim < dim)
|
||||
newDim *= 2;
|
||||
}
|
||||
break;
|
||||
else
|
||||
newDim = 2147483648;
|
||||
|
||||
return (int)newDim;
|
||||
}
|
||||
private static int powTwoAlign(int x, int align)
|
||||
{
|
||||
return (int)(align - 1) & (x + align - 1);
|
||||
}
|
||||
|
||||
public static surfaceOut getSurfaceInfo(GX2SurfaceFormat surfaceFormat, int surfaceWidth, int surfaceHeight, int surfaceDepth, uint surfaceDim, uint surfaceTileMode, uint surfaceAA, int level)
|
||||
{
|
||||
GX2Surface surface = new GX2Surface();
|
||||
|
||||
uint dim = 0;
|
||||
uint width = 0;
|
||||
uint blockSize = 0;
|
||||
int numSamples = 0;
|
||||
int hwFormat = 0;
|
||||
|
||||
var aSurfIn = new surfaceIn();
|
||||
var pSurfOut = new surfaceOut();
|
||||
|
||||
hwFormat = (int)surfaceFormat & 0x3F;
|
||||
|
||||
if (surfaceTileMode == 16)
|
||||
{
|
||||
numSamples = 1 << (int)surfaceAA;
|
||||
|
||||
if (hwFormat < 0x31 || hwFormat > 0x35)
|
||||
blockSize = 1;
|
||||
else
|
||||
blockSize = 4;
|
||||
|
||||
width = (uint)((blockSize - 1) & ((surfaceWidth >> level) + blockSize - 1));
|
||||
|
||||
if (hwFormat == 0x35)
|
||||
return pSurfOut;
|
||||
|
||||
pSurfOut.bpp = formatHwInfo[hwFormat * 4];
|
||||
pSurfOut.size = 96;
|
||||
pSurfOut.pitch = (int)(width / blockSize);
|
||||
pSurfOut.pixelBits = formatHwInfo[hwFormat * 4];
|
||||
pSurfOut.baseAlign = 1;
|
||||
pSurfOut.pitchAlign = 1;
|
||||
pSurfOut.heightAlign = 1;
|
||||
pSurfOut.depthAlign = 1;
|
||||
|
||||
if (dim == 0)
|
||||
{
|
||||
pSurfOut.height = 1;
|
||||
pSurfOut.depth = 1;
|
||||
}
|
||||
else if (dim == 1)
|
||||
{
|
||||
pSurfOut.height = Math.Max(1, surfaceHeight >> level);
|
||||
pSurfOut.depth = 1;
|
||||
}
|
||||
else if (dim == 2)
|
||||
{
|
||||
pSurfOut.height = Math.Max(1, surfaceHeight >> level);
|
||||
pSurfOut.depth = Math.Max(1, surfaceDepth >> level);
|
||||
}
|
||||
else if (dim == 3)
|
||||
{
|
||||
pSurfOut.height = Math.Max(1, surfaceHeight >> level);
|
||||
pSurfOut.depth = Math.Max(6, surfaceDepth);
|
||||
}
|
||||
else if (dim == 4)
|
||||
{
|
||||
pSurfOut.height = 1;
|
||||
pSurfOut.depth = surfaceDepth;
|
||||
}
|
||||
else if (dim == 5)
|
||||
{
|
||||
pSurfOut.height = Math.Max(1, surfaceHeight >> level);
|
||||
pSurfOut.depth = surfaceDepth;
|
||||
}
|
||||
|
||||
pSurfOut.height = (int)(((blockSize - 1) & (pSurfOut.height + blockSize - 1)) / blockSize);
|
||||
pSurfOut.pixelPitch = (int)((blockSize - 1) & ((surfaceWidth >> level) + blockSize - 1));
|
||||
pSurfOut.pixelPitch = (int)Math.Max(blockSize, pSurfOut.pixelPitch);
|
||||
pSurfOut.pixelHeight = (int)((blockSize - 1) & ((surfaceHeight >> level) + blockSize - 1));
|
||||
pSurfOut.pixelHeight = (int)Math.Max(blockSize, pSurfOut.pixelHeight);
|
||||
pSurfOut.pitch = Math.Max(1, pSurfOut.pitch);
|
||||
pSurfOut.height = Math.Max(1, pSurfOut.height);
|
||||
pSurfOut.surfSize = pSurfOut.bpp * numSamples * pSurfOut.depth * pSurfOut.height * pSurfOut.pitch >> 3;
|
||||
|
||||
if (surfaceDim == 2)
|
||||
pSurfOut.sliceSize = pSurfOut.surfSize;
|
||||
|
||||
else
|
||||
pSurfOut.sliceSize = pSurfOut.surfSize / pSurfOut.depth;
|
||||
|
||||
pSurfOut.pitchTileMax = (pSurfOut.pitch >> 3) - 1;
|
||||
pSurfOut.heightTileMax = (pSurfOut.height >> 3) - 1;
|
||||
pSurfOut.sliceTileMax = (pSurfOut.height * pSurfOut.pitch >> 6) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
aSurfIn.size = 60;
|
||||
aSurfIn.tileMode = (int)surfaceTileMode & 0x0F;
|
||||
aSurfIn.format = hwFormat;
|
||||
aSurfIn.bpp = formatHwInfo[hwFormat * 4];
|
||||
aSurfIn.numSamples = 1 << (int)surfaceAA;
|
||||
aSurfIn.numFrags = aSurfIn.numSamples;
|
||||
aSurfIn.width = Math.Max(1, surfaceWidth >> level);
|
||||
|
||||
if (dim == 0)
|
||||
{
|
||||
aSurfIn.height = 1;
|
||||
aSurfIn.numSlices = 1;
|
||||
}
|
||||
else if (dim == 1)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = 1;
|
||||
}
|
||||
else if (dim == 2)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = Math.Max(1, surfaceDepth >> level);
|
||||
}
|
||||
else if (dim == 3)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = Math.Max(6, surfaceDepth);
|
||||
aSurfIn.flags.value |= 0x10;
|
||||
}
|
||||
else if (dim == 4)
|
||||
{
|
||||
aSurfIn.height = 1;
|
||||
aSurfIn.numSlices = surfaceDepth;
|
||||
}
|
||||
else if (dim == 5)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = surfaceDepth;
|
||||
}
|
||||
else if (dim == 6)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = 1;
|
||||
}
|
||||
else if (dim == 7)
|
||||
{
|
||||
aSurfIn.height = Math.Max(1, surfaceHeight >> level);
|
||||
aSurfIn.numSlices = surfaceDepth;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
pSurfOut.size = 96;
|
||||
computeSurfaceInfo(aSurfIn, pSurfOut);
|
||||
|
||||
//memcpy(data, result.data(), result.size());
|
||||
pSurfOut = pOut;
|
||||
|
||||
return pSurfOut;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
470
Switch_FileFormatsMain/FileFormats/Texture/NUTEXB.cs
Normal file
470
Switch_FileFormatsMain/FileFormats/Texture/NUTEXB.cs
Normal file
@ -0,0 +1,470 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using Switch_Toolbox;
|
||||
using System.Windows.Forms;
|
||||
using Switch_Toolbox.Library;
|
||||
using Switch_Toolbox.Library.IO;
|
||||
using Switch_Toolbox.Library.Forms;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public class NUTEXB : IFileFormat
|
||||
{
|
||||
public bool CanSave { get; set; } = false;
|
||||
public bool FileIsEdited { get; set; } = false;
|
||||
public bool FileIsCompressed { get; set; } = false;
|
||||
public string[] Description { get; set; } = new string[] { "TEX" };
|
||||
public string[] Extension { get; set; } = new string[] { "*.nutexb" };
|
||||
public string Magic { get; set; } = "XET";
|
||||
public CompressionType CompressionType { get; set; } = CompressionType.None;
|
||||
public byte[] Data { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public TreeNodeFile EditorRoot { get; set; }
|
||||
public bool IsActive { get; set; } = false;
|
||||
public bool UseEditMenu { get; set; } = false;
|
||||
public string FilePath { get; set; }
|
||||
public IFileInfo IFileInfo { get; set; }
|
||||
|
||||
public enum NUTEXImageFormat : uint
|
||||
{
|
||||
R8G8B8A8_UNORM = 0x00,
|
||||
R8G8B8A8_SRGB = 0x05,
|
||||
BC1_UNORM = 0x80,
|
||||
BC1_SRGB = 0x85,
|
||||
BC2_UNORM = 0x90,
|
||||
BC2_SRGB = 0x95,
|
||||
BC3_UNORM = 0xa0,
|
||||
BC3_SRGB = 0xa5,
|
||||
BC4_UNORM = 0xb0,
|
||||
BC4_SNORM = 0xb5,
|
||||
BC5_UNORM = 0xc0,
|
||||
BC5_SNORM = 0xc5,
|
||||
BC6_UFLOAT = 0xd7,
|
||||
BC7_UNORM = 0xe0,
|
||||
BC7_SRGB = 0xe5,
|
||||
};
|
||||
|
||||
public static uint blk_dims(byte format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case (byte)NUTEXImageFormat.BC1_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC1_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC2_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC2_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC3_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC3_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC4_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC4_SNORM:
|
||||
case (byte)NUTEXImageFormat.BC5_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC5_SNORM:
|
||||
case (byte)NUTEXImageFormat.BC6_UFLOAT:
|
||||
case (byte)NUTEXImageFormat.BC7_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC7_SRGB:
|
||||
return 0x44;
|
||||
|
||||
default: return 0x11;
|
||||
}
|
||||
}
|
||||
|
||||
public static uint bpps(byte format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case (byte)NUTEXImageFormat.R8G8B8A8_UNORM:
|
||||
case (byte)NUTEXImageFormat.R8G8B8A8_SRGB:
|
||||
return 4;
|
||||
|
||||
case (byte)NUTEXImageFormat.BC1_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC1_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC4_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC4_SNORM:
|
||||
return 8;
|
||||
|
||||
case (byte)NUTEXImageFormat.BC2_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC2_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC3_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC3_SRGB:
|
||||
case (byte)NUTEXImageFormat.BC5_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC5_SNORM:
|
||||
case (byte)NUTEXImageFormat.BC6_UFLOAT:
|
||||
case (byte)NUTEXImageFormat.BC7_UNORM:
|
||||
case (byte)NUTEXImageFormat.BC7_SRGB:
|
||||
return 16;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
public Type[] Types
|
||||
{
|
||||
get
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
types.Add(typeof(MenuExt));
|
||||
return types.ToArray();
|
||||
}
|
||||
}
|
||||
class MenuExt : IFileMenuExtension
|
||||
{
|
||||
public ToolStripItemDark[] NewFileMenuExtensions => null;
|
||||
public ToolStripItemDark[] ToolsMenuExtensions => newFileExt;
|
||||
public ToolStripItemDark[] TitleBarExtensions => null;
|
||||
public ToolStripItemDark[] CompressionMenuExtensions => null;
|
||||
public ToolStripItemDark[] ExperimentalMenuExtensions => null;
|
||||
|
||||
ToolStripItemDark[] newFileExt = new ToolStripItemDark[1];
|
||||
public MenuExt()
|
||||
{
|
||||
newFileExt[0] = new ToolStripItemDark("Batch Export NUTEXB");
|
||||
newFileExt[0].Click += Export;
|
||||
}
|
||||
private void Export(object sender, EventArgs args)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.Multiselect = true;
|
||||
|
||||
if (ofd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
foreach (string file in ofd.FileNames)
|
||||
{
|
||||
NuTex texture = new NuTex();
|
||||
texture.Read(new FileReader(file));
|
||||
|
||||
Console.WriteLine(texture.Format.ToString("x") + " " + file + " " + texture.Text);
|
||||
|
||||
/*
|
||||
try
|
||||
{
|
||||
Bitmap bitmap = texture.DisplayImage();
|
||||
|
||||
if (bitmap != null)
|
||||
bitmap.Save(System.IO.Path.GetDirectoryName(ofd.FileName) + texture.Text + ".png");
|
||||
else
|
||||
Console.WriteLine(" Not supported Format! " + texture.Format);
|
||||
|
||||
if (bitmap != null)
|
||||
bitmap.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
texture = null;
|
||||
GC.Collect();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public class NuTex : TreeNodeFile
|
||||
{
|
||||
public uint Width;
|
||||
public uint Height;
|
||||
public byte Format;
|
||||
public uint[] mipSizes;
|
||||
public uint Alignment;
|
||||
public List<List<byte[]>> mipmaps = new List<List<byte[]>>();
|
||||
public List<List<byte[]>> blocksCompressed = new List<List<byte[]>>();
|
||||
bool IsSwizzled = true;
|
||||
|
||||
MenuItem export = new MenuItem("Export");
|
||||
|
||||
public NuTex()
|
||||
{
|
||||
ImageKey = "Texture";
|
||||
SelectedImageKey = "Texture";
|
||||
|
||||
ContextMenu = new ContextMenu();
|
||||
ContextMenu.MenuItems.Add(export);
|
||||
|
||||
export.Click += Export;
|
||||
}
|
||||
private void Export(object sender, EventArgs args)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.FileName = Text;
|
||||
sfd.DefaultExt = "png";
|
||||
sfd.Filter = "Supported Formats|*.dds; *.png;*.tga;*.jpg;*.tiff|" +
|
||||
"Microsoft DDS |*.dds|" +
|
||||
"Portable Network Graphics |*.png|" +
|
||||
"Joint Photographic Experts Group |*.jpg|" +
|
||||
"Bitmap Image |*.bmp|" +
|
||||
"Tagged Image File Format |*.tiff|" +
|
||||
"All files(*.*)|*.*";
|
||||
|
||||
if (sfd.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
Export(sfd.FileName);
|
||||
}
|
||||
}
|
||||
public void Export(string FileName, bool ExportSurfaceLevel = false,
|
||||
bool ExportMipMapLevel = false, int SurfaceLevel = 0, int MipLevel = 0)
|
||||
{
|
||||
string ext = System.IO.Path.GetExtension(FileName);
|
||||
ext = ext.ToLower();
|
||||
switch (ext)
|
||||
{
|
||||
case ".dds":
|
||||
SaveDDS(FileName);
|
||||
break;
|
||||
default:
|
||||
SaveBitMap(FileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
internal void SaveBitMap(string FileName, int SurfaceLevel = 0, int MipLevel = 0)
|
||||
{
|
||||
Bitmap bitMap = DisplayTexture(SurfaceLevel, MipLevel);
|
||||
|
||||
bitMap.Save(FileName);
|
||||
}
|
||||
internal void SaveDDS(string FileName)
|
||||
{
|
||||
DDS dds = new DDS();
|
||||
dds.header = new DDS.Header();
|
||||
dds.header.width = Width;
|
||||
dds.header.height = Height;
|
||||
dds.header.mipmapCount = (uint)mipmaps.Count;
|
||||
|
||||
bool IsDX10 = false;
|
||||
|
||||
IsDX10 = true;
|
||||
dds.DX10header = new DDS.DX10Header();
|
||||
dds.DX10header.DXGI_Format = DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM;
|
||||
|
||||
if (IsDX10)
|
||||
dds.header.ddspf.fourCC = "DX10";
|
||||
|
||||
dds.Save(dds, FileName, IsDX10, mipmaps);
|
||||
}
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
ImageKey = "Texture";
|
||||
SelectedImageKey = "Texture";
|
||||
|
||||
long pos = reader.BaseStream.Length;
|
||||
string magic = reader.ReadMagic((int)pos - 7, 3);//Check magic first!
|
||||
|
||||
if (magic != "XET")
|
||||
throw new Exception($"Invalid magic! Expected XET but got {magic}");
|
||||
|
||||
reader.Seek(pos - 112, System.IO.SeekOrigin.Begin); //Subtract size where the name occurs
|
||||
byte padding = reader.ReadByte();
|
||||
Text = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated);
|
||||
|
||||
reader.Seek(pos - 48, System.IO.SeekOrigin.Begin); //Subtract size of header
|
||||
uint padding2 = reader.ReadUInt32();
|
||||
Width = reader.ReadUInt32();
|
||||
Height = reader.ReadUInt32();
|
||||
uint ArrayCount = reader.ReadUInt32(); //6 for cubemaps
|
||||
Format = reader.ReadByte();
|
||||
byte unk = reader.ReadByte(); //Might be unorm/snorm/srgb
|
||||
ushort padding3 = reader.ReadUInt16();
|
||||
uint unk2 = reader.ReadUInt32();
|
||||
uint mipCount = reader.ReadUInt32();
|
||||
Alignment = reader.ReadUInt32();
|
||||
int unk3 = reader.ReadInt32();
|
||||
int imagesize = reader.ReadInt32();
|
||||
|
||||
reader.Seek(pos - 176, System.IO.SeekOrigin.Begin); //Get mipmap sizes
|
||||
mipSizes = reader.ReadUInt32s((int)mipCount);
|
||||
|
||||
List<byte[]> mips = new List<byte[]>();
|
||||
reader.Seek(0, System.IO.SeekOrigin.Begin);
|
||||
|
||||
if (mipCount == 1 && IsSwizzled)
|
||||
{
|
||||
mips.Add(reader.ReadBytes((int)imagesize));
|
||||
blocksCompressed.Add(mips);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int arrayLevel = 0; arrayLevel < ArrayCount; arrayLevel++)
|
||||
{
|
||||
for (int mipLevel = 0; mipLevel < mipCount; mipLevel++)
|
||||
{
|
||||
mips.Add(reader.ReadBytes((int)mipSizes[mipLevel]));
|
||||
break; //Don't load mip maps yet. They break for some reason????
|
||||
}
|
||||
blocksCompressed.Add(mips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClick(TreeView treeView)
|
||||
{
|
||||
UpdateEditor();
|
||||
}
|
||||
|
||||
public Bitmap DisplayTexture(int DisplayMipIndex = 0, int ArrayIndex = 0)
|
||||
{
|
||||
if (IsSwizzled)
|
||||
LoadTexture();
|
||||
else
|
||||
mipmaps.Add(blocksCompressed[0]);
|
||||
|
||||
if (mipmaps.Count <= 0)
|
||||
{
|
||||
throw new Exception("No texture data found");
|
||||
}
|
||||
|
||||
uint width = (uint)Math.Max(1, Width >> DisplayMipIndex);
|
||||
uint height = (uint)Math.Max(1, Height >> DisplayMipIndex);
|
||||
|
||||
byte[] data = mipmaps[ArrayIndex][DisplayMipIndex];
|
||||
return DecodeBlock(data, width, height, (NUTEXImageFormat)Format);
|
||||
}
|
||||
public static Bitmap DecodeBlock(byte[] data, uint Width, uint Height, NUTEXImageFormat Format)
|
||||
{
|
||||
Bitmap decomp;
|
||||
|
||||
if (Format == NUTEXImageFormat.BC5_SNORM)
|
||||
return DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, true);
|
||||
|
||||
byte[] d = null;
|
||||
if (IsCompressedFormat(Format))
|
||||
d = DDSCompressor.DecompressBlock(data, (int)Width, (int)Height, GetCompressedDXGI_FORMAT(Format));
|
||||
else
|
||||
d = DDSCompressor.DecodePixelBlock(data, (int)Width, (int)Height, GetUncompressedDXGI_FORMAT(Format));
|
||||
|
||||
if (d != null)
|
||||
{
|
||||
decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height);
|
||||
return TextureData.SwapBlueRedChannels(decomp);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static DDS.DXGI_FORMAT GetUncompressedDXGI_FORMAT(NUTEXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case NUTEXImageFormat.R8G8B8A8_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case NUTEXImageFormat.R8G8B8A8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
default:
|
||||
throw new Exception($"Cannot convert format {Format}");
|
||||
}
|
||||
}
|
||||
private static DDS.DXGI_FORMAT GetCompressedDXGI_FORMAT(NUTEXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case NUTEXImageFormat.BC1_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
|
||||
case NUTEXImageFormat.BC1_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB;
|
||||
case NUTEXImageFormat.BC2_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
|
||||
case NUTEXImageFormat.BC2_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB;
|
||||
case NUTEXImageFormat.BC3_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
|
||||
case NUTEXImageFormat.BC3_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB;
|
||||
case NUTEXImageFormat.BC4_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
|
||||
case NUTEXImageFormat.BC4_SNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
|
||||
case NUTEXImageFormat.BC5_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
|
||||
case NUTEXImageFormat.BC5_SNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
|
||||
case NUTEXImageFormat.BC6_UFLOAT: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16;
|
||||
case NUTEXImageFormat.BC7_UNORM: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM;
|
||||
case NUTEXImageFormat.BC7_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB;
|
||||
default:
|
||||
throw new Exception($"Cannot convert format {Format}");
|
||||
}
|
||||
}
|
||||
private static bool IsCompressedFormat(NUTEXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case NUTEXImageFormat.BC1_UNORM:
|
||||
case NUTEXImageFormat.BC1_SRGB:
|
||||
case NUTEXImageFormat.BC2_UNORM:
|
||||
case NUTEXImageFormat.BC2_SRGB:
|
||||
case NUTEXImageFormat.BC3_UNORM:
|
||||
case NUTEXImageFormat.BC3_SRGB:
|
||||
case NUTEXImageFormat.BC4_UNORM:
|
||||
case NUTEXImageFormat.BC4_SNORM:
|
||||
case NUTEXImageFormat.BC5_UNORM:
|
||||
case NUTEXImageFormat.BC5_SNORM:
|
||||
case NUTEXImageFormat.BC6_UFLOAT:
|
||||
case NUTEXImageFormat.BC7_UNORM:
|
||||
case NUTEXImageFormat.BC7_SRGB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadTexture(int target = 1)
|
||||
{
|
||||
mipmaps.Clear();
|
||||
|
||||
uint blk_dim = blk_dims(Format);
|
||||
uint blkWidth = blk_dim >> 4;
|
||||
uint blkHeight = blk_dim & 0xF;
|
||||
|
||||
uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
|
||||
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
||||
uint tileMode = 0;
|
||||
|
||||
int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;
|
||||
|
||||
uint bpp = bpps(Format);
|
||||
|
||||
for (int arrayLevel = 0; arrayLevel < blocksCompressed.Count; arrayLevel++)
|
||||
{
|
||||
int blockHeightShift = 0;
|
||||
|
||||
List<byte[]> mips = new List<byte[]>();
|
||||
for (int mipLevel = 0; mipLevel < blocksCompressed[arrayLevel].Count; mipLevel++)
|
||||
{
|
||||
uint width = (uint)Math.Max(1, Width >> mipLevel);
|
||||
uint height = (uint)Math.Max(1, Height >> mipLevel);
|
||||
|
||||
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
|
||||
|
||||
if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
|
||||
blockHeightShift += 1;
|
||||
|
||||
Console.WriteLine($"{blk_dim.ToString("x")} {bpp} {width} {height} {linesPerBlockHeight} {blkWidth} {blkHeight} {size} { blocksCompressed[arrayLevel][mipLevel].Length}");
|
||||
|
||||
byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, target, bpp, tileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), blocksCompressed[arrayLevel][mipLevel]);
|
||||
//Create a copy and use that to remove uneeded data
|
||||
byte[] result_ = new byte[size];
|
||||
Array.Copy(result, 0, result_, 0, size);
|
||||
|
||||
mips.Add(result_);
|
||||
}
|
||||
mipmaps.Add(mips);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateEditor()
|
||||
{
|
||||
if (Viewport.Instance.gL_ControlModern1.Visible == false)
|
||||
PluginRuntime.FSHPDockState = WeifenLuo.WinFormsUI.Docking.DockState.Document;
|
||||
|
||||
NuTexEditor docked = (NuTexEditor)LibraryGUI.Instance.GetContentDocked(new NuTexEditor());
|
||||
if (docked == null)
|
||||
{
|
||||
docked = new NuTexEditor();
|
||||
LibraryGUI.Instance.LoadDockContent(docked, PluginRuntime.FSHPDockState);
|
||||
}
|
||||
docked.Text = Text;
|
||||
docked.Dock = DockStyle.Fill;
|
||||
docked.LoadProperty(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
IsActive = true;
|
||||
EditorRoot = new NuTex();
|
||||
((NuTex)EditorRoot).FileHandler = this;
|
||||
((NuTex)EditorRoot).Read(new FileReader(Data));
|
||||
}
|
||||
public void Unload()
|
||||
{
|
||||
|
||||
}
|
||||
public byte[] Save()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using Switch_Toolbox;
|
||||
using System.Windows.Forms;
|
||||
using Switch_Toolbox.Library;
|
||||
using Switch_Toolbox.Library.IO;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
@ -38,6 +40,10 @@ namespace FirstPlugin
|
||||
public void Load()
|
||||
{
|
||||
IsActive = true;
|
||||
EditorRoot = new XTXFile();
|
||||
((XTXFile)EditorRoot).FileHandler = this;
|
||||
((XTXFile)EditorRoot).Text = FileName;
|
||||
((XTXFile)EditorRoot).LoadFile(Data);
|
||||
}
|
||||
public void Unload()
|
||||
{
|
||||
@ -47,5 +53,330 @@ namespace FirstPlugin
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public class XTXFormats
|
||||
{
|
||||
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,
|
||||
};
|
||||
|
||||
public enum BNTXImageTypes
|
||||
{
|
||||
UNORM = 0x01,
|
||||
SNORM = 0x02,
|
||||
SRGB = 0x06,
|
||||
};
|
||||
|
||||
public static uint blk_dims(uint format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case (uint)XTXImageFormat.DXT1:
|
||||
case (uint)XTXImageFormat.DXT3:
|
||||
case (uint)XTXImageFormat.DXT5:
|
||||
case (uint)XTXImageFormat.BC4U:
|
||||
case (uint)XTXImageFormat.BC4S:
|
||||
case (uint)XTXImageFormat.BC5U:
|
||||
case (uint)XTXImageFormat.BC5S:
|
||||
case 0x2d:
|
||||
return 0x44;
|
||||
|
||||
default: return 0x11;
|
||||
}
|
||||
}
|
||||
|
||||
public static uint bpps(uint format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_R8:
|
||||
return 1;
|
||||
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGBA8:
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGBA8_SRGB:
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGB10A2:
|
||||
return 4;
|
||||
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGB565:
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGB5A1:
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RGBA4:
|
||||
case (uint)XTXImageFormat.NVN_FORMAT_RG8:
|
||||
return 2;
|
||||
|
||||
case (uint)XTXImageFormat.DXT1:
|
||||
case (uint)XTXImageFormat.BC4S:
|
||||
case (uint)XTXImageFormat.BC4U:
|
||||
return 8;
|
||||
|
||||
case (uint)XTXImageFormat.DXT3:
|
||||
case (uint)XTXImageFormat.DXT5:
|
||||
case (uint)XTXImageFormat.BC5U:
|
||||
case (uint)XTXImageFormat.BC5S:
|
||||
return 16;
|
||||
default: return 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class XTXFile : TreeNodeFile
|
||||
{
|
||||
public uint HeaderSize { get; set; }
|
||||
public uint MajorVersion { get; set; }
|
||||
public uint MinorVersion { get; set; }
|
||||
public BlockHeader blockHeader { get; set; }
|
||||
private const int texHeadBlkType = 2;
|
||||
private const int dataBlkType = 3;
|
||||
|
||||
public void LoadFile(byte[] data)
|
||||
{
|
||||
FileReader reader = new FileReader(new MemoryStream(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();
|
||||
|
||||
blockHeader = new BlockHeader();
|
||||
blockHeader.Read(reader);
|
||||
}
|
||||
|
||||
public override void OnClick(TreeView treeview)
|
||||
{
|
||||
UpdateEditor();
|
||||
}
|
||||
|
||||
public void UpdateEditor()
|
||||
{
|
||||
NuTexEditor docked = (NuTexEditor)LibraryGUI.Instance.GetContentDocked(new NuTexEditor());
|
||||
if (docked == null)
|
||||
{
|
||||
docked = new NuTexEditor();
|
||||
LibraryGUI.Instance.LoadDockContent(docked, PluginRuntime.FSHPDockState);
|
||||
}
|
||||
docked.Text = Text;
|
||||
docked.Dock = DockStyle.Fill;
|
||||
}
|
||||
|
||||
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 TextureInfo textureInfo { get; set; }
|
||||
public long DataOffset;
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
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();
|
||||
|
||||
if (BlockType == texHeadBlkType)
|
||||
{
|
||||
textureInfo = new TextureInfo();
|
||||
textureInfo.Read(reader);
|
||||
}
|
||||
if (BlockType == dataBlkType)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public class TextureInfo : TreeNodeFile
|
||||
{
|
||||
public UInt64 DataSize { get; set; }
|
||||
public uint Alignment { get; set; }
|
||||
public uint Width { get; set; }
|
||||
public uint Height { get; set; }
|
||||
public uint Depth { get; set; }
|
||||
public uint Target { get; set; }
|
||||
public XTXFormats.XTXImageFormat Format { get; set; }
|
||||
public uint MipCount { get; set; }
|
||||
public uint SliceSize { get; set; }
|
||||
public uint[] MipOffsets { get; set; }
|
||||
public BlockHeader DataBlockHeader { get; set; }
|
||||
public List<byte[]> mipmaps = new List<byte[]>();
|
||||
public byte[] data;
|
||||
|
||||
public void Read(FileReader reader)
|
||||
{
|
||||
DataSize = reader.ReadUInt64();
|
||||
Alignment = reader.ReadUInt32();
|
||||
Width = reader.ReadUInt32();
|
||||
Height = reader.ReadUInt32();
|
||||
Depth = reader.ReadUInt32();
|
||||
Target = reader.ReadUInt32();
|
||||
Format = reader.ReadEnum<XTXFormats.XTXImageFormat>(true);
|
||||
MipCount = reader.ReadUInt32();
|
||||
SliceSize = reader.ReadUInt32();
|
||||
long offPos = reader.Position;
|
||||
MipOffsets = reader.ReadUInt32s((int)MipCount);
|
||||
|
||||
reader.Seek(offPos + 68, SeekOrigin.Begin);
|
||||
byte[] Layout = reader.ReadBytes(8);
|
||||
byte Sparse = reader.ReadByte();
|
||||
reader.Seek(3);
|
||||
long DataBlockOff = reader.Position;
|
||||
|
||||
DataBlockHeader = new BlockHeader();
|
||||
DataBlockHeader.Read(reader);
|
||||
|
||||
reader.Seek(DataBlockOff + DataBlockHeader.DataOffset, SeekOrigin.Begin);
|
||||
data = reader.ReadBytes((int)DataBlockHeader.DataSize);
|
||||
|
||||
BlockHeader EndBlockHeader = new BlockHeader();
|
||||
EndBlockHeader.Read(reader);
|
||||
}
|
||||
|
||||
public Bitmap DisplayImage(int mipLevel = 0, int arrayLevel = 0)
|
||||
{
|
||||
LoadTexture();
|
||||
|
||||
Bitmap decomp;
|
||||
|
||||
if (Format == XTXFormats.XTXImageFormat.BC5S)
|
||||
return DDSCompressor.DecompressBC5(mipmaps[0], (int)Width, (int)Height, true);
|
||||
|
||||
byte[] d = null;
|
||||
if (IsCompressedFormat(Format))
|
||||
d = DDSCompressor.DecompressBlock(mipmaps[0], (int)Width, (int)Height, GetCompressedDXGI_FORMAT(Format));
|
||||
else
|
||||
d = DDSCompressor.DecodePixelBlock(mipmaps[0], (int)Width, (int)Height, GetUncompressedDXGI_FORMAT(Format));
|
||||
|
||||
if (d != null)
|
||||
{
|
||||
decomp = BitmapExtension.GetBitmap(d, (int)Width, (int)Height);
|
||||
return TextureData.SwapBlueRedChannels(decomp);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static DDS.DXGI_FORMAT GetCompressedDXGI_FORMAT(XTXFormats.XTXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case XTXFormats.XTXImageFormat.DXT1: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
|
||||
case XTXFormats.XTXImageFormat.DXT3: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM;
|
||||
case XTXFormats.XTXImageFormat.DXT5: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
|
||||
case XTXFormats.XTXImageFormat.BC4U: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM;
|
||||
case XTXFormats.XTXImageFormat.BC4S: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM;
|
||||
case XTXFormats.XTXImageFormat.BC5U: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM;
|
||||
case XTXFormats.XTXImageFormat.BC5S: return DDS.DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM;
|
||||
default:
|
||||
throw new Exception($"Cannot convert format {Format}");
|
||||
}
|
||||
}
|
||||
private static bool IsCompressedFormat(XTXFormats.XTXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case XTXFormats.XTXImageFormat.DXT1:
|
||||
case XTXFormats.XTXImageFormat.DXT3:
|
||||
case XTXFormats.XTXImageFormat.DXT5:
|
||||
case XTXFormats.XTXImageFormat.BC4U:
|
||||
case XTXFormats.XTXImageFormat.BC4S:
|
||||
case XTXFormats.XTXImageFormat.BC5U:
|
||||
case XTXFormats.XTXImageFormat.BC5S:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static DDS.DXGI_FORMAT GetUncompressedDXGI_FORMAT(XTXFormats.XTXImageFormat Format)
|
||||
{
|
||||
switch (Format)
|
||||
{
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_R8: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RG8: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGB10A2: return DDS.DXGI_FORMAT.DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGB565: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G6R5_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGB5A1: return DDS.DXGI_FORMAT.DXGI_FORMAT_B5G5R5A1_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGBA4: return DDS.DXGI_FORMAT.DXGI_FORMAT_B4G4R4A4_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGBA8: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case XTXFormats.XTXImageFormat.NVN_FORMAT_RGBA8_SRGB: return DDS.DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
default:
|
||||
throw new Exception($"Cannot convert format {Format}");
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadTexture()
|
||||
{
|
||||
mipmaps.Clear();
|
||||
|
||||
Console.WriteLine(Format);
|
||||
|
||||
uint blk_dim = XTXFormats.blk_dims((uint)((int)Format >> 8));
|
||||
uint blkWidth = blk_dim >> 4;
|
||||
uint blkHeight = blk_dim & 0xF;
|
||||
|
||||
uint blockHeight = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
|
||||
uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
|
||||
|
||||
int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;
|
||||
|
||||
int TileMode = 0;
|
||||
|
||||
uint bpp = XTXFormats.bpps((uint)Format);
|
||||
|
||||
int blockHeightShift = 0;
|
||||
for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
|
||||
{
|
||||
uint width = (uint)Math.Max(1, Width >> mipLevel);
|
||||
uint height = (uint)Math.Max(1, Height >> mipLevel);
|
||||
|
||||
// uint size = width * height * bpp;
|
||||
uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;
|
||||
|
||||
byte[] mipData = GetMipBlock(MipOffsets[mipLevel], size);
|
||||
|
||||
if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
|
||||
blockHeightShift += 1;
|
||||
|
||||
byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, (int)Target, bpp, (uint)TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), mipData);
|
||||
//Create a copy and use that to remove uneeded data
|
||||
byte[] result_ = new byte[size];
|
||||
Array.Copy(result, 0, result_, 0, size);
|
||||
|
||||
mipmaps.Add(result_);
|
||||
Console.WriteLine("bpp " + bpp);
|
||||
Console.WriteLine("result_ " + size);
|
||||
Console.WriteLine("width " + width);
|
||||
Console.WriteLine("height " + height);
|
||||
}
|
||||
}
|
||||
private byte[] GetMipBlock(uint offset, uint Size)
|
||||
{
|
||||
FileReader reader = new FileReader(new MemoryStream(data));
|
||||
reader.Seek(offset, SeekOrigin.Begin);
|
||||
return reader.ReadBytes((int)Size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,6 +481,9 @@ namespace FirstPlugin
|
||||
|
||||
private void btnSamplerEditor_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (textureRefListView.SelectedItems.Count <= 0)
|
||||
return;
|
||||
|
||||
SamplerEditor samplerEditor = new SamplerEditor();
|
||||
foreach (MatTexture tex in material.textures)
|
||||
{
|
||||
@ -489,7 +492,6 @@ namespace FirstPlugin
|
||||
samplerEditor.LoadSampler(tex);
|
||||
}
|
||||
}
|
||||
|
||||
if (samplerEditor.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
|
||||
@ -499,9 +501,9 @@ namespace FirstPlugin
|
||||
private void textureRefListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (textureRefListView.SelectedItems.Count > 0)
|
||||
{
|
||||
btnSamplerEditor.Enabled = true;
|
||||
}
|
||||
else
|
||||
btnSamplerEditor.Enabled = false;
|
||||
}
|
||||
|
||||
private void shaderOptionsListView_ColumnClick(object sender, ColumnClickEventArgs e)
|
||||
|
353
Switch_FileFormatsMain/GUI/NuTexEditor.Designer.cs
generated
Normal file
353
Switch_FileFormatsMain/GUI/NuTexEditor.Designer.cs
generated
Normal file
@ -0,0 +1,353 @@
|
||||
namespace FirstPlugin
|
||||
{
|
||||
partial class NuTexEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NuTexEditor));
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
|
||||
this.splitter1 = new System.Windows.Forms.Splitter();
|
||||
this.panel2 = new System.Windows.Forms.Panel();
|
||||
this.panel4 = new System.Windows.Forms.Panel();
|
||||
this.pictureBoxCustom1 = new Switch_Toolbox.Library.Forms.PictureBoxCustom();
|
||||
this.panel3 = new System.Windows.Forms.Panel();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.arrayLevelCounterLabel = new System.Windows.Forms.Label();
|
||||
this.btnRightArray = new System.Windows.Forms.Button();
|
||||
this.btnLeftArray = new System.Windows.Forms.Button();
|
||||
this.imageBGComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.texSizeMipsLabel = new System.Windows.Forms.Label();
|
||||
this.mipLevelCounterLabel = new System.Windows.Forms.Label();
|
||||
this.BtnMipsRight = new System.Windows.Forms.Button();
|
||||
this.BtmMipsLeft = new System.Windows.Forms.Button();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.replaceSurfaceLevelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.exportSurfaceLevelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.panel1.SuspendLayout();
|
||||
this.panel2.SuspendLayout();
|
||||
this.panel4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).BeginInit();
|
||||
this.panel3.SuspendLayout();
|
||||
this.contextMenuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.panel1.Controls.Add(this.propertyGrid1);
|
||||
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(593, 296);
|
||||
this.panel1.TabIndex = 1;
|
||||
//
|
||||
// propertyGrid1
|
||||
//
|
||||
this.propertyGrid1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.propertyGrid1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
|
||||
this.propertyGrid1.CategoryForeColor = System.Drawing.Color.WhiteSmoke;
|
||||
this.propertyGrid1.CategorySplitterColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.propertyGrid1.CommandsActiveLinkColor = System.Drawing.Color.Red;
|
||||
this.propertyGrid1.CommandsBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(50)))), ((int)(((byte)(50)))));
|
||||
this.propertyGrid1.CommandsDisabledLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(50)))), ((int)(((byte)(50)))));
|
||||
this.propertyGrid1.CommandsForeColor = System.Drawing.Color.White;
|
||||
this.propertyGrid1.DisabledItemForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(127)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
|
||||
this.propertyGrid1.HelpBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
|
||||
this.propertyGrid1.HelpBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(45)))));
|
||||
this.propertyGrid1.HelpForeColor = System.Drawing.Color.White;
|
||||
this.propertyGrid1.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.propertyGrid1.Location = new System.Drawing.Point(0, 0);
|
||||
this.propertyGrid1.Name = "propertyGrid1";
|
||||
this.propertyGrid1.SelectedItemWithFocusForeColor = System.Drawing.Color.Silver;
|
||||
this.propertyGrid1.Size = new System.Drawing.Size(593, 299);
|
||||
this.propertyGrid1.TabIndex = 2;
|
||||
this.propertyGrid1.ToolbarVisible = false;
|
||||
this.propertyGrid1.ViewBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(40)))), ((int)(((byte)(40)))));
|
||||
this.propertyGrid1.ViewBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.propertyGrid1.ViewForeColor = System.Drawing.Color.White;
|
||||
this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged);
|
||||
//
|
||||
// splitter1
|
||||
//
|
||||
this.splitter1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.splitter1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.splitter1.Location = new System.Drawing.Point(0, 296);
|
||||
this.splitter1.Name = "splitter1";
|
||||
this.splitter1.Size = new System.Drawing.Size(593, 3);
|
||||
this.splitter1.TabIndex = 2;
|
||||
this.splitter1.TabStop = false;
|
||||
//
|
||||
// panel2
|
||||
//
|
||||
this.panel2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.panel2.Controls.Add(this.panel4);
|
||||
this.panel2.Controls.Add(this.panel3);
|
||||
this.panel2.Controls.Add(this.button1);
|
||||
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.panel2.Location = new System.Drawing.Point(0, 299);
|
||||
this.panel2.Name = "panel2";
|
||||
this.panel2.Size = new System.Drawing.Size(593, 297);
|
||||
this.panel2.TabIndex = 3;
|
||||
//
|
||||
// panel4
|
||||
//
|
||||
this.panel4.Controls.Add(this.pictureBoxCustom1);
|
||||
this.panel4.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.panel4.Location = new System.Drawing.Point(0, 80);
|
||||
this.panel4.Name = "panel4";
|
||||
this.panel4.Size = new System.Drawing.Size(593, 217);
|
||||
this.panel4.TabIndex = 4;
|
||||
//
|
||||
// pictureBoxCustom1
|
||||
//
|
||||
this.pictureBoxCustom1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.pictureBoxCustom1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBoxCustom1.BackgroundImage")));
|
||||
this.pictureBoxCustom1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pictureBoxCustom1.Location = new System.Drawing.Point(0, 0);
|
||||
this.pictureBoxCustom1.Name = "pictureBoxCustom1";
|
||||
this.pictureBoxCustom1.Size = new System.Drawing.Size(593, 217);
|
||||
this.pictureBoxCustom1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pictureBoxCustom1.TabIndex = 0;
|
||||
this.pictureBoxCustom1.TabStop = false;
|
||||
//
|
||||
// panel3
|
||||
//
|
||||
this.panel3.Controls.Add(this.label5);
|
||||
this.panel3.Controls.Add(this.arrayLevelCounterLabel);
|
||||
this.panel3.Controls.Add(this.btnRightArray);
|
||||
this.panel3.Controls.Add(this.btnLeftArray);
|
||||
this.panel3.Controls.Add(this.imageBGComboBox);
|
||||
this.panel3.Controls.Add(this.label1);
|
||||
this.panel3.Controls.Add(this.texSizeMipsLabel);
|
||||
this.panel3.Controls.Add(this.mipLevelCounterLabel);
|
||||
this.panel3.Controls.Add(this.BtnMipsRight);
|
||||
this.panel3.Controls.Add(this.BtmMipsLeft);
|
||||
this.panel3.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panel3.Location = new System.Drawing.Point(0, 25);
|
||||
this.panel3.Name = "panel3";
|
||||
this.panel3.Size = new System.Drawing.Size(593, 55);
|
||||
this.panel3.TabIndex = 2;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.ForeColor = System.Drawing.Color.White;
|
||||
this.label5.Location = new System.Drawing.Point(342, 30);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(74, 13);
|
||||
this.label5.TabIndex = 9;
|
||||
this.label5.Text = "Array Counter:";
|
||||
//
|
||||
// arrayLevelCounterLabel
|
||||
//
|
||||
this.arrayLevelCounterLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.arrayLevelCounterLabel.AutoSize = true;
|
||||
this.arrayLevelCounterLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.arrayLevelCounterLabel.Location = new System.Drawing.Point(415, 30);
|
||||
this.arrayLevelCounterLabel.Name = "arrayLevelCounterLabel";
|
||||
this.arrayLevelCounterLabel.Size = new System.Drawing.Size(42, 13);
|
||||
this.arrayLevelCounterLabel.TabIndex = 8;
|
||||
this.arrayLevelCounterLabel.Text = "00 / 00";
|
||||
//
|
||||
// btnRightArray
|
||||
//
|
||||
this.btnRightArray.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnRightArray.Location = new System.Drawing.Point(533, 26);
|
||||
this.btnRightArray.Name = "btnRightArray";
|
||||
this.btnRightArray.Size = new System.Drawing.Size(57, 21);
|
||||
this.btnRightArray.TabIndex = 7;
|
||||
this.btnRightArray.Text = ">";
|
||||
this.btnRightArray.UseVisualStyleBackColor = true;
|
||||
this.btnRightArray.Click += new System.EventHandler(this.btnRightArray_Click);
|
||||
//
|
||||
// btnLeftArray
|
||||
//
|
||||
this.btnLeftArray.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnLeftArray.Enabled = false;
|
||||
this.btnLeftArray.Location = new System.Drawing.Point(470, 26);
|
||||
this.btnLeftArray.Name = "btnLeftArray";
|
||||
this.btnLeftArray.Size = new System.Drawing.Size(57, 21);
|
||||
this.btnLeftArray.TabIndex = 6;
|
||||
this.btnLeftArray.Text = "<";
|
||||
this.btnLeftArray.UseVisualStyleBackColor = true;
|
||||
this.btnLeftArray.Click += new System.EventHandler(this.btnLeftArray_Click);
|
||||
//
|
||||
// imageBGComboBox
|
||||
//
|
||||
this.imageBGComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.imageBGComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.imageBGComboBox.FormattingEnabled = true;
|
||||
this.imageBGComboBox.Location = new System.Drawing.Point(215, 7);
|
||||
this.imageBGComboBox.Name = "imageBGComboBox";
|
||||
this.imageBGComboBox.Size = new System.Drawing.Size(121, 21);
|
||||
this.imageBGComboBox.TabIndex = 5;
|
||||
this.imageBGComboBox.SelectedIndexChanged += new System.EventHandler(this.imageBGComboBox_SelectedIndexChanged);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.ForeColor = System.Drawing.Color.White;
|
||||
this.label1.Location = new System.Drawing.Point(342, 7);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(67, 13);
|
||||
this.label1.TabIndex = 4;
|
||||
this.label1.Text = "Mip Counter:";
|
||||
//
|
||||
// texSizeMipsLabel
|
||||
//
|
||||
this.texSizeMipsLabel.AutoSize = true;
|
||||
this.texSizeMipsLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.texSizeMipsLabel.Location = new System.Drawing.Point(127, 34);
|
||||
this.texSizeMipsLabel.Name = "texSizeMipsLabel";
|
||||
this.texSizeMipsLabel.Size = new System.Drawing.Size(42, 13);
|
||||
this.texSizeMipsLabel.TabIndex = 3;
|
||||
this.texSizeMipsLabel.Text = "00 / 00";
|
||||
//
|
||||
// mipLevelCounterLabel
|
||||
//
|
||||
this.mipLevelCounterLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.mipLevelCounterLabel.AutoSize = true;
|
||||
this.mipLevelCounterLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.mipLevelCounterLabel.Location = new System.Drawing.Point(415, 7);
|
||||
this.mipLevelCounterLabel.Name = "mipLevelCounterLabel";
|
||||
this.mipLevelCounterLabel.Size = new System.Drawing.Size(42, 13);
|
||||
this.mipLevelCounterLabel.TabIndex = 2;
|
||||
this.mipLevelCounterLabel.Text = "00 / 00";
|
||||
//
|
||||
// BtnMipsRight
|
||||
//
|
||||
this.BtnMipsRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.BtnMipsRight.Location = new System.Drawing.Point(533, 3);
|
||||
this.BtnMipsRight.Name = "BtnMipsRight";
|
||||
this.BtnMipsRight.Size = new System.Drawing.Size(57, 21);
|
||||
this.BtnMipsRight.TabIndex = 1;
|
||||
this.BtnMipsRight.Text = ">";
|
||||
this.BtnMipsRight.UseVisualStyleBackColor = true;
|
||||
this.BtnMipsRight.Click += new System.EventHandler(this.BtnMipsRight_Click);
|
||||
//
|
||||
// BtmMipsLeft
|
||||
//
|
||||
this.BtmMipsLeft.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.BtmMipsLeft.Enabled = false;
|
||||
this.BtmMipsLeft.Location = new System.Drawing.Point(470, 3);
|
||||
this.BtmMipsLeft.Name = "BtmMipsLeft";
|
||||
this.BtmMipsLeft.Size = new System.Drawing.Size(57, 21);
|
||||
this.BtmMipsLeft.TabIndex = 0;
|
||||
this.BtmMipsLeft.Text = "<";
|
||||
this.BtmMipsLeft.UseVisualStyleBackColor = true;
|
||||
this.BtmMipsLeft.Click += new System.EventHandler(this.BtmMipsLeft_Click);
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.button1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.button1.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(90)))), ((int)(((byte)(90)))), ((int)(((byte)(90)))));
|
||||
this.button1.FlatAppearance.MouseDownBackColor = System.Drawing.Color.Gray;
|
||||
this.button1.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(90)))), ((int)(((byte)(90)))), ((int)(((byte)(90)))));
|
||||
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.button1.ForeColor = System.Drawing.Color.White;
|
||||
this.button1.Location = new System.Drawing.Point(0, 0);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(593, 25);
|
||||
this.button1.TabIndex = 1;
|
||||
this.button1.Text = "Hide";
|
||||
this.button1.UseVisualStyleBackColor = false;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// contextMenuStrip1
|
||||
//
|
||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.replaceSurfaceLevelToolStripMenuItem,
|
||||
this.exportSurfaceLevelToolStripMenuItem});
|
||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
this.contextMenuStrip1.Size = new System.Drawing.Size(188, 48);
|
||||
//
|
||||
// replaceSurfaceLevelToolStripMenuItem
|
||||
//
|
||||
this.replaceSurfaceLevelToolStripMenuItem.Name = "replaceSurfaceLevelToolStripMenuItem";
|
||||
this.replaceSurfaceLevelToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
||||
this.replaceSurfaceLevelToolStripMenuItem.Text = "Replace Surface Level";
|
||||
//
|
||||
// exportSurfaceLevelToolStripMenuItem
|
||||
//
|
||||
this.exportSurfaceLevelToolStripMenuItem.Name = "exportSurfaceLevelToolStripMenuItem";
|
||||
this.exportSurfaceLevelToolStripMenuItem.Size = new System.Drawing.Size(187, 22);
|
||||
this.exportSurfaceLevelToolStripMenuItem.Text = "Export Surface Level";
|
||||
//
|
||||
// NuTexEditor
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.panel2);
|
||||
this.Controls.Add(this.splitter1);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Name = "NuTexEditor";
|
||||
this.Size = new System.Drawing.Size(593, 596);
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel2.ResumeLayout(false);
|
||||
this.panel4.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxCustom1)).EndInit();
|
||||
this.panel3.ResumeLayout(false);
|
||||
this.panel3.PerformLayout();
|
||||
this.contextMenuStrip1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Splitter splitter1;
|
||||
private System.Windows.Forms.Panel panel2;
|
||||
private Switch_Toolbox.Library.Forms.PictureBoxCustom pictureBoxCustom1;
|
||||
private System.Windows.Forms.PropertyGrid propertyGrid1;
|
||||
private System.Windows.Forms.Panel panel4;
|
||||
private System.Windows.Forms.Panel panel3;
|
||||
private System.Windows.Forms.Label mipLevelCounterLabel;
|
||||
private System.Windows.Forms.Button BtnMipsRight;
|
||||
private System.Windows.Forms.Button BtmMipsLeft;
|
||||
private System.Windows.Forms.Label texSizeMipsLabel;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.ComboBox imageBGComboBox;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Label arrayLevelCounterLabel;
|
||||
private System.Windows.Forms.Button btnRightArray;
|
||||
private System.Windows.Forms.Button btnLeftArray;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem replaceSurfaceLevelToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem exportSurfaceLevelToolStripMenuItem;
|
||||
}
|
||||
}
|
207
Switch_FileFormatsMain/GUI/NuTexEditor.cs
Normal file
207
Switch_FileFormatsMain/GUI/NuTexEditor.cs
Normal file
@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using Syroot.NintenTools.NSW.Bntx;
|
||||
using Syroot.NintenTools.NSW.Bntx.GFX;
|
||||
using Switch_Toolbox.Library;
|
||||
|
||||
namespace FirstPlugin
|
||||
{
|
||||
public partial class NuTexEditor : UserControl
|
||||
{
|
||||
private Thread Thread;
|
||||
|
||||
public NuTexEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
foreach (var type in Enum.GetValues(typeof(Runtime.PictureBoxBG)).Cast<Runtime.PictureBoxBG>())
|
||||
imageBGComboBox.Items.Add(type);
|
||||
|
||||
imageBGComboBox.SelectedItem = Runtime.pictureBoxStyle;
|
||||
UpdateBackgroundImage();
|
||||
}
|
||||
|
||||
NUTEXB.NuTex textureData;
|
||||
int CurMipDisplayLevel = 0;
|
||||
int CurArrayDisplayLevel = 0;
|
||||
|
||||
class PropGridData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Format { get; set; }
|
||||
public uint Width { get; set; }
|
||||
public uint Height { get; set; }
|
||||
public uint MipCount { get; set; }
|
||||
public uint ArrayCount { get; set; }
|
||||
}
|
||||
|
||||
public void LoadProperty(NUTEXB.NuTex tex)
|
||||
{
|
||||
pictureBoxCustom1.Image = Imaging.GetLoadingImage();
|
||||
LoadImage();
|
||||
|
||||
CurMipDisplayLevel = 0;
|
||||
CurArrayDisplayLevel = 0;
|
||||
|
||||
textureData = tex;
|
||||
|
||||
UpdateMipDisplay();
|
||||
|
||||
PropGridData prop = new PropGridData();
|
||||
prop.Name = textureData.Text;
|
||||
prop.Width = textureData.Width;
|
||||
prop.Height = textureData.Height;
|
||||
// prop.MipCount = (uint)textureData.blocksCompressed[0].Count;
|
||||
// prop.ArrayCount = (uint)textureData.blocksCompressed.Count;
|
||||
prop.Height = textureData.Height;
|
||||
|
||||
prop.Format = ((NUTEXB.NUTEXImageFormat)textureData.Format).ToString();
|
||||
|
||||
propertyGrid1.PropertySort = PropertySort.Categorized;
|
||||
propertyGrid1.SelectedObject = prop;
|
||||
}
|
||||
private void LoadImage()
|
||||
{
|
||||
if (Thread != null && Thread.IsAlive)
|
||||
Thread.Abort();
|
||||
|
||||
Thread = new Thread((ThreadStart)(() =>
|
||||
{
|
||||
pictureBoxCustom1.Image = textureData.DisplayTexture(CurMipDisplayLevel, CurArrayDisplayLevel);
|
||||
}));
|
||||
Thread.Start();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
private void UpdateMipDisplay()
|
||||
{
|
||||
LoadImage();
|
||||
|
||||
int MipCount = 1;
|
||||
if (textureData.mipmaps.Count <= 0)
|
||||
return;
|
||||
else
|
||||
MipCount = textureData.mipmaps[CurArrayDisplayLevel].Count;
|
||||
|
||||
|
||||
mipLevelCounterLabel.Text = $"{CurMipDisplayLevel} / {textureData.mipmaps[CurArrayDisplayLevel].Count - 1}";
|
||||
arrayLevelCounterLabel.Text = $"{CurArrayDisplayLevel} / {textureData.mipmaps.Count - 1}";
|
||||
|
||||
if (CurMipDisplayLevel != MipCount - 1)
|
||||
BtnMipsRight.Enabled = true;
|
||||
else
|
||||
BtnMipsRight.Enabled = false;
|
||||
|
||||
if (CurMipDisplayLevel != 0)
|
||||
BtmMipsLeft.Enabled = true;
|
||||
else
|
||||
BtmMipsLeft.Enabled = false;
|
||||
|
||||
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
|
||||
btnRightArray.Enabled = true;
|
||||
else
|
||||
btnRightArray.Enabled = false;
|
||||
|
||||
if (CurArrayDisplayLevel != 0)
|
||||
btnLeftArray.Enabled = true;
|
||||
else
|
||||
btnLeftArray.Enabled = false;
|
||||
}
|
||||
|
||||
bool IsHidden = false;
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (IsHidden)
|
||||
{
|
||||
panel1.Visible = true;
|
||||
IsHidden = false;
|
||||
button1.Text = "Hide";
|
||||
}
|
||||
else
|
||||
{
|
||||
panel1.Visible = false;
|
||||
IsHidden = true;
|
||||
button1.Text = "Show";
|
||||
}
|
||||
}
|
||||
|
||||
private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
|
||||
{
|
||||
if (propertyGrid1.SelectedObject != null)
|
||||
{
|
||||
Texture tex = (Texture)propertyGrid1.SelectedObject;
|
||||
textureData.Text = tex.Name;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtmMipsLeft_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CurMipDisplayLevel != 0)
|
||||
CurMipDisplayLevel -= 1;
|
||||
|
||||
UpdateMipDisplay();
|
||||
}
|
||||
|
||||
private void BtnMipsRight_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CurMipDisplayLevel != textureData.mipmaps[CurArrayDisplayLevel].Count - 1)
|
||||
CurMipDisplayLevel += 1;
|
||||
|
||||
UpdateMipDisplay();
|
||||
}
|
||||
|
||||
private void btnLeftArray_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CurArrayDisplayLevel != 0)
|
||||
CurArrayDisplayLevel -= 1;
|
||||
|
||||
UpdateMipDisplay();
|
||||
}
|
||||
|
||||
private void btnRightArray_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (CurArrayDisplayLevel != textureData.mipmaps.Count - 1)
|
||||
CurArrayDisplayLevel += 1;
|
||||
|
||||
UpdateMipDisplay();
|
||||
}
|
||||
|
||||
|
||||
private void UpdateBackgroundImage()
|
||||
{
|
||||
switch (Runtime.pictureBoxStyle)
|
||||
{
|
||||
case Runtime.PictureBoxBG.Black:
|
||||
pictureBoxCustom1.BackColor = Color.Black;
|
||||
pictureBoxCustom1.BackgroundImage = null;
|
||||
break;
|
||||
case Runtime.PictureBoxBG.Checkerboard:
|
||||
pictureBoxCustom1.BackColor = Color.Transparent;
|
||||
pictureBoxCustom1.BackgroundImage = pictureBoxCustom1.GetCheckerBackground();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void imageBGComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
Runtime.pictureBoxStyle = (Runtime.PictureBoxBG)imageBGComboBox.SelectedItem;
|
||||
UpdateBackgroundImage();
|
||||
}
|
||||
|
||||
private void btnEdit_Click(object sender, EventArgs e)
|
||||
{
|
||||
Button btnSender = (Button)sender;
|
||||
Point ptLowerLeft = new Point(0, btnSender.Height);
|
||||
ptLowerLeft = btnSender.PointToScreen(ptLowerLeft);
|
||||
contextMenuStrip1.Show(ptLowerLeft);
|
||||
}
|
||||
}
|
||||
}
|
331
Switch_FileFormatsMain/GUI/NuTexEditor.resx
Normal file
331
Switch_FileFormatsMain/GUI/NuTexEditor.resx
Normal file
@ -0,0 +1,331 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBoxCustom1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAAlgAAAJYCAMAAACJuGjuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6
|
||||
JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAADAFBMVEXMzMzNzc3Ozs7Pz8/Q0NDR0dHS
|
||||
0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm
|
||||
5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6
|
||||
+vr7+/v8/Pz9/f3+/v7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
129
Switch_FileFormatsMain/GUI/TexturePatternEditor.Designer.cs
generated
Normal file
129
Switch_FileFormatsMain/GUI/TexturePatternEditor.Designer.cs
generated
Normal file
@ -0,0 +1,129 @@
|
||||
namespace FirstPlugin.GUI
|
||||
{
|
||||
partial class TexturePatternEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.listView1 = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.listView2 = new System.Windows.Forms.ListView();
|
||||
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.panel2 = new System.Windows.Forms.Panel();
|
||||
this.panel1.SuspendLayout();
|
||||
this.panel2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// listView1
|
||||
//
|
||||
this.listView1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader1,
|
||||
this.columnHeader2});
|
||||
this.listView1.Location = new System.Drawing.Point(281, 0);
|
||||
this.listView1.Name = "listView1";
|
||||
this.listView1.Size = new System.Drawing.Size(289, 480);
|
||||
this.listView1.TabIndex = 0;
|
||||
this.listView1.UseCompatibleStateImageBehavior = false;
|
||||
this.listView1.View = System.Windows.Forms.View.Details;
|
||||
//
|
||||
// columnHeader1
|
||||
//
|
||||
this.columnHeader1.Text = "Frame";
|
||||
this.columnHeader1.Width = 104;
|
||||
//
|
||||
// columnHeader2
|
||||
//
|
||||
this.columnHeader2.Text = "Texture";
|
||||
this.columnHeader2.Width = 168;
|
||||
//
|
||||
// listView2
|
||||
//
|
||||
this.listView2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||
this.columnHeader3});
|
||||
this.listView2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listView2.Location = new System.Drawing.Point(0, 0);
|
||||
this.listView2.Name = "listView2";
|
||||
this.listView2.Size = new System.Drawing.Size(282, 479);
|
||||
this.listView2.TabIndex = 1;
|
||||
this.listView2.UseCompatibleStateImageBehavior = false;
|
||||
this.listView2.View = System.Windows.Forms.View.Details;
|
||||
this.listView2.SelectedIndexChanged += new System.EventHandler(this.listView2_SelectedIndexChanged);
|
||||
//
|
||||
// columnHeader3
|
||||
//
|
||||
this.columnHeader3.Text = "Material";
|
||||
this.columnHeader3.Width = 190;
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Controls.Add(this.listView2);
|
||||
this.panel1.Dock = System.Windows.Forms.DockStyle.Left;
|
||||
this.panel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(282, 479);
|
||||
this.panel1.TabIndex = 3;
|
||||
//
|
||||
// panel2
|
||||
//
|
||||
this.panel2.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.panel2.Location = new System.Drawing.Point(576, 0);
|
||||
this.panel2.Name = "panel2";
|
||||
this.panel2.Size = new System.Drawing.Size(284, 479);
|
||||
this.panel2.TabIndex = 4;
|
||||
//
|
||||
// TexturePatternEditor
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
||||
this.ClientSize = new System.Drawing.Size(860, 479);
|
||||
this.Controls.Add(this.panel2);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Controls.Add(this.listView1);
|
||||
this.ForeColor = System.Drawing.Color.White;
|
||||
this.Name = "TexturePatternEditor";
|
||||
this.Text = "TexturePatternEditor";
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel2.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ListView listView1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
||||
private System.Windows.Forms.ListView listView2;
|
||||
private System.Windows.Forms.ColumnHeader columnHeader3;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.Panel panel2;
|
||||
}
|
||||
}
|
25
Switch_FileFormatsMain/GUI/TexturePatternEditor.cs
Normal file
25
Switch_FileFormatsMain/GUI/TexturePatternEditor.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FirstPlugin.GUI
|
||||
{
|
||||
public partial class TexturePatternEditor : Form
|
||||
{
|
||||
public TexturePatternEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void listView2_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
120
Switch_FileFormatsMain/GUI/TexturePatternEditor.resx
Normal file
120
Switch_FileFormatsMain/GUI/TexturePatternEditor.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@ -123,7 +123,7 @@ namespace FirstPlugin
|
||||
Formats.Add(typeof(BFLYT));
|
||||
Formats.Add(typeof(CsvModel));
|
||||
Formats.Add(typeof(GFPAK));
|
||||
|
||||
Formats.Add(typeof(NUTEXB));
|
||||
|
||||
return Formats.ToArray();
|
||||
}
|
||||
|
@ -172,6 +172,7 @@
|
||||
<Compile Include="FileFormats\Texture\FTEX.cs" />
|
||||
<Compile Include="FileFormats\Texture\GTX.cs" />
|
||||
<Compile Include="FileFormats\Texture\TegraX1Swizzle.cs" />
|
||||
<Compile Include="FileFormats\Texture\NUTEXB.cs" />
|
||||
<Compile Include="FileFormats\Texture\TexConv.cs" />
|
||||
<Compile Include="FileFormats\Texture\XTX.cs" />
|
||||
<Compile Include="GL\BFRES_Render.cs" />
|
||||
@ -266,6 +267,18 @@
|
||||
<DependentUpon>BfresShapeEditor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GUI\FormLoader.cs" />
|
||||
<Compile Include="GUI\NuTexEditor.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="GUI\NuTexEditor.Designer.cs">
|
||||
<DependentUpon>NuTexEditor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GUI\TexturePatternEditor.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="GUI\TexturePatternEditor.Designer.cs">
|
||||
<DependentUpon>TexturePatternEditor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GUI\TextureUI\FTEXEditor.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
@ -405,6 +418,12 @@
|
||||
<EmbeddedResource Include="GUI\BFRES\BfresShapeEditor.resx">
|
||||
<DependentUpon>BfresShapeEditor.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="GUI\NuTexEditor.resx">
|
||||
<DependentUpon>NuTexEditor.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="GUI\TexturePatternEditor.resx">
|
||||
<DependentUpon>TexturePatternEditor.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="GUI\TextureUI\FTEXEditor.resx">
|
||||
<DependentUpon>FTEXEditor.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
Binary file not shown.
BIN
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.pdb
Normal file
BIN
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.pdb
Normal file
Binary file not shown.
5730
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.xml
Normal file
5730
Switch_Toolbox/Lib/Syroot.NintenTools.Bfres.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -238,6 +238,7 @@ namespace Switch_Toolbox
|
||||
FileReader f = new FileReader(data);
|
||||
string Magic = f.ReadMagic(0, 4);
|
||||
string Magic2 = f.ReadMagic(0, 2);
|
||||
string Magic3 = f.ReadMagic((int)f.BaseStream.Length - 7, 3);
|
||||
|
||||
//Determine if the file is compressed or not
|
||||
if (Magic == "Yaz0")
|
||||
@ -268,7 +269,7 @@ namespace Switch_Toolbox
|
||||
//Check magic first regardless of extension
|
||||
foreach (IFileFormat format in SupportedFormats)
|
||||
{
|
||||
if (format.Magic == Magic || format.Magic == Magic2 || format.Magic.Reverse() == Magic2)
|
||||
if (format.Magic == Magic || format.Magic == Magic3 || format.Magic == Magic2 || format.Magic.Reverse() == Magic2)
|
||||
{
|
||||
format.CompressionType = CompType;
|
||||
format.FileIsCompressed = Compressed;
|
||||
|
@ -21,6 +21,5 @@ namespace Switch_Toolbox
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -367,9 +367,6 @@
|
||||
<Content Include="Lib\Syroot.NintenTools.NSW.Bntx.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Lib\texconv.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Lib\VGAudio.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -8,6 +8,7 @@ using Assimp;
|
||||
using Assimp.Configs;
|
||||
using OpenTK;
|
||||
using Switch_Toolbox.Library.Rendering;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Switch_Toolbox.Library
|
||||
{
|
||||
@ -30,6 +31,8 @@ namespace Switch_Toolbox.Library
|
||||
{
|
||||
}
|
||||
public void LoadFile(string FileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssimpContext Importer = new AssimpContext();
|
||||
|
||||
@ -38,6 +41,15 @@ namespace Switch_Toolbox.Library
|
||||
PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals);
|
||||
LoadMeshes();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.ToString().Contains("Error loading unmanaged library from path"))
|
||||
{
|
||||
MessageBox.Show($"Failed to load assimp! Make sure you have Assimp32.dll next to the program!");
|
||||
}
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
public void processNode()
|
||||
{
|
||||
Matrix4x4 identity = Matrix4x4.Identity;
|
||||
|
@ -325,9 +325,6 @@ namespace Switch_Toolbox.Library
|
||||
reader.TemporarySeek((int)(4 + header.size + DX10HeaderSize), SeekOrigin.Begin);
|
||||
bdata = reader.ReadBytes((int)(reader.BaseStream.Length - reader.Position));
|
||||
|
||||
|
||||
|
||||
|
||||
reader.Dispose();
|
||||
reader.Close();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user