diff --git a/Ryujinx.Headless.SDL2/HideCursor.cs b/Ryujinx.Headless.SDL2/HideCursor.cs
new file mode 100644
index 00000000..2dc0bd6a
--- /dev/null
+++ b/Ryujinx.Headless.SDL2/HideCursor.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Headless.SDL2
+{
+    public enum HideCursor
+    {
+        Never,
+        OnIdle,
+        Always
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs b/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs
index d1d0872b..69b0f42f 100644
--- a/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs
+++ b/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs
@@ -5,7 +5,6 @@ using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.OpenGL;
 using Ryujinx.Input.HLE;
 using System;
-
 using static SDL2.SDL;
 
 namespace Ryujinx.Headless.SDL2.OpenGL
@@ -103,7 +102,13 @@ namespace Ryujinx.Headless.SDL2.OpenGL
         private GraphicsDebugLevel _glLogLevel;
         private SDL2OpenGLContext _openGLContext;
 
-        public OpenGLWindow(InputManager inputManager, GraphicsDebugLevel glLogLevel, AspectRatio aspectRatio, bool enableMouse) : base(inputManager, glLogLevel, aspectRatio, enableMouse)
+        public OpenGLWindow(
+            InputManager inputManager,
+            GraphicsDebugLevel glLogLevel,
+            AspectRatio aspectRatio,
+            bool enableMouse,
+            HideCursor hideCursor)
+            : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursor)
         {
             _glLogLevel = glLogLevel;
         }
@@ -161,4 +166,4 @@ namespace Ryujinx.Headless.SDL2.OpenGL
             SDL_GL_SwapWindow(WindowHandle);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Headless.SDL2/Options.cs b/Ryujinx.Headless.SDL2/Options.cs
index 209ce228..49233bce 100644
--- a/Ryujinx.Headless.SDL2/Options.cs
+++ b/Ryujinx.Headless.SDL2/Options.cs
@@ -6,6 +6,14 @@ namespace Ryujinx.Headless.SDL2
 {
     public class Options
     {
+        // General
+
+        [Option("root-data-dir", Required = false, HelpText = "Set the custom folder path for Ryujinx data.")]
+        public string BaseDataDir { get; set; }
+
+        [Option("profile", Required = false, HelpText = "Set the user profile to launch the game with.")]
+        public string UserProfile { get; set; }
+
         // Input
 
         [Option("input-profile-1", Required = false, HelpText = "Set the input profile in use for Player 1.")]
@@ -23,7 +31,7 @@ namespace Ryujinx.Headless.SDL2
         [Option("input-profile-5", Required = false, HelpText = "Set the input profile in use for Player 5.")]
         public string InputProfile5Name { get; set; }
 
-        [Option("input-profile-6", Required = false, HelpText = "Set the input profile in use for Player 5.")]
+        [Option("input-profile-6", Required = false, HelpText = "Set the input profile in use for Player 6.")]
         public string InputProfile6Name { get; set; }
 
         [Option("input-profile-7", Required = false, HelpText = "Set the input profile in use for Player 7.")]
@@ -63,42 +71,45 @@ namespace Ryujinx.Headless.SDL2
         public string InputIdHandheld { get; set; }
 
         [Option("enable-keyboard", Required = false, Default = false, HelpText = "Enable or disable keyboard support (Independent from controllers binding).")]
-        public bool? EnableKeyboard { get; set; }
+        public bool EnableKeyboard { get; set; }
 
         [Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
-        public bool? EnableMouse { get; set; }
+        public bool EnableMouse { get; set; }
+
+        [Option("hide-cursor", Required = false, Default = HideCursor.OnIdle, HelpText = "Change when the cursor gets hidden.")]
+        public HideCursor HideCursor { get; set; }
 
         [Option("list-input-profiles", Required = false, HelpText = "List inputs profiles.")]
-        public bool? ListInputProfiles { get; set; }
+        public bool ListInputProfiles { get; set; }
 
         [Option("list-inputs-ids", Required = false, HelpText = "List inputs ids.")]
         public bool ListInputIds { get; set; }
 
         // System
 
-        [Option("enable-ptc", Required = false, Default = true, HelpText = "Enables profiled translation cache persistency.")]
-        public bool? EnablePtc { get; set; }
+        [Option("disable-ptc", Required = false, HelpText = "Disables profiled persistent translation cache.")]
+        public bool DisablePtc { get; set; }
 
         [Option("enable-internet-connection", Required = false, Default = false, HelpText = "Enables guest Internet connection.")]
-        public bool? EnableInternetAccess { get; set; }
+        public bool EnableInternetAccess { get; set; }
 
-        [Option("enable-fs-integrity-checks", Required = false, Default = true, HelpText = "Enables integrity checks on Game content files.")]
-        public bool? EnableFsIntegrityChecks { get; set; }
+        [Option("disable-fs-integrity-checks", Required = false, HelpText = "Disables integrity checks on Game content files.")]
+        public bool DisableFsIntegrityChecks { get; set; }
 
         [Option("fs-global-access-log-mode", Required = false, Default = 0, HelpText = "Enables FS access log output to the console.")]
         public int FsGlobalAccessLogMode { get; set; }
 
-        [Option("enable-vsync", Required = false, Default = true, HelpText = "Enables Vertical Sync.")]
-        public bool? EnableVsync { get; set; }
+        [Option("disable-vsync", Required = false, HelpText = "Disables Vertical Sync.")]
+        public bool DisableVsync { get; set; }
 
-        [Option("enable-shader-cache", Required = false, Default = true, HelpText = "Enables Shader cache.")]
-        public bool? EnableShaderCache { get; set; }
+        [Option("disable-shader-cache", Required = false, HelpText = "Disables Shader cache.")]
+        public bool DisableShaderCache { get; set; }
 
         [Option("enable-texture-recompression", Required = false, Default = false, HelpText = "Enables Texture recompression.")]
-        public bool? EnableTextureRecompression { get; set; }
+        public bool EnableTextureRecompression { get; set; }
 
-        [Option("enable-docked-mode", Required = false, Default = true, HelpText = "Enables Docked Mode.")]
-        public bool? EnableDockedMode { get; set; }
+        [Option("disable-docked-mode", Required = false, HelpText = "Disables Docked Mode.")]
+        public bool DisableDockedMode { get; set; }
 
         [Option("system-language", Required = false, Default = SystemLanguage.AmericanEnglish, HelpText = "Change System Language.")]
         public SystemLanguage SystemLanguage { get; set; }
@@ -120,32 +131,32 @@ namespace Ryujinx.Headless.SDL2
 
         // Logging
 
-        [Option("enable-file-logging", Required = false, Default = false, HelpText = "Enables logging to a file on disk.")]
-        public bool? EnableFileLog { get; set; }
+        [Option("disable-file-logging", Required = false, Default = false, HelpText = "Disables logging to a file on disk.")]
+        public bool DisableFileLog { get; set; }
 
         [Option("enable-debug-logs", Required = false, Default = false, HelpText = "Enables printing debug log messages.")]
-        public bool? LoggingEnableDebug { get; set; }
+        public bool LoggingEnableDebug { get; set; }
 
-        [Option("enable-stub-logs", Required = false, Default = true, HelpText = "Enables printing stub log messages.")]
-        public bool? LoggingEnableStub { get; set; }
+        [Option("disable-stub-logs", Required = false, HelpText = "Disables printing stub log messages.")]
+        public bool LoggingDisableStub { get; set; }
 
-        [Option("enable-info-logs", Required = false, Default = true, HelpText = "Enables printing info log messages.")]
-        public bool? LoggingEnableInfo { get; set; }
+        [Option("disable-info-logs", Required = false, HelpText = "Disables printing info log messages.")]
+        public bool LoggingDisableInfo { get; set; }
 
-        [Option("enable-warning-logs", Required = false, Default = true, HelpText = "Enables printing warning log messages.")]
-        public bool? LoggingEnableWarning { get; set; }
+        [Option("disable-warning-logs", Required = false, HelpText = "Disables printing warning log messages.")]
+        public bool LoggingDisableWarning { get; set; }
 
-        [Option("enable-error-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")]
-        public bool? LoggingEnableError { get; set; }
+        [Option("disable-error-logs", Required = false, HelpText = "Disables printing error log messages.")]
+        public bool LoggingEnableError { get; set; }
 
         [Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
-        public bool? LoggingEnableTrace { get; set; }
+        public bool LoggingEnableTrace { get; set; }
 
-        [Option("enable-guest-logs", Required = false, Default = true, HelpText = "Enables printing guest log messages.")]
-        public bool? LoggingEnableGuest { get; set; }
+        [Option("disable-guest-logs", Required = false, HelpText = "Disables printing guest log messages.")]
+        public bool LoggingDisableGuest { get; set; }
 
         [Option("enable-fs-access-logs", Required = false, Default = false, HelpText = "Enables printing FS access log messages.")]
-        public bool? LoggingEnableFsAccessLog { get; set; }
+        public bool LoggingEnableFsAccessLog { get; set; }
 
         [Option("graphics-debug-level", Required = false, Default = GraphicsDebugLevel.None, HelpText = "Change Graphics API debug log level.")]
         public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; }
@@ -164,6 +175,9 @@ namespace Ryujinx.Headless.SDL2
         [Option("backend-threading", Required = false, Default = BackendThreading.Auto, HelpText = "Whether or not backend threading is enabled. The \"Auto\" setting will determine whether threading should be enabled at runtime.")]
         public BackendThreading BackendThreading { get; set; }
 
+        [Option("disable-macro-hle", Required= false, HelpText = "Disables high-level emulation of Macro code. Leaving this enabled improves performance but may cause graphical glitches in some games.")]
+        public bool DisableMacroHLE { get; set; }
+
         [Option("graphics-shaders-dump-path", Required = false, HelpText = "Dumps shaders in this local directory. (Developer only)")]
         public string GraphicsShadersDumpPath { get; set; }
 
@@ -176,14 +190,14 @@ namespace Ryujinx.Headless.SDL2
         // Hacks
 
         [Option("expand-ram", Required = false, Default = false, HelpText = "Expands the RAM amount on the emulated system from 4GiB to 6GiB.")]
-        public bool? ExpandRam { get; set; }
+        public bool ExpandRam { get; set; }
 
         [Option("ignore-missing-services", Required = false, Default = false, HelpText = "Enable ignoring missing services.")]
-        public bool? IgnoreMissingServices { get; set; }
+        public bool IgnoreMissingServices { get; set; }
 
         // Values
 
         [Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
         public string InputPath { get; set; }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Headless.SDL2/Program.cs b/Ryujinx.Headless.SDL2/Program.cs
index 84363e1f..6ea3a98d 100644
--- a/Ryujinx.Headless.SDL2/Program.cs
+++ b/Ryujinx.Headless.SDL2/Program.cs
@@ -33,7 +33,6 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text.Json;
 using System.Threading;
-
 using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
 using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
 using Key = Ryujinx.Common.Configuration.Hid.Key;
@@ -63,20 +62,6 @@ namespace Ryujinx.Headless.SDL2
 
             Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
 
-            AppDataManager.Initialize(null);
-
-            _virtualFileSystem = VirtualFileSystem.CreateInstance();
-            _libHacHorizonManager = new LibHacHorizonManager();
-
-            _libHacHorizonManager.InitializeFsServer(_virtualFileSystem);
-            _libHacHorizonManager.InitializeArpServer();
-            _libHacHorizonManager.InitializeBcatServer();
-            _libHacHorizonManager.InitializeSystemClients();
-
-            _contentManager = new ContentManager(_virtualFileSystem);
-            _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient);
-            _userChannelPersistence = new UserChannelPersistence();
-
             if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
             {
                 AutoResetEvent invoked = new AutoResetEvent(false);
@@ -97,15 +82,9 @@ namespace Ryujinx.Headless.SDL2
                 };
             }
 
-            _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
-
-            GraphicsConfig.EnableShaderCache = true;
-
             Parser.Default.ParseArguments<Options>(args)
-            .WithParsed(options => Load(options))
+            .WithParsed(Load)
             .WithNotParsed(errors => errors.Output());
-
-            _inputManager.Dispose();
         }
 
         private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
@@ -343,6 +322,24 @@ namespace Ryujinx.Headless.SDL2
 
         static void Load(Options option)
         {
+            AppDataManager.Initialize(option.BaseDataDir);
+
+            _virtualFileSystem = VirtualFileSystem.CreateInstance();
+            _libHacHorizonManager = new LibHacHorizonManager();
+
+            _libHacHorizonManager.InitializeFsServer(_virtualFileSystem);
+            _libHacHorizonManager.InitializeArpServer();
+            _libHacHorizonManager.InitializeBcatServer();
+            _libHacHorizonManager.InitializeSystemClients();
+
+            _contentManager = new ContentManager(_virtualFileSystem);
+            _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile);
+            _userChannelPersistence = new UserChannelPersistence();
+
+            _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
+
+            GraphicsConfig.EnableShaderCache = true;
+
             IGamepad gamepad;
 
             if (option.ListInputIds)
@@ -378,8 +375,8 @@ namespace Ryujinx.Headless.SDL2
             }
 
             _inputConfiguration = new List<InputConfig>();
-            _enableKeyboard = (bool)option.EnableKeyboard;
-            _enableMouse = (bool)option.EnableMouse;
+            _enableKeyboard = option.EnableKeyboard;
+            _enableMouse = option.EnableMouse;
 
             void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
             {
@@ -407,16 +404,16 @@ namespace Ryujinx.Headless.SDL2
             }
 
             // Setup logging level
-            Logger.SetEnable(LogLevel.Debug, (bool)option.LoggingEnableDebug);
-            Logger.SetEnable(LogLevel.Stub, (bool)option.LoggingEnableStub);
-            Logger.SetEnable(LogLevel.Info, (bool)option.LoggingEnableInfo);
-            Logger.SetEnable(LogLevel.Warning, (bool)option.LoggingEnableWarning);
-            Logger.SetEnable(LogLevel.Error, (bool)option.LoggingEnableError);
-            Logger.SetEnable(LogLevel.Trace, (bool)option.LoggingEnableTrace);
-            Logger.SetEnable(LogLevel.Guest, (bool)option.LoggingEnableGuest);
-            Logger.SetEnable(LogLevel.AccessLog, (bool)option.LoggingEnableFsAccessLog);
+            Logger.SetEnable(LogLevel.Debug, option.LoggingEnableDebug);
+            Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
+            Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
+            Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
+            Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
+            Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
+            Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
+            Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
 
-            if ((bool)option.EnableFileLog)
+            if (!option.DisableFileLog)
             {
                 Logger.AddTarget(new AsyncLogTargetWrapper(
                     new FileLogTarget(ReleaseInformation.GetBaseApplicationDirectory(), "file"),
@@ -426,11 +423,12 @@ namespace Ryujinx.Headless.SDL2
             }
 
             // Setup graphics configuration
-            GraphicsConfig.EnableShaderCache = (bool)option.EnableShaderCache;
-            GraphicsConfig.EnableTextureRecompression = (bool)option.EnableTextureRecompression;
+            GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
+            GraphicsConfig.EnableTextureRecompression = option.EnableTextureRecompression;
             GraphicsConfig.ResScale = option.ResScale;
             GraphicsConfig.MaxAnisotropy = option.MaxAnisotropy;
             GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
+            GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
 
             while (true)
             {
@@ -443,6 +441,8 @@ namespace Ryujinx.Headless.SDL2
 
                 _userChannelPersistence.ShouldRestart = false;
             }
+
+            _inputManager.Dispose();
         }
 
         private static void SetupProgressHandler()
@@ -479,8 +479,8 @@ namespace Ryujinx.Headless.SDL2
         private static WindowBase CreateWindow(Options options)
         {
             return options.GraphicsBackend == GraphicsBackend.Vulkan
-                ? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, (bool)options.EnableMouse)
-                : new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, (bool)options.EnableMouse);
+                ? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursor)
+                : new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursor);
         }
 
         private static IRenderer CreateRenderer(Options options, WindowBase window)
@@ -533,20 +533,20 @@ namespace Ryujinx.Headless.SDL2
                                                                   _userChannelPersistence,
                                                                   renderer,
                                                                   new SDL2HardwareDeviceDriver(),
-                                                                  (bool)options.ExpandRam ? MemoryConfiguration.MemoryConfiguration6GiB : MemoryConfiguration.MemoryConfiguration4GiB,
+                                                                  options.ExpandRam ? MemoryConfiguration.MemoryConfiguration6GiB : MemoryConfiguration.MemoryConfiguration4GiB,
                                                                   window,
                                                                   options.SystemLanguage,
                                                                   options.SystemRegion,
-                                                                  (bool)options.EnableVsync,
-                                                                  (bool)options.EnableDockedMode,
-                                                                  (bool)options.EnablePtc,
-                                                                  (bool)options.EnableInternetAccess,
-                                                                  (bool)options.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
+                                                                  !options.DisableVsync,
+                                                                  !options.DisableDockedMode,
+                                                                  !options.DisablePtc,
+                                                                  options.EnableInternetAccess,
+                                                                  !options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
                                                                   options.FsGlobalAccessLogMode,
                                                                   options.SystemTimeOffset,
                                                                   options.SystemTimeZone,
                                                                   options.MemoryManagerMode,
-                                                                  (bool)options.IgnoreMissingServices,
+                                                                  options.IgnoreMissingServices,
                                                                   options.AspectRatio,
                                                                   options.AudioVolume);
 
@@ -649,7 +649,7 @@ namespace Ryujinx.Headless.SDL2
             }
             else
             {
-                Logger.Warning?.Print(LogClass.Application, "Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
+                Logger.Warning?.Print(LogClass.Application, $"Couldn't load '{options.InputPath}'. Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
 
                 _emulationContext.Dispose();
 
diff --git a/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj b/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
index 44a16205..81ef53fe 100644
--- a/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
+++ b/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj
@@ -42,6 +42,10 @@
       </Content>
 	</ItemGroup>
 
+  <ItemGroup>
+    <EmbeddedResource Include="Ryujinx.bmp" />
+  </ItemGroup>
+
   <!-- Due to .net core 3.1 embedded resource loading -->
   <PropertyGroup>
     <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
diff --git a/Ryujinx.Headless.SDL2/Ryujinx.bmp b/Ryujinx.Headless.SDL2/Ryujinx.bmp
new file mode 100644
index 00000000..413f3b21
Binary files /dev/null and b/Ryujinx.Headless.SDL2/Ryujinx.bmp differ
diff --git a/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs b/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
index 236d4769..bdf428cc 100644
--- a/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
+++ b/Ryujinx.Headless.SDL2/SDL2MouseDriver.cs
@@ -10,7 +10,12 @@ namespace Ryujinx.Headless.SDL2
 {
     class SDL2MouseDriver : IGamepadDriver
     {
+        private const int CursorHideIdleTime = 8; // seconds
+
         private bool _isDisposed;
+        private HideCursor _hideCursor;
+        private bool _isHidden;
+        private long _lastCursorMoveTime;
 
         public bool[] PressedButtons { get; }
 
@@ -18,9 +23,16 @@ namespace Ryujinx.Headless.SDL2
         public Vector2 Scroll { get; private set; }
         public Size _clientSize;
 
-        public SDL2MouseDriver()
+        public SDL2MouseDriver(HideCursor hideCursor)
         {
             PressedButtons = new bool[(int)MouseButton.Count];
+            _hideCursor = hideCursor;
+
+            if (_hideCursor == HideCursor.Always)
+            {
+                SDL_ShowCursor(SDL_DISABLE);
+                _isHidden = true;
+            }
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -31,26 +43,75 @@ namespace Ryujinx.Headless.SDL2
             return (MouseButton)(rawButton - 1);
         }
 
-        public void Update(SDL_Event evnt)
+        public void UpdatePosition()
         {
-            if (evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN || evnt.type == SDL_EventType.SDL_MOUSEBUTTONUP)
+            SDL_GetMouseState(out int posX, out int posY);
+            Vector2 position = new(posX, posY);
+
+            if (CurrentPosition != position)
             {
-                uint rawButton = evnt.button.button;
+                CurrentPosition = position;
+                _lastCursorMoveTime = Stopwatch.GetTimestamp();
+            }
 
-                if (rawButton > 0 && rawButton <= (int)MouseButton.Count)
+            CheckIdle();
+        }
+
+        private void CheckIdle()
+        {
+            if (_hideCursor != HideCursor.OnIdle)
+            {
+                return;
+            }
+
+            long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
+
+            if (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency)
+            {
+                if (!_isHidden)
                 {
-                    PressedButtons[(int)DriverButtonToMouseButton(rawButton)] = evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN;
-
-                    CurrentPosition = new Vector2(evnt.button.x, evnt.button.y);
+                    SDL_ShowCursor(SDL_DISABLE);
+                    _isHidden = true;
                 }
             }
-            else if (evnt.type == SDL_EventType.SDL_MOUSEMOTION)
+            else
             {
-                CurrentPosition = new Vector2(evnt.motion.x, evnt.motion.y);
+                if (_isHidden)
+                {
+                    SDL_ShowCursor(SDL_ENABLE);
+                    _isHidden = false;
+                }
             }
-            else if (evnt.type == SDL_EventType.SDL_MOUSEWHEEL)
+        }
+
+        public void Update(SDL_Event evnt)
+        {
+            switch (evnt.type)
             {
-                Scroll = new Vector2(evnt.wheel.x, evnt.wheel.y);
+                case SDL_EventType.SDL_MOUSEBUTTONDOWN:
+                case SDL_EventType.SDL_MOUSEBUTTONUP:
+                    uint rawButton = evnt.button.button;
+
+                    if (rawButton > 0 && rawButton <= (int)MouseButton.Count)
+                    {
+                        PressedButtons[(int)DriverButtonToMouseButton(rawButton)] = evnt.type == SDL_EventType.SDL_MOUSEBUTTONDOWN;
+
+                        CurrentPosition = new Vector2(evnt.button.x, evnt.button.y);
+                    }
+
+                    break;
+
+                // NOTE: On Linux using Wayland mouse motion events won't be received at all.
+                case SDL_EventType.SDL_MOUSEMOTION:
+                    CurrentPosition = new Vector2(evnt.motion.x, evnt.motion.y);
+                    _lastCursorMoveTime = Stopwatch.GetTimestamp();
+
+                    break;
+
+                case SDL_EventType.SDL_MOUSEWHEEL:
+                    Scroll = new Vector2(evnt.wheel.x, evnt.wheel.y);
+
+                    break;
             }
         }
 
@@ -100,4 +161,4 @@ namespace Ryujinx.Headless.SDL2
             _isDisposed = true;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Headless.SDL2/Vulkan/VulkanWindow.cs b/Ryujinx.Headless.SDL2/Vulkan/VulkanWindow.cs
index 18323339..172b7685 100644
--- a/Ryujinx.Headless.SDL2/Vulkan/VulkanWindow.cs
+++ b/Ryujinx.Headless.SDL2/Vulkan/VulkanWindow.cs
@@ -12,7 +12,13 @@ namespace Ryujinx.Headless.SDL2.Vulkan
     {
         private GraphicsDebugLevel _glLogLevel;
 
-        public VulkanWindow(InputManager inputManager, GraphicsDebugLevel glLogLevel, AspectRatio aspectRatio, bool enableMouse) : base(inputManager, glLogLevel, aspectRatio, enableMouse)
+        public VulkanWindow(
+            InputManager inputManager,
+            GraphicsDebugLevel glLogLevel,
+            AspectRatio aspectRatio,
+            bool enableMouse,
+            HideCursor hideCursor)
+            : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursor)
         {
             _glLogLevel = glLogLevel;
         }
@@ -95,4 +101,4 @@ namespace Ryujinx.Headless.SDL2.Vulkan
 
         protected override void SwapBuffers() { }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Headless.SDL2/WindowBase.cs b/Ryujinx.Headless.SDL2/WindowBase.cs
index 88b0d573..db6c8ec4 100644
--- a/Ryujinx.Headless.SDL2/WindowBase.cs
+++ b/Ryujinx.Headless.SDL2/WindowBase.cs
@@ -14,13 +14,16 @@ using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
 using System.Threading;
 using static SDL2.SDL;
 using Switch = Ryujinx.HLE.Switch;
 
 namespace Ryujinx.Headless.SDL2
 {
-    abstract class WindowBase : IHostUiHandler, IDisposable
+    abstract partial class WindowBase : IHostUiHandler, IDisposable
     {
         protected const int DefaultWidth = 1280;
         protected const int DefaultHeight = 720;
@@ -29,6 +32,10 @@ namespace Ryujinx.Headless.SDL2
 
         private static ConcurrentQueue<Action> MainThreadActions = new ConcurrentQueue<Action>();
 
+        [LibraryImport("SDL2")]
+        // TODO: Remove this as soon as SDL2-CS was updated to expose this method publicly
+        private static partial IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
+
         public static void QueueMainThreadAction(Action action)
         {
             MainThreadActions.Enqueue(action);
@@ -66,9 +73,14 @@ namespace Ryujinx.Headless.SDL2
         private AspectRatio _aspectRatio;
         private bool _enableMouse;
 
-        public WindowBase(InputManager inputManager, GraphicsDebugLevel glLogLevel, AspectRatio aspectRatio, bool enableMouse)
+        public WindowBase(
+            InputManager inputManager,
+            GraphicsDebugLevel glLogLevel,
+            AspectRatio aspectRatio,
+            bool enableMouse,
+            HideCursor hideCursor)
         {
-            MouseDriver = new SDL2MouseDriver();
+            MouseDriver = new SDL2MouseDriver(hideCursor);
             _inputManager = inputManager;
             _inputManager.SetMouseDriver(MouseDriver);
             NpadManager = _inputManager.CreateNpadManager();
@@ -103,6 +115,34 @@ namespace Ryujinx.Headless.SDL2
             TouchScreenManager.Initialize(device);
         }
 
+        private void SetWindowIcon()
+        {
+            Stream iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ryujinx.Headless.SDL2.Ryujinx.bmp");
+            byte[] iconBytes = new byte[iconStream!.Length];
+
+            if (iconStream.Read(iconBytes, 0, iconBytes.Length) != iconBytes.Length)
+            {
+                Logger.Error?.Print(LogClass.Application, "Failed to read icon to byte array.");
+                iconStream.Close();
+
+                return;
+            }
+
+            iconStream.Close();
+
+            unsafe
+            {
+                fixed (byte* iconPtr = iconBytes)
+                {
+                    IntPtr rwOpsStruct = SDL_RWFromConstMem((IntPtr)iconPtr, iconBytes.Length);
+                    IntPtr iconHandle = SDL_LoadBMP_RW(rwOpsStruct, 1);
+
+                    SDL_SetWindowIcon(WindowHandle, iconHandle);
+                    SDL_FreeSurface(iconHandle);
+                }
+            }
+        }
+
         private void InitializeWindow()
         {
             string titleNameSection = string.IsNullOrWhiteSpace(Device.Application.TitleName) ? string.Empty
@@ -127,6 +167,8 @@ namespace Ryujinx.Headless.SDL2
                 throw new Exception(errorMessage);
             }
 
+            SetWindowIcon();
+
             _windowId = SDL_GetWindowID(WindowHandle);
             SDL2Driver.Instance.RegisterWindow(_windowId, HandleWindowEvent);
 
@@ -146,9 +188,11 @@ namespace Ryujinx.Headless.SDL2
                         Renderer?.Window.SetSize(Width, Height);
                         MouseDriver.SetClientSize(Width, Height);
                         break;
+
                     case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE:
                         Exit();
                         break;
+
                     default:
                         break;
                 }
@@ -331,6 +375,9 @@ namespace Ryujinx.Headless.SDL2
 
             Device.Hid.DebugPad.Update();
 
+            // TODO: Replace this with MouseDriver.CheckIdle() when mouse motion events are received on every supported platform.
+            MouseDriver.UpdatePosition();
+
             return true;
         }
 
@@ -451,4 +498,4 @@ namespace Ryujinx.Headless.SDL2
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/Ryujinx.Input/HLE/NpadManager.cs b/Ryujinx.Input/HLE/NpadManager.cs
index 34e05687..5290ecbb 100644
--- a/Ryujinx.Input/HLE/NpadManager.cs
+++ b/Ryujinx.Input/HLE/NpadManager.cs
@@ -163,7 +163,7 @@ namespace Ryujinx.Input.HLE
             ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
         }
 
-        public void Update(float aspectRatio = 0)
+        public void Update(float aspectRatio = 1)
         {
             lock (_lock)
             {