diff options
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL/EnumConversion.cs')
-rw-r--r-- | src/Ryujinx.Graphics.OpenGL/EnumConversion.cs | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs new file mode 100644 index 00000000..c9a1eaa9 --- /dev/null +++ b/src/Ryujinx.Graphics.OpenGL/EnumConversion.cs @@ -0,0 +1,675 @@ +using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Shader; + +namespace Ryujinx.Graphics.OpenGL +{ + static class EnumConversion + { + public static TextureWrapMode Convert(this AddressMode mode) + { + switch (mode) + { + case AddressMode.Clamp: + return TextureWrapMode.Clamp; + case AddressMode.Repeat: + return TextureWrapMode.Repeat; + case AddressMode.MirrorClamp: + return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampExt; + case AddressMode.MirrorClampToEdge: + return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToEdgeExt; + case AddressMode.MirrorClampToBorder: + return (TextureWrapMode)ExtTextureMirrorClamp.MirrorClampToBorderExt; + case AddressMode.ClampToBorder: + return TextureWrapMode.ClampToBorder; + case AddressMode.MirroredRepeat: + return TextureWrapMode.MirroredRepeat; + case AddressMode.ClampToEdge: + return TextureWrapMode.ClampToEdge; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AddressMode)} enum value: {mode}."); + + return TextureWrapMode.Clamp; + } + + public static NvBlendEquationAdvanced Convert(this AdvancedBlendOp op) + { + switch (op) + { + case AdvancedBlendOp.Zero: + return NvBlendEquationAdvanced.Zero; + case AdvancedBlendOp.Src: + return NvBlendEquationAdvanced.SrcNv; + case AdvancedBlendOp.Dst: + return NvBlendEquationAdvanced.DstNv; + case AdvancedBlendOp.SrcOver: + return NvBlendEquationAdvanced.SrcOverNv; + case AdvancedBlendOp.DstOver: + return NvBlendEquationAdvanced.DstOverNv; + case AdvancedBlendOp.SrcIn: + return NvBlendEquationAdvanced.SrcInNv; + case AdvancedBlendOp.DstIn: + return NvBlendEquationAdvanced.DstInNv; + case AdvancedBlendOp.SrcOut: + return NvBlendEquationAdvanced.SrcOutNv; + case AdvancedBlendOp.DstOut: + return NvBlendEquationAdvanced.DstOutNv; + case AdvancedBlendOp.SrcAtop: + return NvBlendEquationAdvanced.SrcAtopNv; + case AdvancedBlendOp.DstAtop: + return NvBlendEquationAdvanced.DstAtopNv; + case AdvancedBlendOp.Xor: + return NvBlendEquationAdvanced.XorNv; + case AdvancedBlendOp.Plus: + return NvBlendEquationAdvanced.PlusNv; + case AdvancedBlendOp.PlusClamped: + return NvBlendEquationAdvanced.PlusClampedNv; + case AdvancedBlendOp.PlusClampedAlpha: + return NvBlendEquationAdvanced.PlusClampedAlphaNv; + case AdvancedBlendOp.PlusDarker: + return NvBlendEquationAdvanced.PlusDarkerNv; + case AdvancedBlendOp.Multiply: + return NvBlendEquationAdvanced.MultiplyNv; + case AdvancedBlendOp.Screen: + return NvBlendEquationAdvanced.ScreenNv; + case AdvancedBlendOp.Overlay: + return NvBlendEquationAdvanced.OverlayNv; + case AdvancedBlendOp.Darken: + return NvBlendEquationAdvanced.DarkenNv; + case AdvancedBlendOp.Lighten: + return NvBlendEquationAdvanced.LightenNv; + case AdvancedBlendOp.ColorDodge: + return NvBlendEquationAdvanced.ColordodgeNv; + case AdvancedBlendOp.ColorBurn: + return NvBlendEquationAdvanced.ColorburnNv; + case AdvancedBlendOp.HardLight: + return NvBlendEquationAdvanced.HardlightNv; + case AdvancedBlendOp.SoftLight: + return NvBlendEquationAdvanced.SoftlightNv; + case AdvancedBlendOp.Difference: + return NvBlendEquationAdvanced.DifferenceNv; + case AdvancedBlendOp.Minus: + return NvBlendEquationAdvanced.MinusNv; + case AdvancedBlendOp.MinusClamped: + return NvBlendEquationAdvanced.MinusClampedNv; + case AdvancedBlendOp.Exclusion: + return NvBlendEquationAdvanced.ExclusionNv; + case AdvancedBlendOp.Contrast: + return NvBlendEquationAdvanced.ContrastNv; + case AdvancedBlendOp.Invert: + return NvBlendEquationAdvanced.Invert; + case AdvancedBlendOp.InvertRGB: + return NvBlendEquationAdvanced.InvertRgbNv; + case AdvancedBlendOp.InvertOvg: + return NvBlendEquationAdvanced.InvertOvgNv; + case AdvancedBlendOp.LinearDodge: + return NvBlendEquationAdvanced.LineardodgeNv; + case AdvancedBlendOp.LinearBurn: + return NvBlendEquationAdvanced.LinearburnNv; + case AdvancedBlendOp.VividLight: + return NvBlendEquationAdvanced.VividlightNv; + case AdvancedBlendOp.LinearLight: + return NvBlendEquationAdvanced.LinearlightNv; + case AdvancedBlendOp.PinLight: + return NvBlendEquationAdvanced.PinlightNv; + case AdvancedBlendOp.HardMix: + return NvBlendEquationAdvanced.HardmixNv; + case AdvancedBlendOp.Red: + return NvBlendEquationAdvanced.RedNv; + case AdvancedBlendOp.Green: + return NvBlendEquationAdvanced.GreenNv; + case AdvancedBlendOp.Blue: + return NvBlendEquationAdvanced.BlueNv; + case AdvancedBlendOp.HslHue: + return NvBlendEquationAdvanced.HslHueNv; + case AdvancedBlendOp.HslSaturation: + return NvBlendEquationAdvanced.HslSaturationNv; + case AdvancedBlendOp.HslColor: + return NvBlendEquationAdvanced.HslColorNv; + case AdvancedBlendOp.HslLuminosity: + return NvBlendEquationAdvanced.HslLuminosityNv; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AdvancedBlendOp)} enum value: {op}."); + + return NvBlendEquationAdvanced.Zero; + } + + public static All Convert(this AdvancedBlendOverlap overlap) + { + switch (overlap) + { + case AdvancedBlendOverlap.Uncorrelated: + return All.UncorrelatedNv; + case AdvancedBlendOverlap.Disjoint: + return All.DisjointNv; + case AdvancedBlendOverlap.Conjoint: + return All.ConjointNv; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(AdvancedBlendOverlap)} enum value: {overlap}."); + + return All.UncorrelatedNv; + } + + public static All Convert(this BlendFactor factor) + { + switch (factor) + { + case BlendFactor.Zero: + case BlendFactor.ZeroGl: + return All.Zero; + case BlendFactor.One: + case BlendFactor.OneGl: + return All.One; + case BlendFactor.SrcColor: + case BlendFactor.SrcColorGl: + return All.SrcColor; + case BlendFactor.OneMinusSrcColor: + case BlendFactor.OneMinusSrcColorGl: + return All.OneMinusSrcColor; + case BlendFactor.SrcAlpha: + case BlendFactor.SrcAlphaGl: + return All.SrcAlpha; + case BlendFactor.OneMinusSrcAlpha: + case BlendFactor.OneMinusSrcAlphaGl: + return All.OneMinusSrcAlpha; + case BlendFactor.DstAlpha: + case BlendFactor.DstAlphaGl: + return All.DstAlpha; + case BlendFactor.OneMinusDstAlpha: + case BlendFactor.OneMinusDstAlphaGl: + return All.OneMinusDstAlpha; + case BlendFactor.DstColor: + case BlendFactor.DstColorGl: + return All.DstColor; + case BlendFactor.OneMinusDstColor: + case BlendFactor.OneMinusDstColorGl: + return All.OneMinusDstColor; + case BlendFactor.SrcAlphaSaturate: + case BlendFactor.SrcAlphaSaturateGl: + return All.SrcAlphaSaturate; + case BlendFactor.Src1Color: + case BlendFactor.Src1ColorGl: + return All.Src1Color; + case BlendFactor.OneMinusSrc1Color: + case BlendFactor.OneMinusSrc1ColorGl: + return All.OneMinusSrc1Color; + case BlendFactor.Src1Alpha: + case BlendFactor.Src1AlphaGl: + return All.Src1Alpha; + case BlendFactor.OneMinusSrc1Alpha: + case BlendFactor.OneMinusSrc1AlphaGl: + return All.OneMinusSrc1Alpha; + case BlendFactor.ConstantColor: + return All.ConstantColor; + case BlendFactor.OneMinusConstantColor: + return All.OneMinusConstantColor; + case BlendFactor.ConstantAlpha: + return All.ConstantAlpha; + case BlendFactor.OneMinusConstantAlpha: + return All.OneMinusConstantAlpha; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(BlendFactor)} enum value: {factor}."); + + return All.Zero; + } + + public static BlendEquationMode Convert(this BlendOp op) + { + switch (op) + { + case BlendOp.Add: + case BlendOp.AddGl: + return BlendEquationMode.FuncAdd; + case BlendOp.Minimum: + case BlendOp.MinimumGl: + return BlendEquationMode.Min; + case BlendOp.Maximum: + case BlendOp.MaximumGl: + return BlendEquationMode.Max; + case BlendOp.Subtract: + case BlendOp.SubtractGl: + return BlendEquationMode.FuncSubtract; + case BlendOp.ReverseSubtract: + case BlendOp.ReverseSubtractGl: + return BlendEquationMode.FuncReverseSubtract; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(BlendOp)} enum value: {op}."); + + return BlendEquationMode.FuncAdd; + } + + public static TextureCompareMode Convert(this CompareMode mode) + { + switch (mode) + { + case CompareMode.None: + return TextureCompareMode.None; + case CompareMode.CompareRToTexture: + return TextureCompareMode.CompareRToTexture; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(CompareMode)} enum value: {mode}."); + + return TextureCompareMode.None; + } + + public static All Convert(this CompareOp op) + { + switch (op) + { + case CompareOp.Never: + case CompareOp.NeverGl: + return All.Never; + case CompareOp.Less: + case CompareOp.LessGl: + return All.Less; + case CompareOp.Equal: + case CompareOp.EqualGl: + return All.Equal; + case CompareOp.LessOrEqual: + case CompareOp.LessOrEqualGl: + return All.Lequal; + case CompareOp.Greater: + case CompareOp.GreaterGl: + return All.Greater; + case CompareOp.NotEqual: + case CompareOp.NotEqualGl: + return All.Notequal; + case CompareOp.GreaterOrEqual: + case CompareOp.GreaterOrEqualGl: + return All.Gequal; + case CompareOp.Always: + case CompareOp.AlwaysGl: + return All.Always; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(CompareOp)} enum value: {op}."); + + return All.Never; + } + + public static ClipDepthMode Convert(this DepthMode mode) + { + switch (mode) + { + case DepthMode.MinusOneToOne: + return ClipDepthMode.NegativeOneToOne; + case DepthMode.ZeroToOne: + return ClipDepthMode.ZeroToOne; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(DepthMode)} enum value: {mode}."); + + return ClipDepthMode.NegativeOneToOne; + } + + public static All Convert(this DepthStencilMode mode) + { + switch (mode) + { + case DepthStencilMode.Depth: + return All.DepthComponent; + case DepthStencilMode.Stencil: + return All.StencilIndex; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(DepthStencilMode)} enum value: {mode}."); + + return All.Depth; + } + + public static CullFaceMode Convert(this Face face) + { + switch (face) + { + case Face.Back: + return CullFaceMode.Back; + case Face.Front: + return CullFaceMode.Front; + case Face.FrontAndBack: + return CullFaceMode.FrontAndBack; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(Face)} enum value: {face}."); + + return CullFaceMode.Back; + } + + public static FrontFaceDirection Convert(this FrontFace frontFace) + { + switch (frontFace) + { + case FrontFace.Clockwise: + return FrontFaceDirection.Cw; + case FrontFace.CounterClockwise: + return FrontFaceDirection.Ccw; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(FrontFace)} enum value: {frontFace}."); + + return FrontFaceDirection.Cw; + } + + public static DrawElementsType Convert(this IndexType type) + { + switch (type) + { + case IndexType.UByte: + return DrawElementsType.UnsignedByte; + case IndexType.UShort: + return DrawElementsType.UnsignedShort; + case IndexType.UInt: + return DrawElementsType.UnsignedInt; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(IndexType)} enum value: {type}."); + + return DrawElementsType.UnsignedByte; + } + + public static TextureMagFilter Convert(this MagFilter filter) + { + switch (filter) + { + case MagFilter.Nearest: + return TextureMagFilter.Nearest; + case MagFilter.Linear: + return TextureMagFilter.Linear; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(MagFilter)} enum value: {filter}."); + + return TextureMagFilter.Nearest; + } + + public static TextureMinFilter Convert(this MinFilter filter) + { + switch (filter) + { + case MinFilter.Nearest: + return TextureMinFilter.Nearest; + case MinFilter.Linear: + return TextureMinFilter.Linear; + case MinFilter.NearestMipmapNearest: + return TextureMinFilter.NearestMipmapNearest; + case MinFilter.LinearMipmapNearest: + return TextureMinFilter.LinearMipmapNearest; + case MinFilter.NearestMipmapLinear: + return TextureMinFilter.NearestMipmapLinear; + case MinFilter.LinearMipmapLinear: + return TextureMinFilter.LinearMipmapLinear; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(MinFilter)} enum value: {filter}."); + + return TextureMinFilter.Nearest; + } + + public static OpenTK.Graphics.OpenGL.PolygonMode Convert(this GAL.PolygonMode mode) + { + switch (mode) + { + case GAL.PolygonMode.Point: + return OpenTK.Graphics.OpenGL.PolygonMode.Point; + case GAL.PolygonMode.Line: + return OpenTK.Graphics.OpenGL.PolygonMode.Line; + case GAL.PolygonMode.Fill: + return OpenTK.Graphics.OpenGL.PolygonMode.Fill; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(GAL.PolygonMode)} enum value: {mode}."); + + return OpenTK.Graphics.OpenGL.PolygonMode.Fill; + } + + public static PrimitiveType Convert(this PrimitiveTopology topology) + { + switch (topology) + { + case PrimitiveTopology.Points: + return PrimitiveType.Points; + case PrimitiveTopology.Lines: + return PrimitiveType.Lines; + case PrimitiveTopology.LineLoop: + return PrimitiveType.LineLoop; + case PrimitiveTopology.LineStrip: + return PrimitiveType.LineStrip; + case PrimitiveTopology.Triangles: + return PrimitiveType.Triangles; + case PrimitiveTopology.TriangleStrip: + return PrimitiveType.TriangleStrip; + case PrimitiveTopology.TriangleFan: + return PrimitiveType.TriangleFan; + case PrimitiveTopology.Quads: + return PrimitiveType.Quads; + case PrimitiveTopology.QuadStrip: + return PrimitiveType.QuadStrip; + case PrimitiveTopology.Polygon: + return PrimitiveType.TriangleFan; + case PrimitiveTopology.LinesAdjacency: + return PrimitiveType.LinesAdjacency; + case PrimitiveTopology.LineStripAdjacency: + return PrimitiveType.LineStripAdjacency; + case PrimitiveTopology.TrianglesAdjacency: + return PrimitiveType.TrianglesAdjacency; + case PrimitiveTopology.TriangleStripAdjacency: + return PrimitiveType.TriangleStripAdjacency; + case PrimitiveTopology.Patches: + return PrimitiveType.Patches; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(PrimitiveTopology)} enum value: {topology}."); + + return PrimitiveType.Points; + } + + public static TransformFeedbackPrimitiveType ConvertToTfType(this PrimitiveTopology topology) + { + switch (topology) + { + case PrimitiveTopology.Points: + return TransformFeedbackPrimitiveType.Points; + case PrimitiveTopology.Lines: + case PrimitiveTopology.LineLoop: + case PrimitiveTopology.LineStrip: + case PrimitiveTopology.LinesAdjacency: + case PrimitiveTopology.LineStripAdjacency: + return TransformFeedbackPrimitiveType.Lines; + case PrimitiveTopology.Triangles: + case PrimitiveTopology.TriangleStrip: + case PrimitiveTopology.TriangleFan: + case PrimitiveTopology.TrianglesAdjacency: + case PrimitiveTopology.TriangleStripAdjacency: + return TransformFeedbackPrimitiveType.Triangles; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(PrimitiveTopology)} enum value: {topology}."); + + return TransformFeedbackPrimitiveType.Points; + } + + public static OpenTK.Graphics.OpenGL.StencilOp Convert(this GAL.StencilOp op) + { + switch (op) + { + case GAL.StencilOp.Keep: + case GAL.StencilOp.KeepGl: + return OpenTK.Graphics.OpenGL.StencilOp.Keep; + case GAL.StencilOp.Zero: + case GAL.StencilOp.ZeroGl: + return OpenTK.Graphics.OpenGL.StencilOp.Zero; + case GAL.StencilOp.Replace: + case GAL.StencilOp.ReplaceGl: + return OpenTK.Graphics.OpenGL.StencilOp.Replace; + case GAL.StencilOp.IncrementAndClamp: + case GAL.StencilOp.IncrementAndClampGl: + return OpenTK.Graphics.OpenGL.StencilOp.Incr; + case GAL.StencilOp.DecrementAndClamp: + case GAL.StencilOp.DecrementAndClampGl: + return OpenTK.Graphics.OpenGL.StencilOp.Decr; + case GAL.StencilOp.Invert: + case GAL.StencilOp.InvertGl: + return OpenTK.Graphics.OpenGL.StencilOp.Invert; + case GAL.StencilOp.IncrementAndWrap: + case GAL.StencilOp.IncrementAndWrapGl: + return OpenTK.Graphics.OpenGL.StencilOp.IncrWrap; + case GAL.StencilOp.DecrementAndWrap: + case GAL.StencilOp.DecrementAndWrapGl: + return OpenTK.Graphics.OpenGL.StencilOp.DecrWrap; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(GAL.StencilOp)} enum value: {op}."); + + return OpenTK.Graphics.OpenGL.StencilOp.Keep; + } + + public static All Convert(this SwizzleComponent swizzleComponent) + { + switch (swizzleComponent) + { + case SwizzleComponent.Zero: + return All.Zero; + case SwizzleComponent.One: + return All.One; + case SwizzleComponent.Red: + return All.Red; + case SwizzleComponent.Green: + return All.Green; + case SwizzleComponent.Blue: + return All.Blue; + case SwizzleComponent.Alpha: + return All.Alpha; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(SwizzleComponent)} enum value: {swizzleComponent}."); + + return All.Zero; + } + + public static ImageTarget ConvertToImageTarget(this Target target) + { + return (ImageTarget)target.Convert(); + } + + public static TextureTarget Convert(this Target target) + { + switch (target) + { + case Target.Texture1D: + return TextureTarget.Texture1D; + case Target.Texture2D: + return TextureTarget.Texture2D; + case Target.Texture3D: + return TextureTarget.Texture3D; + case Target.Texture1DArray: + return TextureTarget.Texture1DArray; + case Target.Texture2DArray: + return TextureTarget.Texture2DArray; + case Target.Texture2DMultisample: + return TextureTarget.Texture2DMultisample; + case Target.Texture2DMultisampleArray: + return TextureTarget.Texture2DMultisampleArray; + case Target.Cubemap: + return TextureTarget.TextureCubeMap; + case Target.CubemapArray: + return TextureTarget.TextureCubeMapArray; + case Target.TextureBuffer: + return TextureTarget.TextureBuffer; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(Target)} enum value: {target}."); + + return TextureTarget.Texture2D; + } + + public static NvViewportSwizzle Convert(this ViewportSwizzle swizzle) + { + switch (swizzle) + { + case ViewportSwizzle.PositiveX: + return NvViewportSwizzle.ViewportSwizzlePositiveXNv; + case ViewportSwizzle.PositiveY: + return NvViewportSwizzle.ViewportSwizzlePositiveYNv; + case ViewportSwizzle.PositiveZ: + return NvViewportSwizzle.ViewportSwizzlePositiveZNv; + case ViewportSwizzle.PositiveW: + return NvViewportSwizzle.ViewportSwizzlePositiveWNv; + case ViewportSwizzle.NegativeX: + return NvViewportSwizzle.ViewportSwizzleNegativeXNv; + case ViewportSwizzle.NegativeY: + return NvViewportSwizzle.ViewportSwizzleNegativeYNv; + case ViewportSwizzle.NegativeZ: + return NvViewportSwizzle.ViewportSwizzleNegativeZNv; + case ViewportSwizzle.NegativeW: + return NvViewportSwizzle.ViewportSwizzleNegativeWNv; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ViewportSwizzle)} enum value: {swizzle}."); + + return NvViewportSwizzle.ViewportSwizzlePositiveXNv; + } + + public static All Convert(this LogicalOp op) + { + switch (op) + { + case LogicalOp.Clear: + return All.Clear; + case LogicalOp.And: + return All.And; + case LogicalOp.AndReverse: + return All.AndReverse; + case LogicalOp.Copy: + return All.Copy; + case LogicalOp.AndInverted: + return All.AndInverted; + case LogicalOp.Noop: + return All.Noop; + case LogicalOp.Xor: + return All.Xor; + case LogicalOp.Or: + return All.Or; + case LogicalOp.Nor: + return All.Nor; + case LogicalOp.Equiv: + return All.Equiv; + case LogicalOp.Invert: + return All.Invert; + case LogicalOp.OrReverse: + return All.OrReverse; + case LogicalOp.CopyInverted: + return All.CopyInverted; + case LogicalOp.OrInverted: + return All.OrInverted; + case LogicalOp.Nand: + return All.Nand; + case LogicalOp.Set: + return All.Set; + } + + Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(LogicalOp)} enum value: {op}."); + + return All.Never; + } + + public static ShaderType Convert(this ShaderStage stage) + { + return stage switch + { + ShaderStage.Compute => ShaderType.ComputeShader, + ShaderStage.Vertex => ShaderType.VertexShader, + ShaderStage.TessellationControl => ShaderType.TessControlShader, + ShaderStage.TessellationEvaluation => ShaderType.TessEvaluationShader, + ShaderStage.Geometry => ShaderType.GeometryShader, + ShaderStage.Fragment => ShaderType.FragmentShader, + _ => ShaderType.VertexShader + }; + } + } +} |