From 344fc8a55de471121d3f600cca9e95315d0e502f Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sun, 4 Mar 2018 20:32:18 -0300
Subject: [PATCH] Try fixing NvFlinger rotation with scaling, return correct
 error code on WaitSignal timeout, always display window at the center of the
 screen

---
 ChocolArm64/ATranslator.cs                    |  1 -
 Ryujinx.Core/OsHle/CondVar.cs                 |  8 +++-
 .../OsHle/Handles/KProcessScheduler.cs        | 12 ++++--
 Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs   | 38 +++++++++++--------
 Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs       |  7 +++-
 Ryujinx/Ui/GLScreen.cs                        |  4 ++
 6 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/ChocolArm64/ATranslator.cs b/ChocolArm64/ATranslator.cs
index ab434e226..1f4a922ab 100644
--- a/ChocolArm64/ATranslator.cs
+++ b/ChocolArm64/ATranslator.cs
@@ -7,7 +7,6 @@ using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Reflection.Emit;
-using System.Threading;
 
 namespace ChocolArm64
 {
diff --git a/Ryujinx.Core/OsHle/CondVar.cs b/Ryujinx.Core/OsHle/CondVar.cs
index 7b3e18521..ac3ba5749 100644
--- a/Ryujinx.Core/OsHle/CondVar.cs
+++ b/Ryujinx.Core/OsHle/CondVar.cs
@@ -24,7 +24,7 @@ namespace Ryujinx.Core.OsHle
             WaitingThreads = new List<HThread>();
         }
 
-        public void WaitForSignal(HThread Thread)
+        public bool WaitForSignal(HThread Thread)
         {
             int Count = Process.Memory.ReadInt32(CondVarAddress);
 
@@ -41,12 +41,14 @@ namespace Ryujinx.Core.OsHle
                 }
                 else
                 {
-                    Process.Scheduler.WaitForSignal(Thread, (int)(Timeout / 1000000));
+                    bool Result = Process.Scheduler.WaitForSignal(Thread, (int)(Timeout / 1000000));
 
                     lock (WaitingThreads)
                     {
                         WaitingThreads.Remove(Thread);
                     }
+
+                    return Result;
                 }
             }
 
@@ -60,6 +62,8 @@ namespace Ryujinx.Core.OsHle
             }
 
             ReleaseCondVarValue();
+
+            return true;
         }
 
         public void SetSignal(HThread Thread, int Count)
diff --git a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
index 2045f8a17..b11160781 100644
--- a/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
+++ b/Ryujinx.Core/OsHle/Handles/KProcessScheduler.cs
@@ -183,7 +183,7 @@ namespace Ryujinx.Core.OsHle.Handles
             TryResumingExecution(SchedThread);
         }
 
-        public void WaitForSignal(HThread Thread, int Timeout = -1)
+        public bool WaitForSignal(HThread Thread, int Timeout = -1)
         {
             SchedulerThread SchedThread;
 
@@ -206,22 +206,26 @@ namespace Ryujinx.Core.OsHle.Handles
                 {
                     Logging.Error($"{GetDbgThreadInfo(Thread)} was not found on the scheduler queue!");
 
-                    return;
+                    return false;
                 }
             }
 
+            bool Result;
+
             if (Timeout >= 0)
             {
                 Logging.Debug($"{GetDbgThreadInfo(Thread)} has wait timeout of {Timeout}ms.");
 
-                SchedThread.WaitEvent.WaitOne(Timeout);
+                Result = SchedThread.WaitEvent.WaitOne(Timeout);
             }
             else
             {
-                SchedThread.WaitEvent.WaitOne();
+                Result = SchedThread.WaitEvent.WaitOne();
             }
 
             TryResumingExecution(SchedThread);
+
+            return Result;
         }
 
         private void TryResumingExecution(SchedulerThread SchedThread)
diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
index b745867e9..4b5f9819a 100644
--- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs
@@ -278,39 +278,45 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
             int RealWidth  = FbWidth;
             int RealHeight = FbHeight;
 
+            float XSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX) ? -1 : 1;
+            float YSign = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY) ? -1 : 1;
+
             float ScaleX = 1;
             float ScaleY = 1;
+
             float OffsX = 0;
             float OffsY = 0;
 
             if (Crop.Right  != 0 &&
                 Crop.Bottom != 0)
             {
+                //Who knows if this is right, I was never good with math...
                 RealWidth  = Crop.Right  - Crop.Left;
                 RealHeight = Crop.Bottom - Crop.Top;
 
-                ScaleX = (float)FbWidth  / RealWidth;
-                ScaleY = (float)FbHeight / RealHeight;
+                if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90))
+                {
+                    ScaleY = (float)FbHeight / RealHeight;
+                    ScaleX = (float)FbWidth  / RealWidth;
 
-                OffsX = -(float)Crop.Left / Crop.Right;
-                OffsY = -(float)Crop.Top  / Crop.Bottom;
+                    OffsY = ((-(float)Crop.Left / Crop.Right)  + ScaleX - 1) * -XSign;
+                    OffsX = ((-(float)Crop.Top  / Crop.Bottom) + ScaleY - 1) * -YSign;
+                }
+                else
+                {
+                    ScaleX = (float)FbWidth  / RealWidth;
+                    ScaleY = (float)FbHeight / RealHeight;
 
-                OffsX += ScaleX - 1;
-                OffsY += ScaleY - 1;
+                    OffsX = ((-(float)Crop.Left / Crop.Right)  + ScaleX - 1) *  XSign;
+                    OffsY = ((-(float)Crop.Top  / Crop.Bottom) + ScaleY - 1) * -YSign;
+                }
             }
 
+            ScaleX *= XSign;
+            ScaleY *= YSign;
+
             float Rotate = 0;
 
-            if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX))
-            {
-                ScaleX = -ScaleX;
-            }
-
-            if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY))
-            {
-                ScaleY = -ScaleY;
-            }
-
             if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90))
             {
                 Rotate = -MathF.PI * 0.5f;
diff --git a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
index dec13f75e..2705272a3 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcThreadSync.cs
@@ -53,7 +53,12 @@ namespace Ryujinx.Core.OsHle.Svc
 
             Cv = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Cv);
 
-            Cv.WaitForSignal(Thread);
+            if (!Cv.WaitForSignal(Thread))
+            {
+                ThreadState.X0 = (int)SvcResult.ErrTimeout;
+
+                return;
+            }
 
             M.WaitForLock(Thread, ThreadHandle);
 
diff --git a/Ryujinx/Ui/GLScreen.cs b/Ryujinx/Ui/GLScreen.cs
index 1e48b2805..4c7cee467 100644
--- a/Ryujinx/Ui/GLScreen.cs
+++ b/Ryujinx/Ui/GLScreen.cs
@@ -29,6 +29,10 @@ namespace Ryujinx
         {
             this.Ns       = Ns;
             this.Renderer = Renderer;
+
+            Location = new Point(
+                (DisplayDevice.Default.Width  / 2) - (Width  / 2),
+                (DisplayDevice.Default.Height / 2) - (Height / 2));
         }
 
         protected override void OnLoad(EventArgs e)