diff --git a/MicrosoftIris.sln b/MicrosoftIris.sln index 38a1859..e8cc5fe 100644 --- a/MicrosoftIris.sln +++ b/MicrosoftIris.sln @@ -3,10 +3,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32421.90 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIX", "UIX\UIX.csproj", "{78A8B08C-C0E9-4BAC-9AF6-58D3A55C05C9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UIX", "UIX\UIX.csproj", "{78A8B08C-C0E9-4BAC-9AF6-58D3A55C05C9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UIX.RenderApi", "UIX.RenderApi\UIX.RenderApi.csproj", "{CB2B7609-C7B8-4E2A-82D8-DD631B70B621}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIX.Debug", "UIX.Debug\UIX.Debug.csproj", "{B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1F0A2AD3-81C3-4A53-8AEF-DC67ABC63183}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDebugClient", "Tests\SimpleDebugClient\SimpleDebugClient.csproj", "{283532A3-A744-4C1C-960C-0B4FE9AF98C9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,10 +47,37 @@ Global {CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x64.Build.0 = Release|x64 {CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x86.ActiveCfg = Release|x86 {CB2B7609-C7B8-4E2A-82D8-DD631B70B621}.Release|x86.Build.0 = Release|x86 + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|x64.ActiveCfg = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|x64.Build.0 = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|x86.ActiveCfg = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Debug|x86.Build.0 = Debug|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|Any CPU.Build.0 = Release|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|x64.ActiveCfg = Release|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|x64.Build.0 = Release|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|x86.ActiveCfg = Release|Any CPU + {B5E91A1A-82F4-404B-8CAA-8E4D298EB6DE}.Release|x86.Build.0 = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|x64.ActiveCfg = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|x64.Build.0 = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|x86.ActiveCfg = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Debug|x86.Build.0 = Debug|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|Any CPU.Build.0 = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|x64.ActiveCfg = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|x64.Build.0 = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|x86.ActiveCfg = Release|Any CPU + {283532A3-A744-4C1C-960C-0B4FE9AF98C9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {283532A3-A744-4C1C-960C-0B4FE9AF98C9} = {1F0A2AD3-81C3-4A53-8AEF-DC67ABC63183} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25300402-D4C7-4F92-841D-894A842FF055} EndGlobalSection diff --git a/Tests/SimpleDebugClient/Program.cs b/Tests/SimpleDebugClient/Program.cs new file mode 100644 index 0000000..b61b4e1 --- /dev/null +++ b/Tests/SimpleDebugClient/Program.cs @@ -0,0 +1,13 @@ +using Microsoft.Iris.Debug; + +namespace SimpleDebugClient +{ + internal class Program + { + static void Main(string[] args) + { + Bridge bridge = new(OwlCore.Remoting.RemotingMode.Client); + while (true) ; + } + } +} \ No newline at end of file diff --git a/Tests/SimpleDebugClient/SimpleDebugClient.csproj b/Tests/SimpleDebugClient/SimpleDebugClient.csproj new file mode 100644 index 0000000..1ec250a --- /dev/null +++ b/Tests/SimpleDebugClient/SimpleDebugClient.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/UIX.Debug/Bridge.cs b/UIX.Debug/Bridge.cs new file mode 100644 index 0000000..2645eb7 --- /dev/null +++ b/UIX.Debug/Bridge.cs @@ -0,0 +1,47 @@ +#if ZUNE5 + +using OwlCore.Remoting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Microsoft.Iris.Debug +{ + [RemoteProperty] + [RemoteMethod] + [RemoteOptions(RemotingDirection.Bidirectional)] + public class Bridge : IDisposable + { + private readonly MemberRemote _memberRemote; + + public Bridge(RemotingMode mode) + { + // Pass the instance you want to remote into MemberRemote() with an ID that is identical on both machines for that instance. + // An instance will not receive member changes until you do this. + // Optionally leave out the message handler. Uses the default set by MemberRemote.SetDefaultMessageHandler(handler); + IrisDebugRemoteMessageHandler handler = new(mode); + _memberRemote = new MemberRemote(this, typeof(Bridge).Assembly.FullName, handler); + } + + [RemoteMethod, RemoteOptions(RemotingDirection.HostToClient)] + public void LogInterpreterOpCode(object context, Data.InterpreterEntry entry) + { + System.Diagnostics.Debug.WriteLine($"[HOST] [Interpreter] [{context}] {entry}"); + } + + [RemoteMethod, RemoteOptions(RemotingDirection.HostToClient)] + public void LogDispatcher(string message) + { + System.Diagnostics.Debug.WriteLine($"[HOST] [Dispatcher] {message}"); + } + + public void Dispose() + { + // Dispose of the MemberRemote when finished. Forgetting to do this WILL result in a memory leak. + _memberRemote.Dispose(); + } + } +} + +#endif diff --git a/UIX.Debug/Data/InterpreterEntry.cs b/UIX.Debug/Data/InterpreterEntry.cs new file mode 100644 index 0000000..9e0ca55 --- /dev/null +++ b/UIX.Debug/Data/InterpreterEntry.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.Iris.Debug.Data +{ + public class InterpreterEntry + { + public InterpreterEntry(object opCode, params OpCodeArgument[] args) + { + OpCode = opCode; + Arguments = args; + } + + public object OpCode { get; private set; } + public OpCodeArgument[] Arguments { get; private set; } + + public override string ToString() => $"{OpCode}({string.Join(", ", (IEnumerable)Arguments)})"; + } + + public class OpCodeArgument + { + public Type Type { get; private set; } + public object Value { get; private set; } + + public override string ToString() => $"{Type} {Value}"; + } +} diff --git a/UIX.Debug/FodyWeavers.xml b/UIX.Debug/FodyWeavers.xml new file mode 100644 index 0000000..ed2dd57 --- /dev/null +++ b/UIX.Debug/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + diff --git a/UIX.Debug/IrisDebugRemoteMessageHandler.cs b/UIX.Debug/IrisDebugRemoteMessageHandler.cs new file mode 100644 index 0000000..6066613 --- /dev/null +++ b/UIX.Debug/IrisDebugRemoteMessageHandler.cs @@ -0,0 +1,46 @@ +#if ZUNE5 + +using OwlCore.Remoting; +using OwlCore.Remoting.Transfer; +using OwlCore.Remoting.Transfer.MessageConverters; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Iris.Debug +{ + internal class IrisDebugRemoteMessageHandler : IRemoteMessageHandler + { + public RemotingMode Mode { get; set; } + public MemberSignatureScope MemberSignatureScope { get; set; } + + public IRemoteMessageConverter MessageConverter { get; } + + public bool IsInitialized { get; private set; } + + public event EventHandler MessageReceived; + + public IrisDebugRemoteMessageHandler(RemotingMode mode) + { + // The inbox newtonsoft converter. Tested with various types, structs, primitives, classes and more. + // Provided by the lib for convenience, the underlying OwlCore.Remoting system doesn't use this property. + MessageConverter = new NewtonsoftRemoteMessageConverter(); + + Mode = mode; + } + + public Task InitAsync(CancellationToken cancellationToken = default) + { + IsInitialized = true; + return Task.CompletedTask; + } + + public Task SendMessageAsync(IRemoteMessage memberMessage, CancellationToken? cancellationToken = null) + { + // Serialize and send the message. + return Task.CompletedTask; + } + } +} + +#endif diff --git a/UIX.Debug/UIX.Debug.csproj b/UIX.Debug/UIX.Debug.csproj new file mode 100644 index 0000000..d9cb41e --- /dev/null +++ b/UIX.Debug/UIX.Debug.csproj @@ -0,0 +1,23 @@ + + + + net35;net40;net6.0;netstandard2.0 + Microsoft.Iris.Debug + + false + + + + true + + + + + + + + 5.0.0.0 + $(DefineConstants);ZUNE5 + + + diff --git a/UIX/Microsoft/Iris/Queues/Dispatcher.cs b/UIX/Microsoft/Iris/Queues/Dispatcher.cs index 1d992d5..dcc36fb 100644 --- a/UIX/Microsoft/Iris/Queues/Dispatcher.cs +++ b/UIX/Microsoft/Iris/Queues/Dispatcher.cs @@ -4,6 +4,7 @@ // MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11 // Assembly location: C:\Program Files\Zune\UIX.dll +using Microsoft.Iris.Debug; using System; using System.IO; using System.IO.Pipes; @@ -174,12 +175,19 @@ namespace Microsoft.Iris.Queues } } +#if ZUNE5 + private static Bridge Bridge { get; } = new(OwlCore.Remoting.RemotingMode.Host); +#endif + /// /// Sends a message via /// /// public static void SendDebugMessage(string message) { +#if ZUNE5 + Bridge.LogDispatcher(message); +#else if (Application.DebugSettings.OpenDebugPipe && DebugPipe.IsConnected && DebugPipe.CanWrite) { DebugPipe.WriteByte(0x01); @@ -188,6 +196,7 @@ namespace Microsoft.Iris.Queues DebugPipe.Write(buffer, 0, buffer.Length); DebugPipe.Flush(); } +#endif } } } diff --git a/UIX/UIX.csproj b/UIX/UIX.csproj index 872cc63..9af1344 100644 --- a/UIX/UIX.csproj +++ b/UIX/UIX.csproj @@ -12,12 +12,19 @@ True ..\36MSApp1024.snk AnyCPU;x64;x86 + + false + + + true + + @@ -39,8 +46,8 @@ - + + 5.0.0.0 + $(DefineConstants);ZUNE5 + \ No newline at end of file