From c26ddd6259796e5b0b187989ce3e21b52edb00a8 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 23 Jun 2018 02:00:44 -0300
Subject: [PATCH] Fix 3 graphics related issues (#180)

* Fix 3 graphics related bugs

* OGLShader shouldn't be public (yet)
---
 Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs     |  3 +++
 Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs    | 15 ++++++++-------
 Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs       |  1 +
 Ryujinx.HLE/Gpu/NvGpuEngine3d.cs                  | 11 ++++++++++-
 Ryujinx.HLE/Gpu/TextureFactory.cs                 | 11 +++++++++++
 Ryujinx.HLE/Gpu/TextureHelper.cs                  |  1 +
 .../OsHle/Services/Nv/NvMap/NvMapHandle.cs        |  6 +++---
 Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapIoctl.cs |  6 +++---
 8 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index 1bcedacba6..77f16b81fa 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -80,6 +80,7 @@ namespace Ryujinx.Graphics.Gal.Shader
                 { ShaderIrInst.Frcp,   GetFrcpExpr   },
                 { ShaderIrInst.Frsq,   GetFrsqExpr   },
                 { ShaderIrInst.Fsin,   GetFsinExpr   },
+                { ShaderIrInst.Fsqrt,  GetFsqrtExpr  },
                 { ShaderIrInst.Ftos,   GetFtosExpr   },
                 { ShaderIrInst.Ftou,   GetFtouExpr   },
                 { ShaderIrInst.Ipa,    GetIpaExpr    },
@@ -716,6 +717,8 @@ namespace Ryujinx.Graphics.Gal.Shader
 
         private string GetFsinExpr(ShaderIrOp Op) => GetUnaryCall(Op, "sin");
 
+        private string GetFsqrtExpr(ShaderIrOp Op) => GetUnaryCall(Op, "sqrt");
+
         private string GetFtosExpr(ShaderIrOp Op)
         {
             return "int(" + GetOperExpr(Op, Op.OperandA) + ")";
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
index 065ab34416..0763d3caf6 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
@@ -217,7 +217,7 @@ namespace Ryujinx.Graphics.Gal.Shader
 
         public static void Mufu(ShaderIrBlock Block, long OpCode)
         {
-            int SubOp = (int)(OpCode >> 20) & 7;
+            int SubOp = (int)(OpCode >> 20) & 0xf;
 
             bool AbsA = ((OpCode >> 46) & 1) != 0;
             bool NegA = ((OpCode >> 48) & 1) != 0;
@@ -226,12 +226,13 @@ namespace Ryujinx.Graphics.Gal.Shader
 
             switch (SubOp)
             {
-                case 0: Inst = ShaderIrInst.Fcos; break;
-                case 1: Inst = ShaderIrInst.Fsin; break;
-                case 2: Inst = ShaderIrInst.Fex2; break;
-                case 3: Inst = ShaderIrInst.Flg2; break;
-                case 4: Inst = ShaderIrInst.Frcp; break;
-                case 5: Inst = ShaderIrInst.Frsq; break;
+                case 0: Inst = ShaderIrInst.Fcos;  break;
+                case 1: Inst = ShaderIrInst.Fsin;  break;
+                case 2: Inst = ShaderIrInst.Fex2;  break;
+                case 3: Inst = ShaderIrInst.Flg2;  break;
+                case 4: Inst = ShaderIrInst.Frcp;  break;
+                case 5: Inst = ShaderIrInst.Frsq;  break;
+                case 8: Inst = ShaderIrInst.Fsqrt; break;
 
                 default: throw new NotImplementedException(SubOp.ToString());
             }
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs
index 2de50a4a78..9841f58ff0 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs
@@ -43,6 +43,7 @@ namespace Ryujinx.Graphics.Gal.Shader
         Frcp,
         Frsq,
         Fsin,
+        Fsqrt,
         Ftos,
         Ftou,
         Ipa,
diff --git a/Ryujinx.HLE/Gpu/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/NvGpuEngine3d.cs
index deb622fef4..6d03e6b89d 100644
--- a/Ryujinx.HLE/Gpu/NvGpuEngine3d.cs
+++ b/Ryujinx.HLE/Gpu/NvGpuEngine3d.cs
@@ -248,6 +248,15 @@ namespace Ryujinx.HLE.Gpu
 
             int TextureHandle = Vmm.ReadInt32(Position);
 
+            if (TextureHandle == 0)
+            {
+                //TODO: Is this correct?
+                //Some games like puyo puyo will have 0 handles.
+                //It may be just normal behaviour or a bug caused by sync issues.
+                //The game does initialize the value properly after through.
+                return;
+            }
+
             int TicIndex = (TextureHandle >>  0) & 0xfffff;
             int TscIndex = (TextureHandle >> 20) & 0xfff;
 
@@ -314,7 +323,7 @@ namespace Ryujinx.HLE.Gpu
                     continue;
                 }
 
-                for (int Cbuf = 0; Cbuf < ConstBuffers.Length; Cbuf++)
+                for (int Cbuf = 0; Cbuf < ConstBuffers[Index].Length; Cbuf++)
                 {
                     ConstBuffer Cb = ConstBuffers[Index][Cbuf];
 
diff --git a/Ryujinx.HLE/Gpu/TextureFactory.cs b/Ryujinx.HLE/Gpu/TextureFactory.cs
index 9a92a01678..94c6eb183d 100644
--- a/Ryujinx.HLE/Gpu/TextureFactory.cs
+++ b/Ryujinx.HLE/Gpu/TextureFactory.cs
@@ -41,6 +41,17 @@ namespace Ryujinx.HLE.Gpu
 
             TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);
 
+            if (Swizzle == TextureSwizzle.BlockLinear ||
+                Swizzle == TextureSwizzle.BlockLinearColorKey)
+            {
+                TextureAddress &= ~0x1ffL;
+            }
+            else if (Swizzle == TextureSwizzle.Pitch ||
+                     Swizzle == TextureSwizzle.PitchColorKey)
+            {
+                TextureAddress &= ~0x1fL;
+            }
+
             int Pitch = (Tic[3] & 0xffff) << 5;
 
             int BlockHeightLog2 = (Tic[3] >> 3) & 7;
diff --git a/Ryujinx.HLE/Gpu/TextureHelper.cs b/Ryujinx.HLE/Gpu/TextureHelper.cs
index e48e25ad80..237d87abca 100644
--- a/Ryujinx.HLE/Gpu/TextureHelper.cs
+++ b/Ryujinx.HLE/Gpu/TextureHelper.cs
@@ -10,6 +10,7 @@ namespace Ryujinx.HLE.Gpu
         {
             switch (Texture.Swizzle)
             {
+                case TextureSwizzle._1dBuffer:
                 case TextureSwizzle.Pitch:
                 case TextureSwizzle.PitchColorKey:
                      return new LinearSwizzle(Texture.Pitch, Bpp);
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapHandle.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapHandle.cs
index 7902034c64..21fce700c3 100644
--- a/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapHandle.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapHandle.cs
@@ -24,14 +24,14 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvMap
             this.Size = Size;
         }
 
-        public long IncrementRefCount()
+        public void IncrementRefCount()
         {
-            return Interlocked.Increment(ref Dupes);
+            Interlocked.Increment(ref Dupes);
         }
 
         public long DecrementRefCount()
         {
-            return Interlocked.Decrement(ref Dupes);
+            return Interlocked.Decrement(ref Dupes) + 1;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapIoctl.cs b/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapIoctl.cs
index 376b74c1e0..43de4edb19 100644
--- a/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapIoctl.cs
+++ b/Ryujinx.HLE/OsHle/Services/Nv/NvMap/NvMapIoctl.cs
@@ -163,9 +163,9 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvMap
                 return NvResult.InvalidInput;
             }
 
-            long RefCount = Map.DecrementRefCount();
+            long OldRefCount = Map.DecrementRefCount();
 
-            if (RefCount <= 0)
+            if (OldRefCount <= 1)
             {
                 DeleteNvMap(Context, Args.Handle);
 
@@ -178,7 +178,7 @@ namespace Ryujinx.HLE.OsHle.Services.Nv.NvMap
                 Args.Flags = FlagNotFreedYet;
             }
 
-            Args.RefCount = RefCount;
+            Args.RefCount = OldRefCount;
             Args.Size     = Map.Size;
 
             AMemoryHelper.Write(Context.Memory, OutputPosition, Args);