From 73c4651a28a0e9c0c63e38e6563640a751458486 Mon Sep 17 00:00:00 2001 From: Maik Macho Date: Mon, 30 Oct 2017 19:49:23 +0100 Subject: [PATCH] XnaToFna 17.11, two days before November... --- Properties/AssemblyInfo.cs | 2 +- lib-projs/FNA | 2 +- src/Content/ContentHelper.cs | 13 +++--- src/Content/XNBContent.cs | 77 ++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 10 deletions(-) diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index de204cc..384a090 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. -[assembly: AssemblyVersion ("17.09.1.*")] +[assembly: AssemblyVersion ("17.11.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/lib-projs/FNA b/lib-projs/FNA index 7fc4ddd..be99b70 160000 --- a/lib-projs/FNA +++ b/lib-projs/FNA @@ -1 +1 @@ -Subproject commit 7fc4ddd4c6a1ea1d474c85c9ea9243d1204eb819 +Subproject commit be99b7050297e8ebf7117eb11c5be03fa2739d6d diff --git a/src/Content/ContentHelper.cs b/src/Content/ContentHelper.cs index 5a72c49..3aaa6cc 100644 --- a/src/Content/ContentHelper.cs +++ b/src/Content/ContentHelper.cs @@ -79,10 +79,12 @@ public static void UpdateContent(string path, bool patchXNB = true, bool patchXA } - public static void PatchContent(string path, Action patcher, bool writeToTmp = true) { - if (writeToTmp) { + public static void PatchContent(string path, Action patcher, bool writeToTmp = true, string pathOutput = null) { + pathOutput = pathOutput ?? path; + if (writeToTmp) File.Delete(path + ".tmp"); - } + if (pathOutput != path) + File.Delete(pathOutput); using (Stream input = File.OpenRead(path)) using (BinaryReader reader = new BinaryReader(input)) @@ -95,8 +97,9 @@ public static void PatchContent(string path, Action(path/*.Substring(0, path.Length - 4)*/); (obj as IDisposable)?.Dispose(); + Game.Content.Unload(); // Replace .xnb with .tmp File.Delete(path); @@ -46,12 +47,35 @@ public static void TransformContent(string path) { stream.Position = 6; writer.Write((uint) stream.Length); } + + FNAContentManagerHooks.Enabled = false; + + // If we just loaded a texture, reload and dump it as PNG. + /* + if (obj is Texture2D) { + // FNA can't save DXT1, DXT3 and DXT5 textures... unless we force conversion. + FNAContentManagerHooks.SupportsDxt1 = false; + FNAContentManagerHooks.SupportsS3tc = false; + using (Texture2D tex = Game.Content.Load(path)) { + Log($"[TransformContent] Dumping texture, original format: {((Texture2D) obj).Format}"); + if (File.Exists(path + ".png")) + File.Delete(path + ".png"); + using (Stream stream = File.OpenWrite(path + ".png")) + tex.SaveAsPng(stream, tex.Width, tex.Height); + } + FNAContentManagerHooks.SupportsDxt1 = null; + FNAContentManagerHooks.SupportsS3tc = null; + } + */ + + FNAContentManagerHooks.Enabled = true; } // Yo dawg, I heard you like patching... public static class FNAContentManagerHooks { private static bool IsHooked = false; + public static bool Enabled = true; public static void Hook() { if (IsHooked) @@ -71,21 +95,47 @@ public static void Hook() { typeof(ContentTypeReaderManager).GetField("typeCreators", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); typeCreators["Microsoft.Xna.Framework.Content.EffectReader, Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553"] = () => new EffectTransformer(); - typeCreators["Microsoft.Xna.Framework.Content.SoundEffectReader"] // This somehow isn't the full name... + typeCreators["Microsoft.Xna.Framework.Content.SoundEffectReader"] // Games somehow don't use the full name for this one... = () => new SoundEffectTransformer(); + + object gl = typeof(GraphicsDevice).GetField("GLDevice", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(Game.GraphicsDevice); + Type t_gl = gl.GetType(); + orig_SupportsDxt1 = (bool) t_gl.GetProperty("SupportsDxt1").GetValue(gl); + Hook(t_gl, "get_SupportsDxt1", out orig_get_SupportsDxt1); + orig_SupportsS3tc = (bool) t_gl.GetProperty("SupportsS3tc").GetValue(gl); + Hook(t_gl, "get_SupportsS3tc", out orig_get_SupportsS3tc); + } + + private static MethodBase Find(Type type, string name) { + MethodBase found = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + if (found != null) + return found; + + if (name.StartsWith("get_") || name.StartsWith("set_")) { + PropertyInfo prop = type.GetProperty(name.Substring(4), BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + if (name[0] == 'g') + found = prop.GetGetMethod(true); + else + found = prop.GetSetMethod(true); + } + + return found; } private static void Hook(Type type, string name, out T trampoline) { trampoline = - type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + Find(type, name) .Detour( - typeof(FNAContentManagerHooks).GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) + Find(typeof(FNAContentManagerHooks), name) ); } private delegate ContentReader d_GetContentReaderFromXnb(ContentManager self, string originalAssetName, ref Stream stream, BinaryReader xnbReader, char platform, Action recordDisposableObject); private static d_GetContentReaderFromXnb orig_GetContentReaderFromXnb; private static ContentReader GetContentReaderFromXnb(ContentManager self, string originalAssetName, ref Stream stream, BinaryReader xnbReader, char platform, Action recordDisposableObject) { + if (!Enabled) + return orig_GetContentReaderFromXnb(self, originalAssetName, ref stream, xnbReader, platform, recordDisposableObject); + // output will be disposed with the ContentReader. Stream output = File.OpenWrite(originalAssetName + ".tmp"); @@ -109,11 +159,32 @@ private static ContentReader GetContentReaderFromXnb(ContentManager self, string private delegate void d_ctor_ContentReader(ContentReader self, ContentManager manager, Stream stream, GraphicsDevice graphicsDevice, string assetName, int version, char platform, Action recordDisposableObject); private static d_ctor_ContentReader orig_ctor_ContentReader; private static void ctor_ContentReader(ContentReader self, ContentManager manager, Stream stream, GraphicsDevice graphicsDevice, string assetName, int version, char platform, Action recordDisposableObject) { + if (!Enabled) { + orig_ctor_ContentReader(self, manager, stream, graphicsDevice, assetName, version, platform, recordDisposableObject); + return; + } + // What... what is this? Where am I? *Who* am I?! stream = new CopyingStream(stream, null); orig_ctor_ContentReader(self, manager, stream, graphicsDevice, assetName, version, platform, recordDisposableObject); } + public static bool? SupportsDxt1; + private static bool orig_SupportsDxt1; + private delegate bool d_get_SupportsDxt1(object self); + private static d_get_SupportsDxt1 orig_get_SupportsDxt1; + private static bool get_SupportsDxt1(object self) { + return SupportsDxt1 ?? orig_SupportsDxt1; + } + + public static bool? SupportsS3tc; + private static bool orig_SupportsS3tc; + private delegate bool d_get_SupportsS3tc(object self); + private static d_get_SupportsS3tc orig_get_SupportsS3tc; + private static bool get_SupportsS3tc(object self) { + return SupportsS3tc ?? orig_SupportsS3tc; + } + } }