diff --git a/Ryujinx.HLE/Loaders/Executable.cs b/Ryujinx.HLE/Loaders/Executable.cs
index 618ee241a..43193245a 100644
--- a/Ryujinx.HLE/Loaders/Executable.cs
+++ b/Ryujinx.HLE/Loaders/Executable.cs
@@ -2,6 +2,7 @@ using ChocolArm64.Memory;
 using Ryujinx.HLE.Loaders.Executables;
 using Ryujinx.HLE.OsHle;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Ryujinx.HLE.Loaders
 {
@@ -15,6 +16,8 @@ namespace Ryujinx.HLE.Loaders
 
         public string Name { get; private set; }
 
+        public string FilePath { get; private set; }
+
         private AMemory Memory;
 
         public long ImageBase { get; private set; }
@@ -26,8 +29,9 @@ namespace Ryujinx.HLE.Loaders
 
             m_SymbolTable = new Dictionary<long, string>();
 
-            Name = Exe.Name;
+            FilePath = Exe.FilePath;
 
+            Name = Path.GetFileNameWithoutExtension(FilePath.Replace(Homebrew.TemporaryNroSuffix, ""));
             this.Memory    = Memory;
             this.ImageBase = ImageBase;
             this.ImageEnd  = ImageBase;
diff --git a/Ryujinx.HLE/Loaders/Executables/IExecutable.cs b/Ryujinx.HLE/Loaders/Executables/IExecutable.cs
index 1e8e569a5..44bad6149 100644
--- a/Ryujinx.HLE/Loaders/Executables/IExecutable.cs
+++ b/Ryujinx.HLE/Loaders/Executables/IExecutable.cs
@@ -2,7 +2,7 @@ namespace Ryujinx.HLE.Loaders.Executables
 {
     public interface IExecutable
     {
-        string Name { get; }
+        string FilePath { get; }
 
         byte[] Text { get; }
         byte[] RO   { get; }
diff --git a/Ryujinx.HLE/Loaders/Executables/Nro.cs b/Ryujinx.HLE/Loaders/Executables/Nro.cs
index 9e2b7e907..0b5068d7b 100644
--- a/Ryujinx.HLE/Loaders/Executables/Nro.cs
+++ b/Ryujinx.HLE/Loaders/Executables/Nro.cs
@@ -4,7 +4,7 @@ namespace Ryujinx.HLE.Loaders.Executables
 {
     class Nro : IExecutable
     {
-        public string Name { get; private set; }
+        public string FilePath { get; private set; }
 
         public byte[] Text { get; private set; }
         public byte[] RO   { get; private set; }
@@ -16,9 +16,9 @@ namespace Ryujinx.HLE.Loaders.Executables
         public int DataOffset { get; private set; }
         public int BssSize    { get; private set; }
 
-        public Nro(Stream Input, string Name)
+        public Nro(Stream Input, string FilePath)
         {
-            this.Name = Name;
+            this.FilePath = FilePath;
 
             BinaryReader Reader = new BinaryReader(Input);
 
diff --git a/Ryujinx.HLE/Loaders/Executables/Nso.cs b/Ryujinx.HLE/Loaders/Executables/Nso.cs
index a5e1a361e..6a55c755a 100644
--- a/Ryujinx.HLE/Loaders/Executables/Nso.cs
+++ b/Ryujinx.HLE/Loaders/Executables/Nso.cs
@@ -6,7 +6,7 @@ namespace Ryujinx.HLE.Loaders.Executables
 {
     class Nso : IExecutable
     {
-        public string Name { get; private set; }
+        public string FilePath { get; private set; }
 
         public byte[] Text { get; private set; }
         public byte[] RO   { get; private set; }
@@ -31,7 +31,7 @@ namespace Ryujinx.HLE.Loaders.Executables
 
         public Nso(Stream Input, string Name)
         {
-            this.Name = Name;
+            this.FilePath = FilePath;
 
             BinaryReader Reader = new BinaryReader(Input);
 
diff --git a/Ryujinx.HLE/OsHle/Homebrew.cs b/Ryujinx.HLE/OsHle/Homebrew.cs
index 4266c8db4..778e52fe5 100644
--- a/Ryujinx.HLE/OsHle/Homebrew.cs
+++ b/Ryujinx.HLE/OsHle/Homebrew.cs
@@ -1,11 +1,14 @@
 using ChocolArm64.Memory;
+using System.Text;
 
 namespace Ryujinx.HLE.OsHle
 {
     static class Homebrew
     {
+        public const string TemporaryNroSuffix = ".ryu_tmp.nro";
+
         //http://switchbrew.org/index.php?title=Homebrew_ABI
-        public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle)
+        public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle, string SwitchPath)
         {
             Memory.Manager.Map(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
 
@@ -15,6 +18,11 @@ namespace Ryujinx.HLE.OsHle
             //NextLoadPath
             WriteConfigEntry(Memory, ref Position, 2, 0, Position + 0x200, Position + 0x400);
 
+            // Argv
+            long ArgvPosition = Position + 0xC00;
+            WriteConfigEntry(Memory, ref Position, 5, 0, 0, ArgvPosition);
+            Memory.WriteBytes(ArgvPosition, Encoding.ASCII.GetBytes(SwitchPath + "\0"));
+
             //AppletType
             WriteConfigEntry(Memory, ref Position, 7);
 
diff --git a/Ryujinx.HLE/OsHle/Horizon.cs b/Ryujinx.HLE/OsHle/Horizon.cs
index a5bf0616c..9d8a937ff 100644
--- a/Ryujinx.HLE/OsHle/Horizon.cs
+++ b/Ryujinx.HLE/OsHle/Horizon.cs
@@ -87,19 +87,36 @@ namespace Ryujinx.HLE.OsHle
             MainProcess.Run();
         }
 
-        public void LoadProgram(string FileName)
+        public void LoadProgram(string FilePath)
         {
-            bool IsNro = Path.GetExtension(FileName).ToLower() == ".nro";
+            bool IsNro = Path.GetExtension(FilePath).ToLower() == ".nro";
 
-            string Name = Path.GetFileNameWithoutExtension(FileName);
+            string Name = Path.GetFileNameWithoutExtension(FilePath);
+            string SwitchFilePath = Ns.VFs.SystemPathToSwitchPath(FilePath);
+
+            if (IsNro && (SwitchFilePath == null || !SwitchFilePath.StartsWith("sdmc:/")))
+            {
+                // TODO: avoid copying the file if we are already inside a sdmc directory
+                string SwitchPath = $"sdmc:/switch/{Name}{Homebrew.TemporaryNroSuffix}";
+                string TempPath = Ns.VFs.SwitchPathToSystemPath(SwitchPath);
+
+                string SwitchDir = Path.GetDirectoryName(TempPath);
+                if (!Directory.Exists(SwitchDir))
+                {
+                    Directory.CreateDirectory(SwitchDir);
+                }
+                File.Copy(FilePath, TempPath, true);
+
+                FilePath = TempPath;
+            }
 
             Process MainProcess = MakeProcess();
 
-            using (FileStream Input = new FileStream(FileName, FileMode.Open))
+            using (FileStream Input = new FileStream(FilePath, FileMode.Open))
             {
                 MainProcess.LoadProgram(IsNro
-                    ? (IExecutable)new Nro(Input, Name)
-                    : (IExecutable)new Nso(Input, Name));
+                    ? (IExecutable)new Nro(Input, FilePath)
+                    : (IExecutable)new Nso(Input, FilePath));
             }
 
             MainProcess.SetEmptyArgs();
diff --git a/Ryujinx.HLE/OsHle/Process.cs b/Ryujinx.HLE/OsHle/Process.cs
index 53e357ab9..be27dcc28 100644
--- a/Ryujinx.HLE/OsHle/Process.cs
+++ b/Ryujinx.HLE/OsHle/Process.cs
@@ -13,6 +13,7 @@ using Ryujinx.HLE.OsHle.Services.Nv;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.IO;
 using System.Text;
 
 namespace Ryujinx.HLE.OsHle
@@ -155,7 +156,9 @@ namespace Ryujinx.HLE.OsHle
             {
                 HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd);
 
-                Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle);
+                string SwitchPath = Ns.VFs.SystemPathToSwitchPath(Executables[0].FilePath);
+
+                Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle, SwitchPath);
 
                 MainThread.Thread.ThreadState.X0 = (ulong)HbAbiDataPosition;
                 MainThread.Thread.ThreadState.X1 = ulong.MaxValue;
@@ -400,6 +403,11 @@ namespace Ryujinx.HLE.OsHle
         {
             if (Disposing && !Disposed)
             {
+                if (NeedsHbAbi && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix))
+                {
+                    File.Delete(Executables[0].FilePath);
+                }
+
                 //If there is still some thread running, disposing the objects is not
                 //safe as the thread may try to access those resources. Instead, we set
                 //the flag to have the Process disposed when all threads finishes.
diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs
index 1946b187b..74c0564a9 100644
--- a/Ryujinx.HLE/Switch.cs
+++ b/Ryujinx.HLE/Switch.cs
@@ -81,8 +81,9 @@ namespace Ryujinx.HLE
             Gpu.Fifo.DispatchCalls();
         }
 
-        internal virtual void OnFinish(EventArgs e)
+        public virtual void OnFinish(EventArgs e)
         {
+            Os.Dispose();
             Finish?.Invoke(this, e);
         }
 
diff --git a/Ryujinx.HLE/VirtualFileSystem.cs b/Ryujinx.HLE/VirtualFileSystem.cs
index 8b71caa97..38df81f87 100644
--- a/Ryujinx.HLE/VirtualFileSystem.cs
+++ b/Ryujinx.HLE/VirtualFileSystem.cs
@@ -45,6 +45,35 @@ namespace Ryujinx.HLE
 
         public string GetGameSavesPath() => MakeDirAndGetFullPath(NandPath);
 
+        public string SwitchPathToSystemPath(string SwitchPath)
+        {
+            string[] Parts = SwitchPath.Split(":");
+            if (Parts.Length != 2)
+            {
+                return null;
+            }
+            return GetFullPath(MakeDirAndGetFullPath(Parts[0]), Parts[1]);
+        }
+
+        public string SystemPathToSwitchPath(string SystemPath)
+        {
+            string BaseSystemPath = GetBasePath() + "/";
+            if (SystemPath.StartsWith(BaseSystemPath))
+            {
+                string RawPath = SystemPath.Replace(BaseSystemPath, "");
+                int FirstSeparatorOffset = RawPath.IndexOf('/');
+                if (FirstSeparatorOffset == -1)
+                {
+                    return $"{RawPath}:/";
+                }
+
+                string BasePath = RawPath.Substring(0, FirstSeparatorOffset);
+                string FileName = RawPath.Substring(FirstSeparatorOffset + 1);
+                return $"{BasePath}:/{FileName}";
+            }
+            return null;
+        }
+
         private string MakeDirAndGetFullPath(string Dir)
         {
             string FullPath = Path.Combine(GetBasePath(), Dir);
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index 5cacc6228..879b9c20b 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -68,6 +68,7 @@ namespace Ryujinx
                 };
 
                 Screen.MainLoop();
+                Ns.OnFinish(EventArgs.Empty);
             }
 
             Environment.Exit(0);