Importing textures for bcmdl is possible now

And some older stuff I didn't commit yet.
This commit is contained in:
Gericom 2015-11-03 16:18:38 +01:00
parent 557c6efac2
commit f9f00d193c
20 changed files with 1121 additions and 504 deletions

View File

@ -43,11 +43,12 @@ namespace _3DS.NintendoWare.GFX
public string GetSaveDefaultFileFilter()
{
return "CTR Graphics Resource (*.bcres)|*.bcres";
return "CTR Graphics Resource (*.bcres;*.bcmdl)|*.bcres;*.bcmdl";
}
public byte[] Write()
{
//MessageBox.Show("CGFX saving is experimental! A couple of sections (like animations) are lost while saving!");
MemoryStream m = new MemoryStream();
EndianBinaryWriter er = new EndianBinaryWriter(m, Endianness.LittleEndian);
Header.NrBlocks = 1;
@ -224,9 +225,9 @@ namespace _3DS.NintendoWare.GFX
er.Write((uint)0);
for (int i = 0; i < 16; i++)
{
if (Dictionaries[i] != null)
if (Dictionaries[i] != null && (i == 0 || i == 1))
{
if (i != 0 && i != 1) throw new NotImplementedException();
//if (i != 0 && i != 1) throw new NotImplementedException();
er.Write((uint)Dictionaries[i].Count);
er.Write((uint)0);//dictoffset
}
@ -239,7 +240,7 @@ namespace _3DS.NintendoWare.GFX
long[] dictoffsets = new long[16];
for (int i = 0; i < 16; i++)
{
if (Dictionaries[i] != null)
if (Dictionaries[i] != null && (i == 0 || i == 1))
{
dictoffsets[i] = er.BaseStream.Position;
er.BaseStream.Position = basepos + 8 + i * 8 + 4;

View File

@ -44,8 +44,8 @@ namespace _3DS.NintendoWare.GFX
NrChildren = er.ReadUInt32();
Unknown7 = er.ReadUInt32();
NrAnimationGroupDescriptions = er.ReadUInt32();
AnimationGroupDescriptionsDictOffset =er.ReadUInt32();
if (AnimationGroupDescriptionsDictOffset != 0) AnimationGroupDescriptionsDictOffset += (UInt32)er.BaseStream.Position - 4;
AnimationGroupDescriptionsDictOffset = er.ReadUInt32();
if (AnimationGroupDescriptionsDictOffset != 0) AnimationGroupDescriptionsDictOffset += (UInt32)er.BaseStream.Position - 4;
Scale = er.ReadVector3();
Rotation = er.ReadVector3();
Translation = er.ReadVector3();
@ -3857,6 +3857,228 @@ namespace _3DS.NintendoWare.GFX
return o;
}
public String ToMayaASCII(CGFX Resource)
{
var er = new CommonFiles.Maya.MayaASCIIWriter();
if (Resource.Data.Textures != null)
{
foreach (var tex in Resource.Data.Textures)
{
er.CreateNode("file", tex.Name.Replace('.', '_') + "_tex");
er.BeginStatement("setAttr");
{
er.WriteArgument("\".ftn\"");
er.WriteArgument("-type", "\"string\"");
er.WriteArgument("\"Tex/" + tex.Name + ".png\"");
}
er.EndStatement();
er.CreateNode("place2dTexture", tex.Name.Replace('.', '_') + "_tex_p2d");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.c", tex.Name.Replace('.', '_') + "_tex.c");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.tf", tex.Name.Replace('.', '_') + "_tex.tf");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.rf", tex.Name.Replace('.', '_') + "_tex.rf");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.mu", tex.Name.Replace('.', '_') + "_tex.mu");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.mv", tex.Name.Replace('.', '_') + "_tex.mv");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.s", tex.Name.Replace('.', '_') + "_tex.s");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.wu", tex.Name.Replace('.', '_') + "_tex.wu");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.wv", tex.Name.Replace('.', '_') + "_tex.wv");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.re", tex.Name.Replace('.', '_') + "_tex.re");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.of", tex.Name.Replace('.', '_') + "_tex.of");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.r", tex.Name.Replace('.', '_') + "_tex.ro");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.n", tex.Name.Replace('.', '_') + "_tex.n");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.vt1", tex.Name.Replace('.', '_') + "_tex.vt1");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.vt2", tex.Name.Replace('.', '_') + "_tex.vt2");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.vt3", tex.Name.Replace('.', '_') + "_tex.vt3");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.vc1", tex.Name.Replace('.', '_') + "_tex.vc1");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.o", tex.Name.Replace('.', '_') + "_tex.uv");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex_p2d.ofs", tex.Name.Replace('.', '_') + "_tex.fs");
er.ConnectAttribute(tex.Name.Replace('.', '_') + "_tex.msg", ":defaultTextureList1.tx", true);
}
}
foreach (var mat in Materials)
{
er.CreateNode("phong", mat.Name.Replace('.', '_'));
er.BeginStatement("setAttr");
{
er.WriteArgument("\".dc\"", 1);
}
er.EndStatement();
er.CreateNode("shadingEngine", mat.Name.Replace('.', '_') + "_Sg");
er.BeginStatement("setAttr");
{
er.WriteArgument("\".ihi\"", 0);
}
er.EndStatement();
er.BeginStatement("setAttr");
{
er.WriteArgument("\".ro\"", "yes");
}
er.EndStatement();
er.CreateNode("materialInfo", mat.Name.Replace('.', '_') + "_In");
er.ConnectAttribute(mat.Name.Replace('.', '_') + ".oc", mat.Name.Replace('.', '_') + "_Sg.ss");
er.ConnectAttribute(mat.Name.Replace('.', '_') + "_Sg.msg", mat.Name.Replace('.', '_') + "_In.sg");
er.ConnectAttribute(mat.Name.Replace('.', '_') + ".msg", mat.Name.Replace('.', '_') + "_In.m");
er.ConnectAttribute(mat.Name.Replace('.', '_') + "_Sg.pa", ":renderPartition.st", true);
er.ConnectAttribute(mat.Name.Replace('.', '_') + ".msg", ":defaultShaderList1.s", true);
if (mat.Tex0 != null && mat.Tex0.TextureObject is ReferenceTexture)
{
er.ConnectAttribute(((ReferenceTexture)mat.Tex0.TextureObject).LinkedTextureName.Replace('.', '_') + "_tex.oc", mat.Name.Replace('.', '_') + ".c");
er.ConnectAttribute(((ReferenceTexture)mat.Tex0.TextureObject).LinkedTextureName.Replace('.', '_') + "_tex.msg", mat.Name.Replace('.', '_') + "_In.t", true);
}
}
int s = 0;
foreach (var vv in Shapes)
{
var mat = Materials[Meshes[s].MaterialIndex];
er.CreateNode("transform", "S" + s + "_trans");
er.CreateNode("mesh", "S" + s + "_mesh", "S" + s + "_trans");
Polygon p = vv.GetVertexData(this);
int cnt = 0;
foreach (var q in vv.PrimitiveSets[0].Primitives[0].IndexStreams)
{
Vector3[] defs = q.GetFaceData();
cnt += defs.Length;
}
if (p.TexCoords != null)
{
if (mat.NrActiveTextureCoordiators > 0 && mat.TextureCoordiators[0].MappingMethod == 0)
{
Vector2[] texc;
if (mat.TextureCoordiators[0].SourceCoordinate == 0)
{
texc = p.TexCoords;
}
else if (mat.TextureCoordiators[0].SourceCoordinate == 1)
{
texc = p.TexCoords2;
}
else
{
texc = p.TexCoords3;
}
er.BeginStatement("setAttr");
{
er.WriteArgument("\".uvst[0].uvsn\"");
er.WriteArgument("-type", "\"string\"");
er.WriteArgument("\"map1\"");
}
er.EndStatement();
er.BeginStatement("setAttr");
{
er.WriteArgument("-s", texc.Length);
er.WriteArgument("\".uvst[0].uvsp[0:" + (texc.Length - 1) + "]\"");
er.WriteArgument("-type", "\"float2\"");
foreach (var v in texc)
{
er.WriteArgument(v.X);
er.WriteArgument(v.Y);
}
}
er.EndStatement();
er.BeginStatement("setAttr");
{
er.WriteArgument("\".cuvs\"");
er.WriteArgument("-type", "\"string\"");
er.WriteArgument("\"map1\"");
}
er.EndStatement();
}
}
if (p.Vertex != null)
{
er.BeginStatement("setAttr");
{
er.WriteArgument("-s", p.Vertex.Length);
er.WriteArgument("\".vt[0:" + (p.Vertex.Length - 1) + "]\"");
foreach (var v in p.Vertex)
{
er.WriteArgument(v.X);
er.WriteArgument(v.Y);
er.WriteArgument(v.Z);
}
}
er.EndStatement();
er.BeginStatement("setAttr");
{
er.WriteArgument("-s", cnt * 3);
er.WriteArgument("\".ed[0:" + ((cnt * 3) - 1) + "]\"");
int idx = 0;
foreach (var q in vv.PrimitiveSets[0].Primitives[0].IndexStreams)
{
Vector3[] defs = q.GetFaceData();
foreach (Vector3 def in defs)
{
er.WriteArgument(def.X);
er.WriteArgument(def.Y);
er.WriteArgument(0);
er.WriteArgument(def.Y);
er.WriteArgument(def.Z);
er.WriteArgument(0);
er.WriteArgument(def.X);
er.WriteArgument(def.Z);
er.WriteArgument(0);
}
}
}
er.EndStatement();
}
if (p.Colors != null)
{
er.BeginStatement("setAttr");
{
er.WriteArgument("-s", p.Colors.Length);
er.WriteArgument("\".clr[0:" + (p.Colors.Length - 1) + "]\"");
foreach (var v in p.Colors)
{
er.WriteArgument(v.R / 255f);
er.WriteArgument(v.G / 255f);
er.WriteArgument(v.B / 255f);
er.WriteArgument(1);//v.A / 255f);
}
}
er.EndStatement();
}
er.BeginStatement("setAttr");
{
er.WriteArgument("-s", cnt);
er.WriteArgument("\".fc[0:" + (cnt - 1) + "]\"");
er.WriteArgument("-type", "\"polyFaces\"");
int idx = 0;
foreach (var q in vv.PrimitiveSets[0].Primitives[0].IndexStreams)
{
Vector3[] defs = q.GetFaceData();
foreach (Vector3 def in defs)
{
er.WriteArgument("\nf", 3);
er.WriteArgument(idx++);
er.WriteArgument(idx++);
er.WriteArgument(idx++);
er.WriteArgument("\nmu", 0);
er.WriteArgument(3);
er.WriteArgument(def.X);
er.WriteArgument(def.Y);
er.WriteArgument(def.Z);
if (p.Colors != null)
{
er.WriteArgument("\nfc");
er.WriteArgument(3);
er.WriteArgument(def.X);
er.WriteArgument(def.Y);
er.WriteArgument(def.Z);
}
}
}
}
er.EndStatement();
er.ConnectAttribute("S" + s + "_mesh.iog", Materials[Meshes[s].MaterialIndex].Name.Replace('.', '_') + "_Sg.dsm", true);
s++;
}
return er.Close();
}
public override string ToString()
{
return Name;

View File

@ -76,7 +76,8 @@
//
// saveFileDialog1
//
this.saveFileDialog1.Filter = "COLLADA DAE File (*.dae)|*.dae|Wavefront OBJ File (*.obj)|*.obj";
this.saveFileDialog1.Filter = "COLLADA DAE File (*.dae)|*.dae|Wavefront OBJ File (*.obj)|*.obj|Maya ASCII (*.ma)" +
"|*.ma";
//
// CMDLViewer
//

View File

@ -457,6 +457,19 @@ namespace _3DS.UI
}
break;
}
case 2:
{
String result = Model.ToMayaASCII(Resource);
File.Create(saveFileDialog1.FileName).Close();
File.WriteAllBytes(saveFileDialog1.FileName, Encoding.ASCII.GetBytes(result));
Directory.CreateDirectory(Path.GetDirectoryName(saveFileDialog1.FileName) + "\\Tex");
foreach (var v in Resource.Data.Textures)
{
if (!(v is ImageTextureCtr)) continue;
((ImageTextureCtr)v).GetBitmap().Save(Path.GetDirectoryName(saveFileDialog1.FileName) + "\\Tex\\" + v.Name + ".png");
}
break;
}
}
}
}

View File

@ -124,17 +124,17 @@
<data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI3SURBVDhPYxi6gLmM2R3KxALqGTiYS5hdmEuZO5lKmFYD
8R6mUqa96BiqGg0UM8gzFzLPVOtROh+xNeh11uHkHyUnc/6Xnsr9X3U+/3/zjZL/HXfL/zMVMO2D6kAC
WQzyXCUc6z2Xuj7N2JvyP3FbIhgnbY//n3c49X/Nxbz/DVcL/zffLPnPlIfugnigszOZZznNt38atznm
f9T6qP+R6yKAdAhQc9L/irPZcFx6JuMnUybTOqhOCGBOZnaVrZG5GL4m9H/Q8qD/3gu8gLTX/+wDCUAD
kpFwyv/YrUFvGVMYe6BaIYAxnrHXborNW58FPv8dpjr895jr/D95R8z/lJ2oGGSIWqPyJeYEZleoVghg
jGbc4DTD8af1BOv/Vv3mYKej4/gtEf+9l67/LVuRvUemsJATqhUCmEKZDtlOsvmvXqP232+x9/+Apb5w
HLjMF2yA6yy75wY9Bz6YT7552XzS3RioVghgCmA6ql6j/t95hiPYAP8lPmCNVhNm/TPq3P5Hu2nzN/X6
rW90Ws5cnv70/3+99ktndFrPQw2xZ+BhdGY8joFdGI/JFiz9MOnx//9ZV///j72IwMU3/v9Xrjx8BmKA
OUMRowVjB4MsgxREAAGE/DtmimdtPYOMLY7+/w+iJXK2QV2gz7CbgZ/BEcjSAmJVIJYHYgkgFgJiHiBm
B2ImIGbgiVl+BoR541aihAHIZpAGUSAWBmIBIAZpBIU0GxCzADEjEDOwBc6ZyRowG6qZgQEAZbYdbqlW
taMAAAAASUVORK5CYII=
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI3SURBVDhPYxi6gLmM2R3KxALqGTiYS5hdmEuZOxlLGFcD
8R7GUsa96BiqGg0UM8gzFzLPVOtROh++Neh15uGkHyUnc/6Xnsr9X3U+/3/zjZL/HXfL/zPmM+6D6kAC
WQzyXCXs6z2XuD7N2JvyP3FbIhgnbY//n3c49X/Nxbz/DVcL/zffLPnPmIfugnigszOYZznOt38atznm
f9T6qP+R6yKAdAhQc9L/irPZcFxyOuMnYybjOqhOCGBOZnaVrZG5GL4m9H/Q8qD/3gu8gLTX/+wDCUAD
kpFwyv+YLYFvGVMYe6BaIYAxnrHXborNW58FPv8dpjr895jr/D95R8z/lJ2oGGSIaoPyJeYEZleoVghg
jGbc4Djd4af1BOv/Vv3mYKej4/gtEf+9l6z7LVOevUemsJATqhUCmEKZDtlOsvmvXqP232+x9/+Apb5w
HLjMF2yA6yzb5/o9Bz6YT7552XzS3RioVghgCmA6ql6j/t95hiPYAP8lPmCNVv0z/xl2bP+j1bj5m1r9
1jfazWcuT3/6/79e+6UzOq3noYbYM/AwOjEex8AujMdk8pd8mPT4//+sq///x15E4OIb//8rVx4+AzHA
nKGI0YKxg0GWQQoigABCfh0zxbK2nkHGFkf//wfREjnboC7QY9jNwM/gCGRpAbEqEMsDsQQQCwExDxCz
AzETEDPwxCw/A8K8cStRwgBkM0iDKBALA7EAEIM0gkKaDYhZgJgRiBnYAufMZA2YDdXMwAAA4o0dKpJu
g5EAAAAASUVORK5CYII=
</value>
</data>
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">

View File

@ -28,96 +28,103 @@
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TXOBViewer));
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
this.toolStripComboBox1 = new System.Windows.Forms.ToolStripComboBox();
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
this.toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TXOBViewer));
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
this.toolStripComboBox1 = new System.Windows.Forms.ToolStripComboBox();
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripButton1,
this.toolStripButton2,
this.toolStripComboBox1,
this.toolStripLabel1});
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(464, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
//
// toolStripButton1
//
this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripButton1.Enabled = false;
this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton1.Name = "toolStripButton1";
this.toolStripButton1.Size = new System.Drawing.Size(23, 22);
this.toolStripButton1.Text = "Import";
//
// toolStripButton2
//
this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton2.Name = "toolStripButton2";
this.toolStripButton2.Size = new System.Drawing.Size(23, 22);
this.toolStripButton2.Text = "Export";
this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click);
//
// toolStripComboBox1
//
this.toolStripComboBox1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.toolStripComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.toolStripComboBox1.FlatStyle = System.Windows.Forms.FlatStyle.Standard;
this.toolStripComboBox1.Name = "toolStripComboBox1";
this.toolStripComboBox1.Size = new System.Drawing.Size(121, 25);
this.toolStripComboBox1.SelectedIndexChanged += new System.EventHandler(this.toolStripComboBox1_SelectedIndexChanged);
//
// toolStripLabel1
//
this.toolStripLabel1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.toolStripLabel1.Name = "toolStripLabel1";
this.toolStripLabel1.Size = new System.Drawing.Size(40, 22);
this.toolStripLabel1.Text = "Level: ";
//
// pictureBox1
//
this.pictureBox1.BackgroundImage = global::_3DS.Resource.preview_background;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 25);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(464, 308);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox1.TabIndex = 1;
this.pictureBox1.TabStop = false;
//
// saveFileDialog1
//
this.saveFileDialog1.Filter = "PNG Images (*.png)|*.png";
//
// TXOBViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.toolStrip1);
this.Name = "TXOBViewer";
this.Size = new System.Drawing.Size(464, 333);
this.Load += new System.EventHandler(this.TXOBViewer_Load);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(464, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
//
// toolStripButton1
//
this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton1.Name = "toolStripButton1";
this.toolStripButton1.Size = new System.Drawing.Size(23, 22);
this.toolStripButton1.Text = "Import";
this.toolStripButton1.Click += new System.EventHandler(this.toolStripButton1_Click);
//
// toolStripButton2
//
this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
this.toolStripButton2.Name = "toolStripButton2";
this.toolStripButton2.Size = new System.Drawing.Size(23, 22);
this.toolStripButton2.Text = "Export";
this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click);
//
// toolStripComboBox1
//
this.toolStripComboBox1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.toolStripComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.toolStripComboBox1.FlatStyle = System.Windows.Forms.FlatStyle.Standard;
this.toolStripComboBox1.Name = "toolStripComboBox1";
this.toolStripComboBox1.Size = new System.Drawing.Size(121, 25);
this.toolStripComboBox1.SelectedIndexChanged += new System.EventHandler(this.toolStripComboBox1_SelectedIndexChanged);
//
// toolStripLabel1
//
this.toolStripLabel1.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.toolStripLabel1.Name = "toolStripLabel1";
this.toolStripLabel1.Size = new System.Drawing.Size(40, 22);
this.toolStripLabel1.Text = "Level: ";
//
// pictureBox1
//
this.pictureBox1.BackgroundImage = global::_3DS.Resource.preview_background;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 25);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(464, 308);
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox1.TabIndex = 1;
this.pictureBox1.TabStop = false;
//
// saveFileDialog1
//
this.saveFileDialog1.Filter = "PNG Images (*.png)|*.png";
//
// openFileDialog1
//
this.openFileDialog1.DefaultExt = "png";
this.openFileDialog1.FileName = "openFileDialog1";
this.openFileDialog1.Filter = "PNG Images (*.png)|*.png";
//
// TXOBViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.pictureBox1);
this.Controls.Add(this.toolStrip1);
this.Name = "TXOBViewer";
this.Size = new System.Drawing.Size(464, 333);
this.Load += new System.EventHandler(this.TXOBViewer_Load);
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -130,5 +137,6 @@
private System.Windows.Forms.ToolStripComboBox toolStripComboBox1;
private System.Windows.Forms.ToolStripLabel toolStripLabel1;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
}
}

View File

@ -8,6 +8,8 @@ using System.Text;
using System.Windows.Forms;
using _3DS.NintendoWare.GFX;
using System.Drawing.Imaging;
using System.IO;
using _3DS.GPU;
namespace _3DS.UI
{
@ -43,5 +45,46 @@ namespace _3DS.UI
pictureBox1.Image.Save(saveFileDialog1.FileName, ImageFormat.Png);
}
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
if (Texture.HWFormat != Textures.ImageFormat.RGBA8 &&
Texture.HWFormat != Textures.ImageFormat.RGB8 &&
Texture.HWFormat != Textures.ImageFormat.RGB565 &&
Texture.HWFormat != Textures.ImageFormat.ETC1 &&
Texture.HWFormat != Textures.ImageFormat.ETC1A4)
{
MessageBox.Show("This texture format is currently not supported for importing.");
return;
}
if (openFileDialog1.ShowDialog() == DialogResult.OK
&& openFileDialog1.FileName.Length > 0)
{
Bitmap b = new Bitmap(new MemoryStream(File.ReadAllBytes(openFileDialog1.FileName)));
if (b.Width != Texture.Width && b.Height != Texture.Height)
{
MessageBox.Show("Make sure the texture is even big as the original texture! (" + Texture.Width + "x" + Texture.Height + ")");
return;
}
for (int i = 0; i < Texture.NrLevels; i++)
{
int l = i;
uint w = Texture.Width;
uint h = Texture.Height;
int bpp = Textures.GetBpp(Texture.HWFormat);
int offset = 0;
while (l > 0)
{
offset += (int)(w * h * bpp / 8);
w /= 2;
h /= 2;
l--;
}
byte[] result = Textures.FromBitmap(new Bitmap(b, (int)w, (int)h), Texture.HWFormat);
Array.Copy(result, 0, Texture.TextureImage.Data, offset, result.Length);
}
pictureBox1.Image = Texture.GetBitmap(toolStripComboBox1.SelectedIndex);
}
}
}
}

View File

@ -153,4 +153,7 @@
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>258, 17</value>
</metadata>
</root>

View File

@ -46,6 +46,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DAE.cs" />
<Compile Include="Maya\MayaASCIIWriter.cs" />
<Compile Include="MTL.cs" />
<Compile Include="OBJ.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace CommonFiles.Maya
{
public class MayaASCIIWriter
{
private StringWriter mWriter;
public MayaASCIIWriter()
{
mWriter = new StringWriter();
WriteComment("Maya ASCII 3.0 scene");
WriteComment("Created by Every File Explorer");
mWriter.WriteLine();
BeginStatement("requires");
{
WriteArgument("maya", "\"3.0\"");
}
EndStatement();
BeginStatement("currentUnit");
{
WriteArgument("-l", "centimeter");
WriteArgument("-a", "degree");
WriteArgument("-t", "film");
}
EndStatement();
}
public void WriteComment(String comment)
{
mWriter.WriteLine("//" + comment);
}
public void BeginStatement(String keyword)
{
mWriter.Write(keyword);
}
public void WriteArgument(int val)
{
WriteArgument(val.ToString());
}
public void WriteArgument(float val)
{
WriteArgument(val.ToString().Replace(",", "."));
}
public void WriteArgument(String arg)
{
mWriter.Write(" " + arg);
}
public void WriteArgument(String arg, int val)
{
WriteArgument(arg, val.ToString());
}
public void WriteArgument(String arg, float val)
{
WriteArgument(arg, val.ToString().Replace(",", "."));
}
public void WriteArgument(String arg, String val)
{
mWriter.Write(" " + arg + " " + val);
}
public void EndStatement()
{
mWriter.WriteLine(";");
}
public void CreateNode(String Type, String Name)
{
CreateNode(Type, Name, null, false, false);
}
public void CreateNode(String Type, String Name, bool Shared)
{
CreateNode(Type, Name, null, Shared, false);
}
public void CreateNode(String Type, String Name, String Parent)
{
CreateNode(Type, Name, Parent, false, false);
}
public void CreateNode(String Type, String Name, String Parent, bool Shared)
{
CreateNode(Type, Name, Parent, Shared, false);
}
public void CreateNode(String Type, String Name, String Parent, bool Shared, bool SkipSelect)
{
BeginStatement("createNode");
{
WriteArgument(Type);
WriteArgument("-n", "\"" + Name + "\"");
if (Parent != null) WriteArgument("-p", "\"" + Parent + "\"");
if (Shared) WriteArgument("-s");
if (SkipSelect) WriteArgument("-ss");
}
EndStatement();
}
public void ConnectAttribute(String FirstNode, String SecondNode)
{
ConnectAttribute(FirstNode, SecondNode, false);
}
public void ConnectAttribute(String FirstNode, String SecondNode, bool NextAvailable)
{
BeginStatement("connectAttr");
{
WriteArgument("\"" + FirstNode + "\"");
WriteArgument("\"" + SecondNode + "\"");
if (NextAvailable) WriteArgument("-na");
}
EndStatement();
}
public String Close()
{
mWriter.Flush();
String result = mWriter.ToString();
mWriter.Close();
return result;
}
}
}

View File

@ -100,7 +100,7 @@ namespace LibEveryFileExplorer.Collections
Matrix33 result = Matrix33.Identity;
result[0, 0] = Scale.X;
result[1, 1] = Scale.Y;
result[2, 2] = Scale.X;
result[2, 2] = Scale.Z;
return result;
}

View File

@ -194,7 +194,7 @@ namespace LibEveryFileExplorer.Collections
Matrix44 result = Matrix44.Identity;
result[0, 0] = Scale.X;
result[1, 1] = Scale.Y;
result[2, 2] = Scale.X;
result[2, 2] = Scale.Z;
return result;
}

View File

@ -233,7 +233,7 @@ namespace MarioKart.MK7.KMP
{
Point1 = v.Point1,
Point2 = v.Point2,
KeyPointID = v.Type,
KeyPointID = (short)(v.Type == 255?-1:v.Type),
RespawnID = v.RespawnId,
};

View File

@ -191,6 +191,7 @@ namespace MarioKart.MKDS
this.Normals = Normals.ToArray();
Planes = planes.ToArray();
Header = new MKDSKCLHeader();
//Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 32, 10);
Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 128, 50);
}

View File

@ -143,7 +143,7 @@ namespace MarioKart.MKDS.NKM
public Byte Unknown8 { get; set; }
public SByte LinkedCame { get; set; }
public Byte AreaType { get; set; }//1 = Camera Stuff, 4 = Water Fall Sound Area
public Byte AreaType { get; set; }//1 = Camera Area, 3 = Area for Boo's etc. (unknown5 = subtype), 4 = Water Fall Sound Area
public UInt16 Unknown10 { get; set; }//unverified

View File

@ -55,6 +55,8 @@
<Compile Include="NDSPlugin.cs" />
<Compile Include="NDSProject.cs" />
<Compile Include="NitroSystem\SND\SDAT.cs" />
<Compile Include="NitroSystem\SND\SWAR.cs" />
<Compile Include="NitroSystem\SND\SWAV.cs" />
<Compile Include="Nitro\ARM9.cs" />
<Compile Include="Nitro\ASMHack.cs" />
<Compile Include="GPU\CommandContext.cs" />

View File

@ -6,6 +6,7 @@ using LibEveryFileExplorer.Files;
using System.Drawing;
using System.IO;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.IO.Serialization;
namespace NDS.NitroSystem.SND
{
@ -13,7 +14,7 @@ namespace NDS.NitroSystem.SND
{
public SDAT(byte[] Data)
{
EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.LittleEndian);
EndianBinaryReaderEx er = new EndianBinaryReaderEx(new MemoryStream(Data), Endianness.LittleEndian);
try
{
Header = new SDATHeader(er);
@ -43,9 +44,10 @@ namespace NDS.NitroSystem.SND
public SDATHeader Header;
public class SDATHeader
{
public SDATHeader(EndianBinaryReader er)
public SDATHeader(EndianBinaryReaderEx er)
{
Signature = er.ReadString(Encoding.ASCII, 4);
er.ReadObject(this);
/*Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "SDAT") throw new SignatureNotCorrectException(Signature, "SDAT", er.BaseStream.Position - 4);
Endianness = er.ReadUInt16();
Version = er.ReadUInt16();
@ -60,9 +62,12 @@ namespace NDS.NitroSystem.SND
FATLength = er.ReadUInt32();
FILEOffset = er.ReadUInt32();
FILELength = er.ReadUInt32();
Padding = er.ReadBytes(16);
Padding = er.ReadBytes(16);*/
}
[BinaryStringSignature("SDAT")]
[BinaryFixedSize(4)]
public String Signature;
[BinaryBOM(0xFFFE)]
public UInt16 Endianness;
public UInt16 Version;
public UInt32 FileSize;
@ -76,6 +81,7 @@ namespace NDS.NitroSystem.SND
public UInt32 FATLength;
public UInt32 FILEOffset;
public UInt32 FILELength;
[BinaryFixedSize(16)]
public byte[] Padding;//16
}
@ -289,12 +295,12 @@ namespace NDS.NitroSystem.SND
public override string GetFileDescription()
{
return "Sound Data (SDAT)";
return "Nitro Sound Data (SDAT)";
}
public override string GetFileFilter()
{
return "Sound Data (*.sdat)|*.sdat";
return "Nitro Sound Data (*.sdat)|*.sdat";
}
public override Bitmap GetIcon()

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.Files;
using System.Drawing;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.IO.Serialization;
namespace NDS.NitroSystem.SND
{
public class SWAR : FileFormat<SWAR.SWARIdentifier>//, IViewable
{
public SWARHeader Header;
public class SWARHeader
{
public SWARHeader(EndianBinaryReaderEx er)
{
er.ReadObject(this);
}
[BinaryStringSignature("SWAR")]
[BinaryFixedSize(4)]
public String Signature;
[BinaryBOM(0xFFFE)]
public UInt16 Endianness;
public UInt16 Version;
public UInt32 FileSize;
public UInt16 HeaderSize;
public UInt16 NrBlocks;
}
public DATA Data;
public class DATA
{
public DATA(EndianBinaryReaderEx er)
{
er.ReadObject(this);
WaveInfoOffsets = er.ReadUInt32s((int)NrWaves);
}
[BinaryStringSignature("DATA")]
[BinaryFixedSize(4)]
public String Signature;
public UInt32 SectionSize;
[BinaryFixedSize(32)]
public Byte[] Padding;
public UInt32 NrWaves;
[BinaryIgnore]
public UInt32[] WaveInfoOffsets;
}
public class SWARIdentifier : FileFormatIdentifier
{
public override string GetCategory()
{
return Category_Archives;
}
public override string GetFileDescription()
{
return "Nitro Sound Wave Archive (SWAR)";
}
public override string GetFileFilter()
{
return "Nitro Sound Wave Archive (*.sdat)|*.sdat";
}
public override Bitmap GetIcon()
{
return null;
}
public override FormatMatch IsFormat(EFEFile File)
{
if (File.Data.Length > 4 && File.Data[0] == 'S' && File.Data[1] == 'W' && File.Data[2] == 'A' && File.Data[3] == 'R') return FormatMatch.Content;
return FormatMatch.No;
}
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.IO.Serialization;
using LibEveryFileExplorer.Files;
namespace NDS.NitroSystem.SND
{
public class SWAV : FileFormat<SWAR.SWARIdentifier>//, IViewable
{
public SWAVHeader Header;
public class SWAVHeader
{
public SWAVHeader(EndianBinaryReaderEx er)
{
er.ReadObject(this);
}
[BinaryStringSignature("SWAV")]
[BinaryFixedSize(4)]
public String Signature;
[BinaryBOM(0xFFFE)]
public UInt16 Endianness;
public UInt16 Version;
public UInt32 FileSize;
public UInt16 HeaderSize;
public UInt16 NrBlocks;
}
}
}

View File

@ -10,40 +10,40 @@ using LibEveryFileExplorer.GFX;
namespace WiiU.GPU
{
public class Textures
{
public enum TileMode : uint
{
Default = 0,
LinearAligned = 1,
Tiled1DThin1 = 2,
Tiled1DThick = 3,
Tiled2DThin1 = 4,
Tiled2DThin2 = 5,
Tiled2DThin4 = 6,
Tiled2DThick = 7,
Tiled2BThin1 = 8,
Tiled2BThin2 = 9,
Tiled2BThin4 = 10,
Tiled2BThick = 11,
Tiled3DThin1 = 12,
Tiled3DThick = 13,
Tiled3BThin1 = 14,
Tiled3BThick = 15,
LinearSpecial = 16
}
public class Textures
{
public enum TileMode : uint
{
Default = 0,
LinearAligned = 1,
Tiled1DThin1 = 2,
Tiled1DThick = 3,
Tiled2DThin1 = 4,
Tiled2DThin2 = 5,
Tiled2DThin4 = 6,
Tiled2DThick = 7,
Tiled2BThin1 = 8,
Tiled2BThin2 = 9,
Tiled2BThin4 = 10,
Tiled2BThick = 11,
Tiled3DThin1 = 12,
Tiled3DThick = 13,
Tiled3BThin1 = 14,
Tiled3BThick = 15,
LinearSpecial = 16
}
public enum ImageFormat : uint
{
RGB565,
DXT5
//ETC1,
//ETC1A4
}
public enum ImageFormat : uint
{
RGB565,
DXT5
//ETC1,
//ETC1A4
}
//private static readonly int[] Bpp = { 32, 24, 16, 16, 16, 16, 16, 8, 8, 8, 4, 4, 4, 8 };
//private static readonly int[] Bpp = { 32, 24, 16, 16, 16, 16, 16, 8, 8, 8, 4, 4, 4, 8 };
private static readonly int[] TileOrder =
private static readonly int[] TileOrder =
{
0, 1, 4, 5,
2, 3, 6, 7,
@ -51,11 +51,11 @@ namespace WiiU.GPU
8, 9, 12, 13,
10, 11, 14, 15
};
//1. Swap column 1 and 2, 4 and 5 etc.
//2. Put back 8x8 tiles in 16x16 blocks in the order 0, 3
// 1, 2
//1. Swap column 1 and 2, 4 and 5 etc.
//2. Put back 8x8 tiles in 16x16 blocks in the order 0, 3
// 1, 2
private static readonly int[,] ETC1Modifiers =
private static readonly int[,] ETC1Modifiers =
{
{ 2, 8 },
{ 5, 17 },
@ -67,370 +67,439 @@ namespace WiiU.GPU
{ 47, 183 }
};
//public static int GetBpp(ImageFormat Format) { return Bpp[(uint)Format]; }
//public static int GetBpp(ImageFormat Format) { return Bpp[(uint)Format]; }
public static Bitmap ToBitmap(byte[] Data, int Width, int Height, ImageFormat Format, TileMode TileMode, uint SwizzleMode, bool ExactSize = false)
{
return ToBitmap(Data, 0, Width, Height, Format, TileMode, SwizzleMode, ExactSize);
}
public static Bitmap ToBitmap(byte[] Data, int Width, int Height, ImageFormat Format, TileMode TileMode, uint SwizzleMode, bool ExactSize = false)
{
return ToBitmap(Data, 0, Width, Height, Format, TileMode, SwizzleMode, ExactSize);
}
public static unsafe Bitmap ToBitmap(byte[] Data, int Offset, int Width, int Height, ImageFormat Format, TileMode TileMode, uint SwizzleMode, bool ExactSize = false)
{
if (Data == null || Data.Length < 1 || Offset < 0 || Offset >= Data.Length || Width < 1 || Height < 1) return null;
if (ExactSize && ((Width % 8) != 0 || (Height % 8) != 0)) return null;
int physicalwidth = Width;
int physicalheight = Height;
if (!ExactSize)
{
Width = 1 << (int)Math.Ceiling(Math.Log(Width, 2));
Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2));
}
Bitmap bitm = new Bitmap(Width, Height);//physicalwidth, physicalheight);
BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
uint* res = (uint*)d.Scan0;
int offs = Offset;//0;
int stride = d.Stride / 4;
switch (Format)
{
case ImageFormat.RGB565:
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
//if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] =
GFXUtil.ConvertColorFormat(
IOUtil.ReadU16LE(Data, offs),
ColorFormat.RGB565,
ColorFormat.ARGB8888);
offs += 2;
}
}
break;
case ImageFormat.DXT5:
for (int y2 = 0; y2 < Height; y2 += 4)
{
for (int x2 = 0; x2 < Width; x2 += 4)
{
ulong a_data = IOUtil.ReadU64LE(Data, offs);
byte[] AlphaPalette = new byte[8];
AlphaPalette[0] = (byte)(a_data & 0xFF);
AlphaPalette[1] = (byte)((a_data >> 8) & 0xFF);
a_data >>= 16;
if (AlphaPalette[0] > AlphaPalette[1])
{
AlphaPalette[2] = (byte)((6 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 7);
AlphaPalette[3] = (byte)((5 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 7);
AlphaPalette[4] = (byte)((4 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 7);
AlphaPalette[5] = (byte)((3 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 7);
AlphaPalette[6] = (byte)((2 * AlphaPalette[0] + 5 * AlphaPalette[1]) / 7);
AlphaPalette[7] = (byte)((1 * AlphaPalette[0] + 6 * AlphaPalette[1]) / 7);
}
else
{
AlphaPalette[2] = (byte)((4 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 5);
AlphaPalette[3] = (byte)((3 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 5);
AlphaPalette[4] = (byte)((2 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 5);
AlphaPalette[5] = (byte)((1 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 5);
AlphaPalette[6] = 0;
AlphaPalette[7] = 255;
}
offs += 8;
ushort color0 = IOUtil.ReadU16LE(Data, offs);
ushort color1 = IOUtil.ReadU16LE(Data, offs + 2);
uint data = IOUtil.ReadU32LE(Data, offs + 4);
uint[] Palette = new uint[4];
Palette[0] = GFXUtil.ConvertColorFormat(color0, ColorFormat.RGB565, ColorFormat.ARGB8888);
Palette[1] = GFXUtil.ConvertColorFormat(color1, ColorFormat.RGB565, ColorFormat.ARGB8888);
Color a = System.Drawing.Color.FromArgb((int)Palette[0]);
Color b = System.Drawing.Color.FromArgb((int)Palette[1]);
if (color0 > color1)//1/3 and 2/3
{
Palette[2] = GFXUtil.ToColorFormat((a.R * 2 + b.R * 1) / 3, (a.G * 2 + b.G * 1) / 3, (a.B * 2 + b.B * 1) / 3, ColorFormat.ARGB8888);
Palette[3] = GFXUtil.ToColorFormat((a.R * 1 + b.R * 2) / 3, (a.G * 1 + b.G * 2) / 3, (a.B * 1 + b.B * 2) / 3, ColorFormat.ARGB8888);
}
else//1/2 and transparent
{
Palette[2] = GFXUtil.ToColorFormat((a.R + b.R) / 2, (a.G + b.G) / 2, (a.B + b.B) / 2, ColorFormat.ARGB8888);
Palette[3] = 0;
}
public static unsafe Bitmap ToBitmap(byte[] Data, int Offset, int Width, int Height, ImageFormat Format, TileMode TileMode, uint SwizzleMode, bool ExactSize = false)
{
if (Data == null || Data.Length < 1 || Offset < 0 || Offset >= Data.Length || Width < 1 || Height < 1) return null;
if (ExactSize && ((Width % 8) != 0 || (Height % 8) != 0)) return null;
int physicalwidth = Width;
int physicalheight = Height;
if (!ExactSize)
{
Width = 1 << (int)Math.Ceiling(Math.Log(Width, 2));
Height = 1 << (int)Math.Ceiling(Math.Log(Height, 2));
}
Bitmap bitm = new Bitmap(Width, Height);//physicalwidth, physicalheight);
BitmapData d = bitm.LockBits(new Rectangle(0, 0, bitm.Width, bitm.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
uint* res = (uint*)d.Scan0;
int offs = Offset;//0;
int stride = d.Stride / 4;
switch (Format)
{
case ImageFormat.RGB565:
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
//if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] =
GFXUtil.ConvertColorFormat(
IOUtil.ReadU16LE(Data, offs),
ColorFormat.RGB565,
ColorFormat.ARGB8888);
offs += 2;
}
}
break;
case ImageFormat.DXT5:
for (int y2 = 0; y2 < Height; y2 += 4)
{
for (int x2 = 0; x2 < Width; x2 += 4)
{
ulong a_data = IOUtil.ReadU64LE(Data, offs);
byte[] AlphaPalette = new byte[8];
AlphaPalette[0] = (byte)(a_data & 0xFF);
AlphaPalette[1] = (byte)((a_data >> 8) & 0xFF);
a_data >>= 16;
if (AlphaPalette[0] > AlphaPalette[1])
{
AlphaPalette[2] = (byte)((6 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 7);
AlphaPalette[3] = (byte)((5 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 7);
AlphaPalette[4] = (byte)((4 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 7);
AlphaPalette[5] = (byte)((3 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 7);
AlphaPalette[6] = (byte)((2 * AlphaPalette[0] + 5 * AlphaPalette[1]) / 7);
AlphaPalette[7] = (byte)((1 * AlphaPalette[0] + 6 * AlphaPalette[1]) / 7);
}
else
{
AlphaPalette[2] = (byte)((4 * AlphaPalette[0] + 1 * AlphaPalette[1]) / 5);
AlphaPalette[3] = (byte)((3 * AlphaPalette[0] + 2 * AlphaPalette[1]) / 5);
AlphaPalette[4] = (byte)((2 * AlphaPalette[0] + 3 * AlphaPalette[1]) / 5);
AlphaPalette[5] = (byte)((1 * AlphaPalette[0] + 4 * AlphaPalette[1]) / 5);
AlphaPalette[6] = 0;
AlphaPalette[7] = 255;
}
offs += 8;
ushort color0 = IOUtil.ReadU16LE(Data, offs);
ushort color1 = IOUtil.ReadU16LE(Data, offs + 2);
uint data = IOUtil.ReadU32LE(Data, offs + 4);
uint[] Palette = new uint[4];
Palette[0] = GFXUtil.ConvertColorFormat(color0, ColorFormat.RGB565, ColorFormat.ARGB8888);
Palette[1] = GFXUtil.ConvertColorFormat(color1, ColorFormat.RGB565, ColorFormat.ARGB8888);
Color a = System.Drawing.Color.FromArgb((int)Palette[0]);
Color b = System.Drawing.Color.FromArgb((int)Palette[1]);
if (color0 > color1)//1/3 and 2/3
{
Palette[2] = GFXUtil.ToColorFormat((a.R * 2 + b.R * 1) / 3, (a.G * 2 + b.G * 1) / 3, (a.B * 2 + b.B * 1) / 3, ColorFormat.ARGB8888);
Palette[3] = GFXUtil.ToColorFormat((a.R * 1 + b.R * 2) / 3, (a.G * 1 + b.G * 2) / 3, (a.B * 1 + b.B * 2) / 3, ColorFormat.ARGB8888);
}
else//1/2 and transparent
{
Palette[2] = GFXUtil.ToColorFormat((a.R + b.R) / 2, (a.G + b.G) / 2, (a.B + b.B) / 2, ColorFormat.ARGB8888);
Palette[3] = 0;
}
int q = 30;
int aq = 45;
for (int y3 = 0; y3 < 4; y3++)
{
for (int x3 = 0; x3 < 4; x3++)
{
//if (x2 + x3 >= physicalwidth) continue;
if (y2 + y3 >= physicalheight) continue;
res[(y2 + y3) * stride + x2 + x3] = (Palette[(data >> q) & 3] & 0xFFFFFF) | ((uint)AlphaPalette[(a_data >> aq) & 7] << 24);
q -= 2;
aq -= 3;
}
}
offs += 8;
}
// }
//}
}
break;
/*case ImageFormat.ETC1://Some reference: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
case ImageFormat.ETC1A4:
{
for (int y = 0; y < Height; y += 8)
{
for (int x = 0; x < Width; x += 8)
{
for (int i = 0; i < 8; i += 4)
{
for (int j = 0; j < 8; j += 4)
{
ulong alpha = 0xFFFFFFFFFFFFFFFF;
ulong data = IOUtil.ReadU64BE(Data, offs);
if (Format == ImageFormat.ETC1A4)
{
offs += 8;
alpha = IOUtil.ReadU64BE(Data, offs);
}
bool diffbit = ((data >> 33) & 1) == 1;
bool flipbit = ((data >> 32) & 1) == 1; //0: |||, 1: |-|
int r1, r2, g1, g2, b1, b2;
if (diffbit) //'differential' mode
{
int r = (int)((data >> 59) & 0x1F);
int g = (int)((data >> 51) & 0x1F);
int b = (int)((data >> 43) & 0x1F);
r1 = (r << 3) | ((r & 0x1C) >> 2);
g1 = (g << 3) | ((g & 0x1C) >> 2);
b1 = (b << 3) | ((b & 0x1C) >> 2);
r += (int)((data >> 56) & 0x7) << 29 >> 29;
g += (int)((data >> 48) & 0x7) << 29 >> 29;
b += (int)((data >> 40) & 0x7) << 29 >> 29;
r2 = (r << 3) | ((r & 0x1C) >> 2);
g2 = (g << 3) | ((g & 0x1C) >> 2);
b2 = (b << 3) | ((b & 0x1C) >> 2);
}
else //'individual' mode
{
r1 = (int)((data >> 60) & 0xF) * 0x11;
g1 = (int)((data >> 52) & 0xF) * 0x11;
b1 = (int)((data >> 44) & 0xF) * 0x11;
r2 = (int)((data >> 56) & 0xF) * 0x11;
g2 = (int)((data >> 48) & 0xF) * 0x11;
b2 = (int)((data >> 40) & 0xF) * 0x11;
}
int Table1 = (int)((data >> 37) & 0x7);
int Table2 = (int)((data >> 34) & 0x7);
for (int y3 = 0; y3 < 4; y3++)
{
for (int x3 = 0; x3 < 4; x3++)
{
if (x + j + x3 >= physicalwidth) continue;
if (y + i + y3 >= physicalheight) continue;
int q = 30;
int aq = 45;
for (int y3 = 0; y3 < 4; y3++)
{
for (int x3 = 0; x3 < 4; x3++)
{
//if (x2 + x3 >= physicalwidth) continue;
if (y2 + y3 >= physicalheight) continue;
res[(y2 + y3) * stride + x2 + x3] = (Palette[(data >> q) & 3] & 0xFFFFFF) | ((uint)AlphaPalette[(a_data >> aq) & 7] << 24);
q -= 2;
aq -= 3;
}
}
offs += 8;
}
// }
//}
}
break;
/*case ImageFormat.ETC1://Some reference: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
case ImageFormat.ETC1A4:
{
for (int y = 0; y < Height; y += 8)
{
for (int x = 0; x < Width; x += 8)
{
for (int i = 0; i < 8; i += 4)
{
for (int j = 0; j < 8; j += 4)
{
ulong alpha = 0xFFFFFFFFFFFFFFFF;
ulong data = IOUtil.ReadU64BE(Data, offs);
if (Format == ImageFormat.ETC1A4)
{
offs += 8;
alpha = IOUtil.ReadU64BE(Data, offs);
}
bool diffbit = ((data >> 33) & 1) == 1;
bool flipbit = ((data >> 32) & 1) == 1; //0: |||, 1: |-|
int r1, r2, g1, g2, b1, b2;
if (diffbit) //'differential' mode
{
int r = (int)((data >> 59) & 0x1F);
int g = (int)((data >> 51) & 0x1F);
int b = (int)((data >> 43) & 0x1F);
r1 = (r << 3) | ((r & 0x1C) >> 2);
g1 = (g << 3) | ((g & 0x1C) >> 2);
b1 = (b << 3) | ((b & 0x1C) >> 2);
r += (int)((data >> 56) & 0x7) << 29 >> 29;
g += (int)((data >> 48) & 0x7) << 29 >> 29;
b += (int)((data >> 40) & 0x7) << 29 >> 29;
r2 = (r << 3) | ((r & 0x1C) >> 2);
g2 = (g << 3) | ((g & 0x1C) >> 2);
b2 = (b << 3) | ((b & 0x1C) >> 2);
}
else //'individual' mode
{
r1 = (int)((data >> 60) & 0xF) * 0x11;
g1 = (int)((data >> 52) & 0xF) * 0x11;
b1 = (int)((data >> 44) & 0xF) * 0x11;
r2 = (int)((data >> 56) & 0xF) * 0x11;
g2 = (int)((data >> 48) & 0xF) * 0x11;
b2 = (int)((data >> 40) & 0xF) * 0x11;
}
int Table1 = (int)((data >> 37) & 0x7);
int Table2 = (int)((data >> 34) & 0x7);
for (int y3 = 0; y3 < 4; y3++)
{
for (int x3 = 0; x3 < 4; x3++)
{
if (x + j + x3 >= physicalwidth) continue;
if (y + i + y3 >= physicalheight) continue;
int val = (int)((data >> (x3 * 4 + y3)) & 0x1);
bool neg = ((data >> (x3 * 4 + y3 + 16)) & 0x1) == 1;
uint c;
if ((flipbit && y3 < 2) || (!flipbit && x3 < 2))
{
int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1);
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888);
}
else
{
int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1);
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888);
}
res[(i + y3) * stride + x + j + x3] = c;
}
}
offs += 8;
}
}
}
res += stride * 8;
}
}
break;
* */
}
Detile(res, stride, Width, Height, physicalwidth, physicalheight, TileMode);
bitm.UnlockBits(d);
return bitm;
}
int val = (int)((data >> (x3 * 4 + y3)) & 0x1);
bool neg = ((data >> (x3 * 4 + y3 + 16)) & 0x1) == 1;
uint c;
if ((flipbit && y3 < 2) || (!flipbit && x3 < 2))
{
int add = ETC1Modifiers[Table1, val] * (neg ? -1 : 1);
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r1 + add), (byte)ColorClamp(g1 + add), (byte)ColorClamp(b1 + add), ColorFormat.ARGB8888);
}
else
{
int add = ETC1Modifiers[Table2, val] * (neg ? -1 : 1);
c = GFXUtil.ToColorFormat((byte)(((alpha >> ((x3 * 4 + y3) * 4)) & 0xF) * 0x11), (byte)ColorClamp(r2 + add), (byte)ColorClamp(g2 + add), (byte)ColorClamp(b2 + add), ColorFormat.ARGB8888);
}
res[(i + y3) * stride + x + j + x3] = c;
}
}
offs += 8;
}
}
}
res += stride * 8;
}
}
break;
* */
}
Detile(res, stride, Width, Height, physicalwidth, physicalheight, TileMode);
bitm.UnlockBits(d);
return bitm;
}
private static unsafe void Detile(uint* res, int stride, int width, int height, int physicalwidth, int physicalheight, TileMode Mode)
{
switch (Mode)
{
case Textures.TileMode.Tiled2DThin1:
DetileTiled2DThin1(res, stride, width, height, physicalwidth, physicalheight);
return;
default:
throw new Exception("Unsupported Tilemode!");
}
}
private static unsafe void Detile(uint* res, int stride, int width, int height, int physicalwidth, int physicalheight, TileMode Mode)
{
switch (Mode)
{
case Textures.TileMode.Tiled2DThin1:
DetileTiled2DThin1(res, stride, width, height, physicalwidth, physicalheight);
return;
default:
throw new Exception("Unsupported Tilemode!");
}
}
//private static readonly int[] Tiled2DThin1OrderA = { 0, 1, 3, 2 };
//private static readonly int[] Tiled2DThin1OrderB = { 0, 2, 3, 1 };
private static readonly int[] Tiled2DThin1Order = { 2, 0, 1, 3 };
//private static readonly int[] Tiled2DThin1OrderA = { 0, 1, 3, 2 };
//private static readonly int[] Tiled2DThin1OrderB = { 0, 2, 3, 1 };
private static readonly int[] Tiled2DThin1Order = { 2, 0, 1, 3 };
private static unsafe void DetileTiled2DThin1(uint* res, int stride, int width, int height, int physicalwidth, int physicalheight)
{
uint[] Result = new uint[width * height];
int px = 0;
int py = 0;
for (int y = 0; y < height; y += 64)
{
for (int x = 0; x < width; x += 64)
{
for (int i = 0; i < 64; i++)//y2 = 0; y2 < 64; y2 += 8)
{
int tile = i;
int q = Tiled2DThin1Order[(tile / 2) % 4];
int p = tile & ~7;
int xx = (p % 16) * 2 + (q % 2) * 8;
//if ((i / 0x20) == 1)
//{
//xx += (i % 2) * 8;
//}
/*else */xx += (i % 2) * 32;
int yy = p / 16 * 16 + (q / 2) * 8;
for (int y3 = 0; y3 < 8; y3++)
{
for (int x3 = 0; x3 < 8; x3++)
{
//if (x + x2 + x3 >= physicalwidth) continue;
//if (y + y3 + yy >= physicalheight) continue;
Result[(y + y3 + yy) * width + x + x3 + xx] = ReadPixel(res, stride, width, height, ref px, ref py);
}
}
}
}
}
/*R600Tiling t = new R600Tiling();
R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT r = new R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT();
r.bpp = 32;
r.tileMode = 4;
r.tileType = 0;
r.pitch = (uint)stride;
r.height = (uint)height;
r.numSlices = 1;
r.numSamples = (uint)(height * width);
R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT o = new R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT();
int i = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
r.x = (uint)x;
r.y = (uint)y;
r.sample = (uint)i;
int pixel_number = (int)t.ComputeSurfaceAddrFromCoord(ref r, ref o);
/*int pixel_number = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]/
//Micro tiles: 8x8
//Macro tiles: 32x16 (4x2 tiles = 4 banks, 2 pipes)
Result[y * width + x] = res[(pixel_number & 0xFFF) / 4];
i++;
}
}*/
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] = Result[y * width + x];
}
}
/*
//Swap columns first!
for (int c = 0; c < width; c += 16)
{
//Swap c + 4 and c + 8
for (int y = 0; y < height; y++)
{
for (int x = 0; x < 4; x++)
{
if (c + x >= physicalwidth) continue;
if (y >= physicalheight) continue;
uint a = res[y * stride + c + x + 4];
uint b = res[y * stride + c + x + 8];
res[y * stride + c + x + 4] = b;
res[y * stride + c + x + 8] = a;
}
}
}
uint[] Result = new uint[width * height];
//work in 16x16 and then in 8x8 tiles
int px = 0;
int py = 0;
for (int y = 0; y < height; y += 32)
{
for (int x = 0; x < width; x += 32)
{
for (int j = 0; j < 4; j++)
{
int x4 = (Tiled2DThin1OrderA[j] % 2) * 16;
int y4 = ((Tiled2DThin1OrderA[j] & 2) >> 1) * 16;
//Read out the 256 pixels needed!
uint[] Pixels = new uint[256];
for (int i = 0; i < 256; i++) Pixels[i] = ReadPixel(res, stride, width, height, ref px, ref py);
int idx = 0;
for (int i = 0; i < 4; i++)
{
int x2 = (Tiled2DThin1OrderB[i] % 2) * 8;
int y2 = ((Tiled2DThin1OrderB[i] & 2) >> 1) * 8;
for (int y3 = 0; y3 < 8; y3++)
{
for (int x3 = 0; x3 < 8; x3++)
{
Result[(y + y2 + y3 + y4) * width + x + x2 + x3 + x4] = Pixels[idx++];
//res[(y + y2 + y3) * stride + x + x2 + x3] = Pixels[idx++];
}
}
}
}
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] = Result[y * width + x];
}
}
*/
}
//Alignment: 2048 pixels (I think), which matches exactly with the 128x16 blocks
private static unsafe uint ReadPixel(uint* res, int stride, int width, int height, ref int px, ref int py)
{
if (px >= width || py >= height || px < 0 || py < 0)
return 0;//throw new ArgumentException("ReadPixel fail!");
uint result = res[py * stride + px];
px++;
if (px == width)
{
px = 0;
py++;
}
return result;
}
//First block:
// Macro:
// 1 2 5 6
// 0 3 4 7
//Second block:
// Macro:
// 5 6 1 2
// 4 7 0 3
//Third block:
// Macro:
// 3 0 7 4
// 2 1 6 5
//Fourth block:
// Macro:
// 7 4 3 0
// 6 5 2 1
private static unsafe void DetileTiled2DThin1(uint* res, int stride, int width, int height, int physicalwidth, int physicalheight)
{
uint[] right_order = new uint[width * height];
int q = 0;
//Let's put the tiles in the right order
for (int y = 0; y < height; y += 8)
{
for (int xx = 0; xx < width; xx += 64)
{
for (int yy = 0; yy < 8; yy++)
{
for (int x = 0; x < 64; x++)
{
right_order[q++] = res[(y + yy) * stride + x + xx];
}
}
}
}
private static int ColorClamp(int Color)
{
if (Color > 255) Color = 255;
if (Color < 0) Color = 0;
return Color;
}
q = 0;
uint[] Result = new uint[width * height];
for (int y = 0; y < height; y += 8)
{
for (int x = 0; x < width; x += 8)
{
for (int yy = 0; yy < 8; yy++)
{
for (int xx = 0; xx < 8; xx++)
{
Result[(y + yy) * width + x + xx] = right_order[q++];
}
}
}
}
}
//
/* uint[] Result = new uint[width * height];
int px = 0;
int py = 0;
for (int y = 0; y < height; y += /*8/16)
{
for (int x = 0; x < width; x += 64)
{
/*for (int y2 = 0; y2 < 8; y2++)
{
for (int x2 = 0; x2 < 64; x2++)
{
Result[(y + (x2 / 8)) * width + x + y2 * 8 + x2 % 8] =
res[(y + y2) * stride + x + x2];
}
}/
/*for (int i = 0; i < 64; i++)//y2 = 0; y2 < 64; y2 += 8)
{
int tile = i;
int q = Tiled2DThin1Order[(tile / 2) % 4];
int p = tile & ~7;
int xx = (p % 16) * 2 + (q % 2) * 8;
//if ((i / 0x20) == 1)
//{
//xx += (i % 2) * 8;
//}
/*else /
xx += (i % 2) * 32;
int yy = p / 16 * 16 + (q / 2) * 8;
for (int y3 = 0; y3 < 8; y3++)
{
for (int x3 = 0; x3 < 8; x3++)
{
if (y + y3 + yy >= height || x + x3 + xx >= width) continue;
//if (x + x2 + x3 >= physicalwidth) continue;
//if (y + y3 + yy >= physicalheight) continue;
Result[(y + y3 + yy) * width + x + x3 + xx] = ReadPixel(res, stride, width, height, ref px, ref py);
}
}
}/
}
}*/
//TODO: We now have the tiles, so start constructing the macro tiles
/*R600Tiling t = new R600Tiling();
R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT r = new R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT();
r.bpp = 32;
r.tileMode = 4;
r.tileType = 0;
r.pitch = (uint)stride;
r.height = (uint)height;
r.numSlices = 1;
r.numSamples = (uint)(height * width);
R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT o = new R600Tiling._ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT();
int i = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
r.x = (uint)x;
r.y = (uint)y;
r.sample = (uint)i;
int pixel_number = (int)t.ComputeSurfaceAddrFromCoord(ref r, ref o);
/*int pixel_number = 0;
pixel_number |= ((x >> 0) & 1) << 0; // pn[0] = x[0]
pixel_number |= ((x >> 1) & 1) << 1; // pn[1] = x[1]
pixel_number |= ((x >> 2) & 1) << 2; // pn[2] = x[2]
pixel_number |= ((y >> 1) & 1) << 3; // pn[3] = y[1]
pixel_number |= ((y >> 0) & 1) << 4; // pn[4] = y[0]
pixel_number |= ((y >> 2) & 1) << 5; // pn[5] = y[2]/
Result[y * width + x] = res[(pixel_number & 0xFFF) / 4];
i++;
}
}*/
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] = Result[y * width + x];
}
}
/*
//Swap columns first!
for (int c = 0; c < width; c += 16)
{
//Swap c + 4 and c + 8
for (int y = 0; y < height; y++)
{
for (int x = 0; x < 4; x++)
{
if (c + x >= physicalwidth) continue;
if (y >= physicalheight) continue;
uint a = res[y * stride + c + x + 4];
uint b = res[y * stride + c + x + 8];
res[y * stride + c + x + 4] = b;
res[y * stride + c + x + 8] = a;
}
}
}
uint[] Result = new uint[width * height];
//work in 16x16 and then in 8x8 tiles
int px = 0;
int py = 0;
for (int y = 0; y < height; y += 32)
{
for (int x = 0; x < width; x += 32)
{
for (int j = 0; j < 4; j++)
{
int x4 = (Tiled2DThin1OrderA[j] % 2) * 16;
int y4 = ((Tiled2DThin1OrderA[j] & 2) >> 1) * 16;
//Read out the 256 pixels needed!
uint[] Pixels = new uint[256];
for (int i = 0; i < 256; i++) Pixels[i] = ReadPixel(res, stride, width, height, ref px, ref py);
int idx = 0;
for (int i = 0; i < 4; i++)
{
int x2 = (Tiled2DThin1OrderB[i] % 2) * 8;
int y2 = ((Tiled2DThin1OrderB[i] & 2) >> 1) * 8;
for (int y3 = 0; y3 < 8; y3++)
{
for (int x3 = 0; x3 < 8; x3++)
{
Result[(y + y2 + y3 + y4) * width + x + x2 + x3 + x4] = Pixels[idx++];
//res[(y + y2 + y3) * stride + x + x2 + x3] = Pixels[idx++];
}
}
}
}
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (x >= physicalwidth) continue;
if (y >= physicalheight) continue;
res[y * stride + x] = Result[y * width + x];
}
}
*/
}
private static unsafe uint ReadPixel(uint* res, int stride, int width, int height, ref int px, ref int py)
{
if (px >= width || py >= height || px < 0 || py < 0)
return 0;//throw new ArgumentException("ReadPixel fail!");
uint result = res[py * stride + px];
px++;
if (px == width)
{
px = 0;
py++;
}
return result;
}
private static int ColorClamp(int Color)
{
if (Color > 255) Color = 255;
if (Color < 0) Color = 0;
return Color;
}
}
}