private void Swap(CodeParser.Class clss, string v1, string v2, int[] locations)
        {
            var a = clss.Functions.IndexOf(clss.Functions.Single(x => x.Name == v1));
            var b = clss.Functions.IndexOf(clss.Functions.Single(x => x.Name == v2));

            var s = locations[a];

            locations[a] = locations[b];
            locations[b] = s;
        }
        void WriteFunctionPointerReader(CodeParser.Class clss)
        {
            // TODO - we'll probably have to do this PER platform

            int[] standardLocations = new int[clss.Functions.Count];
            int[] windowsLocations  = new int[clss.Functions.Count];

            for (int i = 0; i < clss.Functions.Count; i++)
            {
                windowsLocations[i]  = i * 8;
                standardLocations[i] = i * 8;
            }

            //
            // MSVC switches the order in the vtable of overloaded functions
            // I'm not going to try to try to work out how to order shit
            // so lets just manually fix shit here
            //
            if (clss.Name == "ISteamUserStats")
            {
                Swap(clss, "GetStat1", "GetStat2", windowsLocations);
                Swap(clss, "SetStat1", "SetStat2", windowsLocations);
                Swap(clss, "GetUserStat1", "GetUserStat2", windowsLocations);
                Swap(clss, "GetGlobalStat1", "GetGlobalStat2", windowsLocations);
                Swap(clss, "GetGlobalStatHistory1", "GetGlobalStatHistory2", windowsLocations);
            }

            if (clss.Name == "ISteamGameServerStats")
            {
                Swap(clss, "GetUserStat1", "GetUserStat2", windowsLocations);
                Swap(clss, "SetUserStat1", "SetUserStat2", windowsLocations);
            }

            if (clss.Name == "ISteamUGC")
            {
                Swap(clss, "CreateQueryAllUGCRequest1", "CreateQueryAllUGCRequest2", windowsLocations);
            }


            StartBlock($"public override void InitInternals()");
            {
                var different = new List <int>();

                for (int i = 0; i < clss.Functions.Count; i++)
                {
                    var func = clss.Functions[i];

                    if (Cleanup.IsDeprecated($"{clss.Name}.{func.Name}"))
                    {
                        WriteLine($" // {func.Name} is deprecated");
                    }
                    else
                    {
                        if (standardLocations[i] != windowsLocations[i])
                        {
                            different.Add(i);
                            continue;
                        }

                        WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, Platform.MemoryOffset( {standardLocations[i]} ) ) );");
                    }
                }

                if (different.Count > 0)
                {
                    WriteLine("");
                    WriteLine("#if PLATFORM_WIN");
                    foreach (var i in different)
                    {
                        var func = clss.Functions[i];
                        WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, Platform.MemoryOffset( {windowsLocations[i]} ) ) );");
                    }
                    WriteLine("#else");
                    foreach (var i in different)
                    {
                        var func = clss.Functions[i];
                        WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, Platform.MemoryOffset( {standardLocations[i]} ) ) );");
                    }
                    WriteLine("#endif");
                }
            }
            EndBlock();

            StartBlock($"internal override void Shutdown()");
            {
                WriteLine($"base.Shutdown();");
                WriteLine("");

                for (int i = 0; i < clss.Functions.Count; i++)
                {
                    var func            = clss.Functions[i];
                    var returnType      = BaseType.Parse(func.ReturnType);
                    var args            = func.Arguments.Select(x => BaseType.Parse(x.Value, x.Key)).ToArray();
                    var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

                    if (Cleanup.IsDeprecated($"{clss.Name}.{func.Name}"))
                    {
                        continue;
                    }

                    WriteLine($"_{func.Name} = null;");
                }
            }
            EndBlock();
        }
        private void WriteFunction(CodeParser.Class clss, CodeParser.Class.Function func)
        {
            var returnType = BaseType.Parse(func.ReturnType);

            returnType.Func = func.Name;

            var args = func.Arguments.Select(x =>
            {
                var bt  = BaseType.Parse(x.Value, x.Key);
                bt.Func = func.Name;
                return(bt);
            }).ToArray();
            var argstr         = string.Join(", ", args.Select(x => x.AsArgument()));
            var delegateargstr = string.Join(", ", args.Select(x => x.AsArgument()));

            var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

            if (returnType is SteamApiCallType sap)
            {
                sap.CallResult = func.CallResult;

                argstr = string.Join(", ", args.Select(x => x.AsArgument().Replace("ref ", " /* ref */ ")));
            }

            WriteLine($"#region FunctionMeta");

            WriteLine($"[UnmanagedFunctionPointer( Platform.MemberConvention )]");

            if (returnType.ReturnAttribute != null)
            {
                WriteLine(returnType.ReturnAttribute);
            }

            if (returnType.IsReturnedWeird)
            {
                WriteLine("#if PLATFORM_WIN");
                WriteLine($"private delegate void F{func.Name}( IntPtr self, ref {returnType.TypeName} retVal, {delegateargstr} );".Replace(" retVal,  )", " retVal )"));
                WriteLine("#else");
            }

            WriteLine($"private delegate {returnType.TypeNameFrom} F{func.Name}( IntPtr self, {delegateargstr} );".Replace("( IntPtr self,  )", "( IntPtr self )"));

            if (returnType.IsReturnedWeird)
            {
                WriteLine("#endif");
            }

            WriteLine($"private F{func.Name} _{func.Name};");

            WriteLine();
            WriteLine($"#endregion");

            StartBlock($"internal {returnType.ReturnType} {func.Name}( {argstr} )".Replace("(  )", "()"));
            {
                var callargs = string.Join(", ", args.Select(x => x.AsCallArgument()));

                if (returnType.IsReturnedWeird)
                {
                    WriteLine("#if PLATFORM_WIN");
                    {
                        WriteLine($"var retVal = default( {returnType.TypeName} );");
                        WriteLine($"_{func.Name}( Self, ref retVal, {callargs} );".Replace(",  );", " );"));
                        WriteLine($"{returnType.Return( "retVal" )}");
                    }
                    WriteLine("#else");
                }

                if (returnType.IsVoid)
                {
                    WriteLine($"_{func.Name}( Self, {callargs} );".Replace("( Self,  )", "( Self )"));
                }
                else
                {
                    var v = $"_{func.Name}( Self, {callargs} )".Replace("( Self,  )", "( Self )");

                    WriteLine(returnType.Return(v));
                }

                if (returnType.IsReturnedWeird)
                {
                    WriteLine("#endif");
                }
            }
            EndBlock();
        }
        void WriteFunctionPointerReader(CodeParser.Class clss)
        {
            // TODO - we'll probably have to do this PER platform

            int[] locations = new int[clss.Functions.Count];

            for (int i = 0; i < clss.Functions.Count; i++)
            {
                locations[i] = i * 8;
            }

            //
            // MSVC switches the order in the vtable of overloaded functions
            // I'm not going to try to try to work out how to order shit
            // so lets just manually fix shit here
            //
            if (clss.Name == "ISteamUserStats")
            {
                Swap(clss, "GetStat1", "GetStat2", locations);
                Swap(clss, "SetStat1", "SetStat2", locations);
                Swap(clss, "GetUserStat1", "GetUserStat2", locations);
                Swap(clss, "GetGlobalStat1", "GetGlobalStat2", locations);
                Swap(clss, "GetGlobalStatHistory1", "GetGlobalStatHistory2", locations);
            }

            if (clss.Name == "ISteamUGC")
            {
                Swap(clss, "CreateQueryAllUGCRequest1", "CreateQueryAllUGCRequest2", locations);
            }


            StartBlock($"public override void InitInternals()");
            {
                for (int i = 0; i < clss.Functions.Count; i++)
                {
                    var func            = clss.Functions[i];
                    var returnType      = BaseType.Parse(func.ReturnType);
                    var args            = func.Arguments.Select(x => BaseType.Parse(x.Value, x.Key)).ToArray();
                    var regularpos      = i * 8;
                    var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

                    if (Cleanup.IsDeprecated($"{clss.Name}.{func.Name}"))
                    {
                        WriteLine($" // {func.Name} is deprecated - {locations[i]}");
                    }
                    else
                    {
                        var pos = $"Config.Os == OsType.Windows ? {locations[i]} : {regularpos} ";

                        if (regularpos == locations[i])
                        {
                            pos = regularpos.ToString();
                        }

                        WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, {pos}) );");

                        if (windowsSpecific)
                        {
                            WriteLine($"_{func.Name}_Windows = Marshal.GetDelegateForFunctionPointer<F{func.Name}_Windows>( Marshal.ReadIntPtr( VTable, {pos}) );");
                        }
                    }
                }
            }
            EndBlock();

            StartBlock($"internal override void Shutdown()");
            {
                WriteLine($"base.Shutdown();");
                WriteLine("");

                for (int i = 0; i < clss.Functions.Count; i++)
                {
                    var func            = clss.Functions[i];
                    var returnType      = BaseType.Parse(func.ReturnType);
                    var args            = func.Arguments.Select(x => BaseType.Parse(x.Value, x.Key)).ToArray();
                    var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

                    if (Cleanup.IsDeprecated($"{clss.Name}.{func.Name}"))
                    {
                        continue;
                    }

                    WriteLine($"_{func.Name} = null;");

                    if (windowsSpecific)
                    {
                        WriteLine($"_{func.Name}_Windows = null;");
                    }
                }
            }
            EndBlock();
        }
        private void WriteFunction(CodeParser.Class clss, CodeParser.Class.Function func)
        {
            var returnType = BaseType.Parse(func.ReturnType);

            returnType.Func = func.Name;

            var args = func.Arguments.Select(x =>
            {
                var bt  = BaseType.Parse(x.Value, x.Key);
                bt.Func = func.Name;
                return(bt);
            }).ToArray();
            var argstr         = string.Join(", ", args.Select(x => x.AsArgument()));
            var delegateargstr = string.Join(", ", args.Select(x => x.AsArgument()));

            var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

            if (returnType is SteamApiCallType sap)
            {
                sap.CallResult = func.CallResult;

                argstr = string.Join(", ", args.Select(x => x.AsArgument().Replace("ref ", " /* ref */ ")));
            }

            WriteLine($"#region FunctionMeta");

            WriteLine($"[UnmanagedFunctionPointer( CallingConvention.ThisCall )]");

            if (returnType.ReturnAttribute != null)
            {
                WriteLine(returnType.ReturnAttribute);
            }

            WriteLine($"private delegate {returnType.TypeNameFrom} F{func.Name}( IntPtr self, {delegateargstr} );".Replace("( IntPtr self,  )", "( IntPtr self )"));
            WriteLine($"private F{func.Name} _{func.Name};");

            if (windowsSpecific)
            {
                var delegateargstrw = string.Join(", ", args.Select(x => x.AsWinArgument()));
                WriteLine($"[UnmanagedFunctionPointer( CallingConvention.ThisCall )]");

                if (returnType.IsReturnedWeird)
                {
                    var windelargs = $"ref {returnType.TypeName} retVal, {delegateargstrw}".Trim(',', ' ');
                    WriteLine($"private delegate void F{func.Name}_Windows( IntPtr self, {windelargs} );".Replace("( IntPtr self,  )", "( IntPtr self )"));
                }
                else
                {
                    if (returnType.ReturnAttribute != null)
                    {
                        WriteLine(returnType.ReturnAttribute);
                    }


                    WriteLine($"private delegate {returnType.TypeNameFrom} F{func.Name}_Windows( IntPtr self, {delegateargstrw} );".Replace("( IntPtr self,  )", "( IntPtr self )"));
                }

                WriteLine($"private F{func.Name}_Windows _{func.Name}_Windows;");
            }

            WriteLine();
            WriteLine($"#endregion");

            StartBlock($"internal {returnType.ReturnType} {func.Name}( {argstr} )".Replace("(  )", "()"));
            {
                var callargs = string.Join(", ", args.Select(x => x.AsCallArgument()));

                if (returnType.IsReturnedWeird)
                {
                    StartBlock("if ( Config.Os == OsType.Windows )");
                    {
                        WriteLine($"var retVal = default( {returnType.TypeName} );");
                        WriteLine($"_{func.Name}_Windows( Self, ref retVal, {callargs} );".Replace(",  );", " );"));
                        WriteLine($"{returnType.Return( "retVal" )}");
                    }
                    EndBlock();
                    WriteLine();
                }
                else if (windowsSpecific)
                {
                    StartBlock("if ( Config.Os == OsType.Windows )");
                    {
                        var wincallargs = callargs;

                        foreach (var arg in args)
                        {
                            if (!arg.WindowsSpecific)
                            {
                                continue;
                            }

                            if (arg.IsVector)
                            {
                                WriteLine($"{arg.TypeName}.Pack8[] {arg.VarName}_windows = {arg.VarName};");
                            }
                            else
                            {
                                WriteLine($"{arg.TypeName}.Pack8 {arg.VarName}_windows = {arg.VarName};");
                            }

                            wincallargs = wincallargs.Replace($" {arg.VarName}", $" {arg.VarName}_windows");
                        }

                        if (!returnType.IsVoid)
                        {
                            Write("var retVal = ");
                        }

                        WriteLine($"_{func.Name}_Windows( Self, {wincallargs} );".Replace("( Self,  )", "( Self )"));

                        foreach (var arg in args)
                        {
                            if (!arg.WindowsSpecific)
                            {
                                continue;
                            }

                            WriteLine($"{arg.VarName} = {arg.VarName}_windows;");
                        }

                        if (!returnType.IsVoid)
                        {
                            WriteLine(returnType.Return("retVal"));
                        }
                    }
                    EndBlock();
                    WriteLine();
                }

                if (returnType.IsVoid)
                {
                    WriteLine($"_{func.Name}( Self, {callargs} );".Replace("( Self,  )", "( Self )"));
                }
                else
                {
                    var v = $"_{func.Name}( Self, {callargs} )".Replace("( Self,  )", "( Self )");

                    WriteLine(returnType.Return(v));
                }
            }
            EndBlock();
        }
        private void WriteFunction(CodeParser.Class clss, CodeParser.Class.Function func)
        {
            var returnType = BaseType.Parse(func.ReturnType);

            returnType.Func = func.Name;

            var args = func.Arguments.Select(x =>
            {
                var bt  = BaseType.Parse(x.Value, x.Key);
                bt.Func = func.Name;
                return(bt);
            }).ToArray();

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] is StringType)
                {
                    if (args[i + 1] is IntType || args[i + 1] is UIntType)
                    {
                        if (args[i + 1].Ref == string.Empty)
                        {
                            args[i + 1] = new ConstValueType(args[i + 1], "(1024 * 32)");
                        }
                    }
                    else
                    {
                        throw new System.Exception($"String Builder Next Type Is {args[i+1].GetType()}");
                    }
                }
            }

            var argstr         = string.Join(", ", args.Where(x => !x.ShouldSkipAsArgument).Select(x => x.AsArgument()));;
            var delegateargstr = string.Join(", ", args.Select(x => x.AsNativeArgument()));

            var windowsSpecific = NeedsWindowsSpecificFunction(func, returnType, args);

            if (returnType is SteamApiCallType sap)
            {
                sap.CallResult = func.CallResult;

                argstr = string.Join(", ", args.Select(x => x.AsArgument().Replace("ref ", " /* ref */ ")));
            }

            WriteLine($"#region FunctionMeta");

            WriteLine($"[UnmanagedFunctionPointer( Platform.MemberConvention )]");

            if (returnType.ReturnAttribute != null)
            {
                WriteLine(returnType.ReturnAttribute);
            }

            if (returnType.IsReturnedWeird)
            {
                WriteLine("#if PLATFORM_WIN");
                WriteLine($"private delegate void F{func.Name}( IntPtr self, ref {returnType.TypeName} retVal, {delegateargstr} );".Replace(" retVal,  )", " retVal )"));
                WriteLine("#else");
            }

            WriteLine($"private delegate {returnType.TypeNameFrom} F{func.Name}( IntPtr self, {delegateargstr} );".Replace("( IntPtr self,  )", "( IntPtr self )"));

            if (returnType.IsReturnedWeird)
            {
                WriteLine("#endif");
            }

            WriteLine($"private F{func.Name} _{func.Name};");

            WriteLine();
            WriteLine($"#endregion");

            StartBlock($"internal {returnType.ReturnType} {func.Name}( {argstr} )".Replace("(  )", "()"));
            {
                var callargs = string.Join(", ", args.Select(x => x.AsCallArgument()));

                //
                // Code before any calls
                //
                foreach (var arg in args)
                {
                    if (arg is StringType sb)
                    {
                        WriteLine($"IntPtr mem{sb.VarName} = Helpers.TakeMemory();");
                    }
                }

                //
                // The actual call
                //
                if (returnType.IsReturnedWeird)
                {
                    WriteLine("#if PLATFORM_WIN");
                    {
                        WriteLine($"var retVal = default( {returnType.TypeName} );");
                        WriteLine($"_{func.Name}( Self, ref retVal, {callargs} );".Replace(",  );", " );"));
                        WriteLine($"{returnType.Return( "retVal" )}");
                    }
                    WriteLine("#else");
                }

                if (returnType.IsVoid)
                {
                    WriteLine($"_{func.Name}( Self, {callargs} );".Replace("( Self,  )", "( Self )"));
                }
                else
                {
                    WriteLine($"var returnValue = _{func.Name}( Self, {callargs} );".Replace("( Self,  )", "( Self )"));
                }

                //
                // Code after the call
                //
                foreach (var arg in args)
                {
                    if (arg is StringType sb)
                    {
                        WriteLine($"{sb.VarName} = Helpers.MemoryToString( mem{sb.VarName} );");
                    }
                }

                //
                // Return
                //
                if (!returnType.IsVoid)
                {
                    WriteLine(returnType.Return("returnValue"));
                }

                if (returnType.IsReturnedWeird)
                {
                    WriteLine("#endif");
                }
            }
            EndBlock();
        }
Esempio n. 7
0
        void WriteFunctionPointerReader(CodeParser.Class clss)
        {
            // TODO - we'll probably have to do this PER platform

            int[] locations = new int[clss.Functions.Count];

            for (int i = 0; i < clss.Functions.Count; i++)
            {
                locations[i] = i * 8;
            }

            //
            // MSVC switches the order in the vtable of overloaded functions
            // I'm not going to try to try to work out how to order shit
            // so lets just manually fix shit here
            //
            if (clss.Name == "ISteamUserStats")
            {
                Swap(clss, "GetStat1", "GetStat2", locations);
                Swap(clss, "SetStat1", "SetStat2", locations);
                Swap(clss, "GetUserStat1", "GetUserStat2", locations);
                Swap(clss, "GetGlobalStat1", "GetGlobalStat2", locations);
                Swap(clss, "GetGlobalStatHistory1", "GetGlobalStatHistory2", locations);
            }

            if (clss.Name == "ISteamUGC")
            {
                Swap(clss, "CreateQueryAllUGCRequest1", "CreateQueryAllUGCRequest2", locations);
            }


            StartBlock($"public override void InitInternals()");
            {
                for (int i = 0; i < clss.Functions.Count; i++)
                {
                    var func       = clss.Functions[i];
                    var returnType = BaseType.Parse(func.ReturnType);
                    var regularpos = i * 8;

                    if (Cleanup.IsDeprecated($"{clss.Name}.{func.Name}"))
                    {
                        WriteLine($" // {func.Name} is deprecated - {locations[i]}");
                    }
                    else
                    {
                        if (regularpos != locations[i])
                        {
                            WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, Config.Os == OsType.Windows ? {locations[i]} : {regularpos} ) );");
                            if (returnType.IsReturnedWeird)
                            {
                                throw new System.NotImplementedException();
                            }
                        }
                        else
                        {
                            WriteLine($"_{func.Name} = Marshal.GetDelegateForFunctionPointer<F{func.Name}>( Marshal.ReadIntPtr( VTable, {locations[i]}) );");

                            if (returnType.IsReturnedWeird)
                            {
                                WriteLine($"_{func.Name}_Windows = Marshal.GetDelegateForFunctionPointer<F{func.Name}_Windows>( Marshal.ReadIntPtr( VTable, {locations[i]}) );");
                            }
                        }
                    }
                }
            }
            EndBlock();
        }