Some fixes for EFE Script, SMDH saving

This commit is contained in:
Gericom 2015-01-24 11:49:11 +01:00
parent 7ff339c62b
commit 079791c401
6 changed files with 206 additions and 62 deletions

View File

@ -7,14 +7,15 @@ using System.Drawing;
using System.IO;
using _3DS.UI;
using LibEveryFileExplorer.IO;
using LibEveryFileExplorer.IO.Serialization;
namespace _3DS
{
public class SMDH : FileFormat<SMDH.SMDHIdentifier>, IViewable
public class SMDH : FileFormat<SMDH.SMDHIdentifier>, IViewable, IWriteable
{
public SMDH(byte[] Data)
{
EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.LittleEndian);
EndianBinaryReaderEx er = new EndianBinaryReaderEx(new MemoryStream(Data), Endianness.LittleEndian);
try
{
Header = new SMDHHeader(er);
@ -31,6 +32,26 @@ namespace _3DS
}
}
public string GetSaveDefaultFileFilter()
{
return "System Menu Data Header (*.icn)|*.icn";
}
public byte[] Write()
{
MemoryStream m = new MemoryStream();
EndianBinaryWriter er = new EndianBinaryWriter(m, Endianness.LittleEndian);
Header.Write(er);
for (int i = 0; i < 16; i++) AppTitles[i].Write(er);
AppSettings.Write(er);
er.Write(Reserved, 0, 8);
er.Write(SmallIcon, 0, 0x480);
er.Write(LargeIcon, 0, 0x1200);
byte[] result = m.ToArray();
er.Close();
return result;
}
public System.Windows.Forms.Form GetDialog()
{
return new SMDHViewer(this);
@ -39,13 +60,22 @@ namespace _3DS
public SMDHHeader Header;
public class SMDHHeader
{
public SMDHHeader(EndianBinaryReader er)
public SMDHHeader(EndianBinaryReaderEx er)
{
Signature = er.ReadString(Encoding.ASCII, 4);
if (Signature != "SMDH") throw new SignatureNotCorrectException(Signature, "SMDH", er.BaseStream.Position - 4);
Version = er.ReadUInt16();
Reserved = er.ReadUInt16();
er.ReadObject(this);
//Signature = er.ReadString(Encoding.ASCII, 4);
//if (Signature != "SMDH") throw new SignatureNotCorrectException(Signature, "SMDH", er.BaseStream.Position - 4);
//Version = er.ReadUInt16();
//Reserved = er.ReadUInt16();
}
public void Write(EndianBinaryWriter er)
{
er.Write(Signature, Encoding.ASCII, false);
er.Write(Version);
er.Write(Reserved);
}
[BinaryStringSignature("SMDH")]
[BinaryFixedSize(4)]
public String Signature;
public UInt16 Version;
public UInt16 Reserved;
@ -60,6 +90,12 @@ namespace _3DS
LongDescription = er.ReadString(Encoding.Unicode, 128).TrimEnd('\0');
Publisher = er.ReadString(Encoding.Unicode, 64).TrimEnd('\0');
}
public void Write(EndianBinaryWriter er)
{
er.Write(ShortDescription.PadRight(64, '\0'), Encoding.Unicode, false);
er.Write(LongDescription.PadRight(128, '\0'), Encoding.Unicode, false);
er.Write(Publisher.PadRight(64, '\0'), Encoding.Unicode, false);
}
public String ShortDescription;//0x80
public String LongDescription;//0x100
public String Publisher;//0x80
@ -95,9 +131,10 @@ namespace _3DS
DisableSDSaveBackup = 512
}
public ApplicationSettings(EndianBinaryReader er)
public ApplicationSettings(EndianBinaryReaderEx er)
{
GameRatings = er.ReadBytes(0x10);
er.ReadObject(this);
/*GameRatings = er.ReadBytes(0x10);
RegionLockout = (RegionLockoutFlags)er.ReadUInt32();
MatchMakerID = er.ReadUInt32();
MatchMakerBITID = er.ReadUInt64();
@ -105,8 +142,21 @@ namespace _3DS
EULAVersion = er.ReadUInt16();
Reserved = er.ReadUInt16();
AnimationDefaultFrame = er.ReadSingle();
StreetPassID = er.ReadUInt32();
StreetPassID = er.ReadUInt32();*/
}
public void Write(EndianBinaryWriter er)
{
er.Write(GameRatings, 0, 0x10);
er.Write((uint)RegionLockout);
er.Write(MatchMakerID);
er.Write(MatchMakerBITID);
er.Write((uint)Flags);
er.Write(EULAVersion);
er.Write(Reserved);
er.Write(AnimationDefaultFrame);
er.Write(StreetPassID);
}
[BinaryFixedSize(0x10)]
public byte[] GameRatings;//0x10
public RegionLockoutFlags RegionLockout;
public UInt32 MatchMakerID;

View File

@ -37,7 +37,9 @@ namespace EveryFileExplorer
Console.WriteLine("Executing " + Path.GetFileName(Arguments[0]) + "...");
EFEScript.Execute(Script, args);
Win32Util.FreeConsole();
SendKeys.SendWait("{ENTER}");
//Using this causes scripts to be runned over and over again if opened by double-clicking
//But without this, you need to press ENTER before be able to use the cmd again if you run it from there...
//SendKeys.SendWait("{ENTER}");
return;
}

View File

@ -8,6 +8,7 @@ using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.CodeDom;
using System.Windows.Forms;
namespace LibEveryFileExplorer.Script
{
@ -21,6 +22,7 @@ namespace LibEveryFileExplorer.Script
//prepare the script to be executed!
StringBuilder b = new StringBuilder();
b.AppendLine("using System;");
b.AppendLine("using System.Collections.Generic;");
b.AppendLine("using System.IO;");
b.AppendLine();
foreach (var v in Commands)
@ -68,7 +70,7 @@ namespace LibEveryFileExplorer.Script
foreach (var vv in m.GetParameters())
{
if (!first) b.Append(", ");
b.Append(vv.ParameterType.FullName + " ");
b.Append(GetCSharpRepresentation(vv.ParameterType) + " ");
b.Append(vv.Name);
first = false;
}
@ -113,7 +115,7 @@ namespace LibEveryFileExplorer.Script
AssemblyName[] refassem = Assembly.GetEntryAssembly().GetReferencedAssemblies();
foreach (var a in refassem)
{
opt.ReferencedAssemblies.Add(a.Name + ".dll");
opt.ReferencedAssemblies.Add(Assembly.ReflectionOnlyLoad(a.FullName).Location);
}
foreach (var v in Commands)
{
@ -127,6 +129,57 @@ namespace LibEveryFileExplorer.Script
result.CompiledAssembly.GetType("EFEScript.Script").InvokeMember("Run", BindingFlags.InvokeMethod, null, null, Args);
}
private static string GetCSharpRepresentation(Type t)
{
if (t.IsGenericType)
{
var genericArgs = t.GetGenericArguments().ToList();
return GetCSharpRepresentation(t, genericArgs);
}
return t.Name;
}
private static string GetCSharpRepresentation(Type t, List<Type> availableArguments)
{
if (t.IsGenericType)
{
string value = t.Name;
if (value.IndexOf("`") > -1)
{
value = value.Substring(0, value.IndexOf("`"));
}
if (t.DeclaringType != null)
{
// This is a nested type, build the nesting type first
value = GetCSharpRepresentation(t.DeclaringType, availableArguments) + "+" + value;
}
// Build the type arguments (if any)
string argString = "";
var thisTypeArgs = t.GetGenericArguments();
for (int i = 0; i < thisTypeArgs.Length && availableArguments.Count > 0; i++)
{
if (i != 0) argString += ", ";
argString += GetCSharpRepresentation(availableArguments[0]);
availableArguments.RemoveAt(0);
}
// If there are type arguments, add them with < >
if (argString.Length > 0)
{
value += "<" + argString + ">";
}
return value;
}
return t.Name;
}
public static void RegisterCommand(String Command, Delegate Function)
{
if (Commands.ContainsKey(Command) || Commands.ContainsValue(Function)) throw new Exception("Command '" + Command + "' or Function already registered!");

View File

@ -139,60 +139,61 @@ namespace MarioKart.MKDS
ty.DialogResult = System.Windows.Forms.DialogResult.None;
ty.ShowDialog();
while (ty.DialogResult != System.Windows.Forms.DialogResult.OK) ;
Dictionary<string, ushort> Mapping;
Dictionary<string, bool> Colli;
Mapping = ty.Mapping;
Colli = ty.Colli;
List<Vector3> Vertex = new List<Vector3>();
List<Vector3> Normals = new List<Vector3>();
List<KCLPlane> planes = new List<KCLPlane>();
List<Triangle> Triangles = new List<Triangle>();
foreach (var v in o.Faces)
{
if (Colli[v.Material])
{
Triangle t = new Triangle(o.Vertices[v.VertexIndieces[0]], o.Vertices[v.VertexIndieces[1]], o.Vertices[v.VertexIndieces[2]]);
Vector3 qq = (t.PointB - t.PointA).Cross(t.PointC - t.PointA);
if ((qq.X * qq.X + qq.Y * qq.Y + qq.Z * qq.Z) < 0.01) continue;
KCLPlane p = new KCLPlane();
p.CollisionType = (ushort)(((Mapping[v.Material] & 0xFF) << 8) | (Mapping[v.Material] >> 8));
Vector3 a = (t.PointC - t.PointA).Cross(t.Normal);
a.Normalize();
a = -a;
Vector3 b = (t.PointB - t.PointA).Cross(t.Normal);
b.Normalize();
Vector3 c = (t.PointC - t.PointB).Cross(t.Normal);
c.Normalize();
p.Length = (t.PointC - t.PointA).Dot(c);
int q = ContainsVector3(t.PointA, Vertex);
if (q == -1) { p.VertexIndex = (ushort)Vertex.Count; Vertex.Add(t.PointA); }
else p.VertexIndex = (ushort)q;
q = ContainsVector3(t.Normal, Normals);
if (q == -1) { p.NormalIndex = (ushort)Normals.Count; Normals.Add(t.Normal); }
else p.NormalIndex = (ushort)q;
q = ContainsVector3(a, Normals);
if (q == -1) { p.NormalAIndex = (ushort)Normals.Count; Normals.Add(a); }
else p.NormalAIndex = (ushort)q;
q = ContainsVector3(b, Normals);
if (q == -1) { p.NormalBIndex = (ushort)Normals.Count; Normals.Add(b); }
else p.NormalBIndex = (ushort)q;
q = ContainsVector3(c, Normals);
if (q == -1) { p.NormalCIndex = (ushort)Normals.Count; Normals.Add(c); }
else p.NormalCIndex = (ushort)q;
planes.Add(p);
Triangles.Add(t);
}
}
Vertices = Vertex.ToArray();
this.Normals = Normals.ToArray();
Planes = planes.ToArray();
Header = new MKDSKCLHeader();
Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 128, 50);
FromOBJ(o, ty.Mapping, ty.Colli);
return true;
}
return false;
}
public void FromOBJ(OBJ Model, Dictionary<string, ushort> TypeMapping, Dictionary<string, bool> CollideMapping)
{
List<Vector3> Vertex = new List<Vector3>();
List<Vector3> Normals = new List<Vector3>();
List<KCLPlane> planes = new List<KCLPlane>();
List<Triangle> Triangles = new List<Triangle>();
foreach (var v in Model.Faces)
{
if (CollideMapping[v.Material])
{
Triangle t = new Triangle(Model.Vertices[v.VertexIndieces[0]], Model.Vertices[v.VertexIndieces[1]], Model.Vertices[v.VertexIndieces[2]]);
Vector3 qq = (t.PointB - t.PointA).Cross(t.PointC - t.PointA);
if ((qq.X * qq.X + qq.Y * qq.Y + qq.Z * qq.Z) < 0.01) continue;
KCLPlane p = new KCLPlane();
p.CollisionType = (ushort)(((TypeMapping[v.Material] & 0xFF) << 8) | (TypeMapping[v.Material] >> 8));
Vector3 a = (t.PointC - t.PointA).Cross(t.Normal);
a.Normalize();
a = -a;
Vector3 b = (t.PointB - t.PointA).Cross(t.Normal);
b.Normalize();
Vector3 c = (t.PointC - t.PointB).Cross(t.Normal);
c.Normalize();
p.Length = (t.PointC - t.PointA).Dot(c);
int q = ContainsVector3(t.PointA, Vertex);
if (q == -1) { p.VertexIndex = (ushort)Vertex.Count; Vertex.Add(t.PointA); }
else p.VertexIndex = (ushort)q;
q = ContainsVector3(t.Normal, Normals);
if (q == -1) { p.NormalIndex = (ushort)Normals.Count; Normals.Add(t.Normal); }
else p.NormalIndex = (ushort)q;
q = ContainsVector3(a, Normals);
if (q == -1) { p.NormalAIndex = (ushort)Normals.Count; Normals.Add(a); }
else p.NormalAIndex = (ushort)q;
q = ContainsVector3(b, Normals);
if (q == -1) { p.NormalBIndex = (ushort)Normals.Count; Normals.Add(b); }
else p.NormalBIndex = (ushort)q;
q = ContainsVector3(c, Normals);
if (q == -1) { p.NormalCIndex = (ushort)Normals.Count; Normals.Add(c); }
else p.NormalCIndex = (ushort)q;
planes.Add(p);
Triangles.Add(t);
}
}
Vertices = Vertex.ToArray();
this.Normals = Normals.ToArray();
Planes = planes.ToArray();
Header = new MKDSKCLHeader();
Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 128, 50);
}
private int ContainsVector3(Vector3 a, List<Vector3> b)
{
for (int i = 0; i < b.Count; i++)

View File

@ -102,6 +102,7 @@
<Compile Include="MKDS\NKM\PATH.cs" />
<Compile Include="MKDS\NKM\POIT.cs" />
<Compile Include="MKDS\NKM\STAG.cs" />
<Compile Include="MarioKartPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resource.Designer.cs">
<AutoGen>True</AutoGen>

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibEveryFileExplorer;
using LibEveryFileExplorer.Script;
using System.IO;
using CommonFiles;
using LibEveryFileExplorer.IO;
namespace MarioKart
{
public class MarioKartPlugin : EFEPlugin
{
public override void OnLoad()
{
EFEScript.RegisterCommand("MarioKart.MKDS.KCL.Generate", (Action<String, String, Dictionary<String, ushort>>)MarioKart_MKDS_KCL_Generate);
}
public static void MarioKart_MKDS_KCL_Generate(String OBJPath, String OutPath, Dictionary<String, ushort> TypeMapping)
{
MKDS.KCL k = new MKDS.KCL();
OBJ o = new OBJ(File.ReadAllBytes(OBJPath));
List<String> matnames = new List<string>();
foreach (var v in o.Faces) if (!matnames.Contains(v.Material)) matnames.Add(v.Material);
Dictionary<string, bool> Colli = new Dictionary<string,bool>();
foreach (string s in matnames)
{
if (!TypeMapping.ContainsKey(s)) TypeMapping.Add(s, 0);
Colli.Add(s, true);
}
k.FromOBJ(o, TypeMapping, Colli);
File.Create(OutPath).Close();
File.WriteAllBytes(OutPath, k.Write());
}
}
}