diff --git a/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack.meta b/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack.meta
index 7182dbd8..b3e69672 100644
--- a/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack.meta
+++ b/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 611bc182f939ea147a72b08613e2d2ba
+guid: 164952f99969ca942b4761b200d7e381
 folderAsset: yes
 DefaultImporter:
   externalObjects: {}
diff --git a/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack/Editors/AxibugNSPTools.cs b/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack/Editors/AxibugNSPTools.cs
index c9e192f0..e623c351 100644
--- a/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack/Editors/AxibugNSPTools.cs
+++ b/AxibugEmuOnline.Client/Assets/AxiProjectTools/AxiNSPack/Editors/AxibugNSPTools.cs
@@ -3,6 +3,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text.RegularExpressions;
 using UnityEditor;
@@ -82,7 +83,7 @@ namespace AxibugEmuOnline.Editors
             {
                 BuildReport report = BuildPipeline.BuildPlayer(options);
             }
-            catch(Exception ex)
+            catch (Exception ex)
             {
                 Debug.LogError($"[AxibugNSPTools] Unity Build NSP ����:{ex.ToString()}");
                 return;
@@ -147,13 +148,13 @@ namespace AxibugEmuOnline.Editors
             #region ������ʱĿ¼
             CleanDirectory(Path.Combine(nspParentDir, "repacker_extract"));
             CleanDirectory(Path.Combine(Path.GetTempPath(), "NCA"));
-            CleanDirectory(Path.Combine(WorkRoot, "hacpack_backup"));
+            CleanDirectory(Path.Combine(nspParentDir, "hacpack_backup"));
             #endregion
 
             EditorUtility.DisplayProgressBar("AxibugNSPTools", $"���NSP�ļ�", 0.2f);
             #region ���NSP�ļ�
             string extractPath = Path.Combine(nspParentDir, "repacker_extract");
-            ExecuteCommand($"{tools["authoringTool"]} extract -o \"{extractPath}\" \"{nspFilePath}\"");
+            ExecuteCommand($"{tools["authoringTool"]} extract -o \"{extractPath}\" \"{nspFilePath}\"", nspParentDir);
 
             string controlPath = null;
             string programPath = null;
@@ -167,34 +168,43 @@ namespace AxibugEmuOnline.Editors
 
             #region �ؽ�NCA/NSP
             string tmpPath = Path.Combine(Path.GetTempPath(), "NCA");
-            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NCA", 0.6f);
-            string programNCA = BuildProgramNCA(tmpPath, titleID, programPath);
-            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NCA", 0.7f);
-            string controlNCA = BuildControlNCA(tmpPath, titleID, controlPath);
-            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NCA", 0.8f);
-            BuildMetaNCA(tmpPath, titleID, programNCA, controlNCA);
+            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ� Program NCA", 0.3f);
+            string programNCA = BuildProgramNCA(tmpPath, titleID, programPath, nspParentDir);
+            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ� Control NCA", 0.4f);
+            string controlNCA = BuildControlNCA(tmpPath, titleID, controlPath, nspParentDir);
+            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ� Meta NCA", 0.5f);
+            BuildMetaNCA(tmpPath, titleID, programNCA, controlNCA, nspParentDir);
+            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NSP", 0.6f);
+            string outputNSP = BuildFinalNSP(nspFilePath, nspParentDir, tmpPath, titleID, nspParentDir);
             EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NSP", 0.9f);
-            string outputNSP = BuildFinalNSP(nspFilePath, nspParentDir, tmpPath, titleID);
-            EditorUtility.DisplayProgressBar("AxibugNSPTools", $"�ؽ�NSP", 1f);
             Debug.Log($"[AxibugNSPTools]Repacking completed: {outputNSP}");
-            EditorUtility.ClearProgressBar();
-            #endregion
+
+			#endregion
+
+			EditorUtility.DisplayProgressBar("AxibugNSPTools", $"������ʱĿ¼", 1);
+			#region ������ʱĿ¼
+			CleanDirectory(Path.Combine(nspParentDir, "repacker_extract"));
+			CleanDirectory(Path.Combine(Path.GetTempPath(), "NCA"));
+			CleanDirectory(Path.Combine(nspParentDir, "hacpack_backup"));
+			#endregion
+			System.Diagnostics.Process.Start("explorer", "/select,\"" + outputNSP.Trim() + "\"");
+			EditorUtility.ClearProgressBar();
         }
 
+
+
         #region ��������
         static string GetUserInput()
         {
             Console.Write("Enter the NSP filepath: ");
             return Console.ReadLine();
         }
-
         static string ExtractTitleID(string path)
         {
             var match = Regex.Match(path, @"0100[\dA-Fa-f]{12}");
             return match.Success ? match.Value : null;
         }
 
-
         static void CleanDirectory(string path)
         {
             if (Directory.Exists(path))
@@ -215,8 +225,9 @@ namespace AxibugEmuOnline.Editors
             }
         }
 
-        static string ExecuteCommand(string command)
+        static string ExecuteCommand(string command, string workdir)
         {
+            Debug.Log($"����cmd=>{command}");
             var process = new System.Diagnostics.Process()
             {
                 StartInfo = new System.Diagnostics.ProcessStartInfo
@@ -228,7 +239,8 @@ namespace AxibugEmuOnline.Editors
                     UseShellExecute = false,
                     CreateNoWindow = true,
                     StandardOutputEncoding = Encoding.UTF8,  // ��ȷָ������
-                    StandardErrorEncoding = Encoding.UTF8
+                    StandardErrorEncoding = Encoding.UTF8,
+                    WorkingDirectory = workdir
                 }
             };
 
@@ -275,36 +287,36 @@ namespace AxibugEmuOnline.Editors
         #endregion
 
         #region NCA�����߼�
-        static string BuildProgramNCA(string tmpPath, string titleID, string programDir)
+        static string BuildProgramNCA(string tmpPath, string titleID, string programDir, string workdir)
         {
             string args = $"-k \"{prodKeysPath}\" -o \"{tmpPath}\" --titleid {titleID} " +
                           $"--type nca --ncatype program --exefsdir \"{programDir}/fs0\" " +
                           $"--romfsdir \"{programDir}/fs1\" --logodir \"{programDir}/fs2\"";
 
-            string output = ExecuteCommand($"{tools["hacPack"]} {args}");
+            string output = ExecuteCommand($"{tools["hacPack"]} {args}", workdir);
             return ParseNCAOutput(output, "Program");
         }
 
-        static string BuildControlNCA(string tmpPath, string titleID, string controlDir)
+        static string BuildControlNCA(string tmpPath, string titleID, string controlDir, string workdir)
         {
             string args = $"-k \"{prodKeysPath}\" -o \"{tmpPath}\" --titleid {titleID} " +
                           $"--type nca --ncatype control --romfsdir \"{controlDir}/fs0\"";
 
-            string output = ExecuteCommand($"{tools["hacPack"]} {args}");
+            string output = ExecuteCommand($"{tools["hacPack"]} {args}", workdir);
 
             return ParseNCAOutput(output, "Control");
         }
 
-        static void BuildMetaNCA(string tmpPath, string titleID, string programNCA, string controlNCA)
+        static void BuildMetaNCA(string tmpPath, string titleID, string programNCA, string controlNCA, string workdir)
         {
             string args = $"-k \"{prodKeysPath}\" -o \"{tmpPath}\" --titleid {titleID} " +
                           $"--type nca --ncatype meta --titletype application " +
                           $"--programnca \"{programNCA}\" --controlnca \"{controlNCA}\"";
 
-            ExecuteCommand($"{tools["hacPack"]} {args}");
+            ExecuteCommand($"{tools["hacPack"]} {args}", workdir);
         }
 
-        static string BuildFinalNSP(string origPath, string parentDir, string tmpPath, string titleID)
+        static string BuildFinalNSP(string origPath, string parentDir, string tmpPath, string titleID, string workdir)
         {
             string outputPath = origPath.Replace(".nsp", "_repacked.nsp");
             if (File.Exists(outputPath)) File.Delete(outputPath);
@@ -312,7 +324,7 @@ namespace AxibugEmuOnline.Editors
             string args = $"-k \"{prodKeysPath}\" -o \"{parentDir}\" --titleid {titleID} " +
                           $"--type nsp --ncadir \"{tmpPath}\"";
 
-            ExecuteCommand($"{tools["hacPack"]} {args}");
+            ExecuteCommand($"{tools["hacPack"]} {args}", workdir);
             File.Move(Path.Combine(parentDir, $"{titleID}.nsp"), outputPath);
             return outputPath;
         }
@@ -321,7 +333,9 @@ namespace AxibugEmuOnline.Editors
         {
             var line = output.Split('\n')
                 .FirstOrDefault(l => l.Contains($"Created {type} NCA:"));
-            return line?.Split(':').Last().Trim();
+            //return line?.Split(':').Last().Trim();
+            return line?.Substring(line.IndexOf("NCA:") + "NCA:".Length).Trim();
+
         }
         #endregion
     }
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs
index 648bbd62..e39ca58e 100644
--- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNS.cs
@@ -18,11 +18,13 @@ public class AxiNS
 	public AxiNSUser user;
 	public AxiNSMount mount;
 	public AxiNSIO io;
+	public AxiNSWaitHandle wait;
 	AxiNS()
 	{
 		user = new AxiNSUser();
 		mount = new AxiNSMount();
 		io = new AxiNSIO();
+		wait = new AxiNSWaitHandle();
 	}
 
 	/// <summary>
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs
index 6431408c..9e3fe02e 100644
--- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSIO.cs
@@ -4,81 +4,94 @@ using nn.fs;
 
 public class AxiNSIO
 {
-    string save_name => AxiNS.instance.mount.SaveMountName;
-    public string save_path => $"{save_name}:/";
+	string save_name => AxiNS.instance.mount.SaveMountName;
+	public string save_path => $"{save_name}:/";
 #if UNITY_SWITCH
 	private FileHandle fileHandle = new nn.fs.FileHandle();
 #endif
-    /// <summary>
-    /// ���Path�Ƿ����
-    /// </summary>
-    /// <param name="filePath"></param>
-    /// <returns></returns>
-    public bool CheckPathExists(string filePath)
-    {
+	/// <summary>
+	/// ���Path�Ƿ����
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <returns></returns>
+	public bool CheckPathExists(string filePath)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
-        nn.fs.EntryType entryType = 0;
+		nn.fs.EntryType entryType = 0;
 		nn.Result result = nn.fs.FileSystem.GetEntryType(ref entryType, filePath);
 		//result.abortUnlessSuccess();
 		//����쳣������ı�Ť
 		return nn.fs.FileSystem.ResultPathAlreadyExists.Includes(result);
 #endif
-    }
-    /// <summary>
-    /// ���Path�Ƿ񲻴���
-    /// </summary>
-    /// <param name="filePath"></param>
-    /// <returns></returns>
-    public bool CheckPathNotFound(string filePath)
-    {
+	}
+	/// <summary>
+	/// ���Path�Ƿ񲻴���
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <returns></returns>
+	public bool CheckPathNotFound(string filePath)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
-        nn.fs.EntryType entryType = 0;
+		nn.fs.EntryType entryType = 0;
 		nn.Result result = nn.fs.FileSystem.GetEntryType(ref entryType, filePath);
 		//����쳣������ı�Ť
 		return nn.fs.FileSystem.ResultPathNotFound.Includes(result);
 #endif
-    }
-    /// <summary>
-    /// ����Ŀ¼��Ŀ¼����Ҳ�᷵��true
-    /// </summary>
-    /// <param name="filePath"></param>
-    /// <returns></returns>
-    public bool CreateDir(string filePath)
-    {
+	}
+	/// <summary>
+	/// ����Ŀ¼��Ŀ¼����Ҳ�᷵��true
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <returns></returns>
+	public bool CreateDir(string filePath)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
-        // ʹ�÷�װ�������ʹ�����Ŀ¼
-        if (!EnsureParentDirectory(filePath, true))
-        {
-            UnityEngine.Debug.LogError($"�޷�ȷ����Ŀ¼���ļ�д��ȡ��: {filePath}");
-            return false;
-        }
+		// ʹ�÷�װ�������ʹ�����Ŀ¼
+		if (!EnsureParentDirectory(filePath, true))
+		{
+			UnityEngine.Debug.LogError($"�޷�ȷ����Ŀ¼���ļ�д��ȡ��: {filePath}");
+			return false;
+		}
 		return true;
 #endif
-    }
-    /// <summary>
-    /// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
-    /// </summary>
-    /// <param name="filePath"></param>
-    /// <param name="bw"></param>
-    /// <returns></returns>
-    public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms)
-    {
-        return FileToSaveWithCreate(filePath, ms.ToArray());
-    }
-    /// <summary>
-    /// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
-    /// </summary>
-    /// <param name="filePath"></param>
-    /// <param name="data"></param>
-    /// <returns></returns>
-    public bool FileToSaveWithCreate(string filePath, byte[] data)
-    {
+	}
+
+	/// <summary>
+	/// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <param name="bw"></param>
+	/// <returns></returns>
+	public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms)
+	{
+		return FileToSaveWithCreate(filePath, ms.ToArray());
+	}
+	/// <summary>
+	/// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <param name="data"></param>
+	/// <returns></returns>
+	public AxiNSWait_FileToSaveByMSWithCreate FileToSaveWithCreateAsync(string filePath, System.IO.MemoryStream ms)
+	{
+		var wait = new AxiNSWait_FileToSaveByMSWithCreate(filePath, ms);
+		AxiNS.instance.wait.AddWait(wait);
+		return wait;
+	}
+	/// <summary>
+	/// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <param name="data"></param>
+	/// <returns></returns>
+	public bool FileToSaveWithCreate(string filePath, byte[] data)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
@@ -182,21 +195,33 @@ public class AxiNSIO
 
 		return true;
 #endif
-    }
-    public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms)
-    {
-        if (LoadSwitchDataFile(filename, out byte[] outputData))
-        {
-            using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms))
-            {
-                writer.Write(outputData);
-            }
-            return true;
-        }
-        return false;
-    }
-    public bool LoadSwitchDataFile(string filename, out byte[] outputData)
-    {
+	}
+	/// <summary>
+	/// ���沢�����ļ������Ŀ¼�����ڻ����Զ�����Ŀ¼��
+	/// </summary>
+	/// <param name="filePath"></param>
+	/// <param name="data"></param>
+	/// <returns></returns>
+	public AxiNSWait_FileToSaveWithCreate FileToSaveWithCreateAsync(string filePath, byte[] data)
+	{
+		var wait = new AxiNSWait_FileToSaveWithCreate(filePath, data);
+		AxiNS.instance.wait.AddWait(wait);
+		return wait;
+	}
+	public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms)
+	{
+		if (LoadSwitchDataFile(filename, out byte[] outputData))
+		{
+			using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms))
+			{
+				writer.Write(outputData);
+			}
+			return true;
+		}
+		return false;
+	}
+	public bool LoadSwitchDataFile(string filename, out byte[] outputData)
+	{
 #if !UNITY_SWITCH
         outputData = null;
         return false;
@@ -247,25 +272,218 @@ public class AxiNSIO
 		outputData = loadedData;
 		return true;
 #endif
-    }
-    public bool DeletePathFile(string filename)
-    {
+	}
+	public AxiNSWait_LoadSwitchDataFile LoadSwitchDataFileAsync(string filename)
+	{
+		var wait = new AxiNSWait_LoadSwitchDataFile(filename);
+		AxiNS.instance.wait.AddWait(wait);
+		return wait;
+	}
+	public bool DeletePathFile(string filename)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
-		//TODO
+
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // This next line prevents the user from quitting the game while saving. 
+        // This is required for Nintendo Switch Guideline 0080
+        UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
 #endif
-    }
-    public bool DeletePathDir(string filename)
-    {
+
+		if (CheckPathNotFound(filename))
+			return false;
+		nn.Result result;
+		result = nn.fs.File.Delete(filename);
+		if (result.IsSuccess() == false)
+		{
+			UnityEngine.Debug.LogError($"nn.fs.File.Delete ʧ�� {filename} : result=>{result.GetErrorInfo()}");
+			return false;
+		}
+		result = nn.fs.FileSystem.Commit(save_name);
+		if (!result.IsSuccess())
+		{
+			UnityEngine.Debug.LogError($"FileSystem.Commit({save_name}) ʧ��: " + result.GetErrorInfo());
+			return false;
+		}
+		return true;
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // End preventing the user from quitting the game while saving.
+        UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
+#endif
+
+#endif
+	}
+	public AxiNSWait_DeletePathFile DeletePathFileAsync(string filename)
+	{
+		var wait = new AxiNSWait_DeletePathFile(filename);
+		AxiNS.instance.wait.AddWait(wait);
+		return wait;
+	}
+	public bool DeletePathDir(string filename)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
-		//TODO
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // This next line prevents the user from quitting the game while saving. 
+        // This is required for Nintendo Switch Guideline 0080
+        UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
 #endif
-    }
-    bool EnsureParentDirectory(string filePath, bool bAutoCreateDir = true)
-    {
+
+		if (CheckPathNotFound(filename))
+			return false;
+		nn.Result result;
+		result = nn.fs.Directory.Delete(filename);
+		if (result.IsSuccess() == false)
+		{
+			UnityEngine.Debug.LogError($"nn.fs.File.Delete ʧ�� {filename} : result=>{result.GetErrorInfo()}");
+			return false;
+		}
+		result = nn.fs.FileSystem.Commit(save_name);
+		if (!result.IsSuccess())
+		{
+			UnityEngine.Debug.LogError($"FileSystem.Commit({save_name}) ʧ��: " + result.GetErrorInfo());
+			return false;
+		}
+		return true;
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // End preventing the user from quitting the game while saving.
+        UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
+#endif
+#endif
+	}
+	public AxiNSWait_DeletePathDir DeletePathDirAsync(string filename)
+	{
+		var wait = new AxiNSWait_DeletePathDir(filename);
+		AxiNS.instance.wait.AddWait(wait);
+		return wait;
+	}
+
+	/// <summary>
+	/// �ݹ�ɾ��Ŀ¼
+	/// </summary>
+	/// <param name="filename"></param>
+	/// <returns></returns>
+	public bool DeleteRecursivelyPathDir(string filename)
+	{
+#if !UNITY_SWITCH
+        return false;
+#else
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // This next line prevents the user from quitting the game while saving. 
+        // This is required for Nintendo Switch Guideline 0080
+        UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
+#endif
+
+		if (CheckPathNotFound(filename))
+			return false;
+		nn.Result result;
+		result = nn.fs.Directory.DeleteRecursively(filename);
+		if (result.IsSuccess() == false)
+		{
+			UnityEngine.Debug.LogError($"nn.fs.File.DeleteRecursively ʧ�� {filename} : result=>{result.GetErrorInfo()}");
+			return false;
+		}
+		result = nn.fs.FileSystem.Commit(save_name);
+		if (!result.IsSuccess())
+		{
+			UnityEngine.Debug.LogError($"FileSystem.Commit({save_name}) ʧ��: " + result.GetErrorInfo());
+			return false;
+		}
+		return true;
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // End preventing the user from quitting the game while saving.
+        UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
+#endif
+#endif
+	}
+
+	/// <summary>
+	/// �ݹ�ɾ�����
+	/// </summary>
+	/// <param name="filename"></param>
+	/// <returns></returns>
+	public bool CleanRecursivelyPathDir(string filename)
+	{
+#if !UNITY_SWITCH
+        return false;
+#else
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // This next line prevents the user from quitting the game while saving. 
+        // This is required for Nintendo Switch Guideline 0080
+        UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
+#endif
+
+		if (CheckPathNotFound(filename))
+			return false;
+		nn.Result result;
+		result = nn.fs.Directory.CleanRecursively(filename);
+		if (result.IsSuccess() == false)
+		{
+			UnityEngine.Debug.LogError($"nn.fs.File.DeleteRecursively ʧ�� {filename} : result=>{result.GetErrorInfo()}");
+			return false;
+		}
+		result = nn.fs.FileSystem.Commit(save_name);
+		if (!result.IsSuccess())
+		{
+			UnityEngine.Debug.LogError($"FileSystem.Commit({save_name}) ʧ��: " + result.GetErrorInfo());
+			return false;
+		}
+		return true;
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // End preventing the user from quitting the game while saving.
+        UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
+#endif
+#endif
+	}
+
+	public bool RenameDir(string oldpath, string newpath)
+	{
+#if !UNITY_SWITCH
+        return false;
+#else
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // This next line prevents the user from quitting the game while saving. 
+        // This is required for Nintendo Switch Guideline 0080
+        UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
+#endif
+
+		if (CheckPathNotFound(oldpath))
+			return false;
+
+		nn.Result result;
+		result = nn.fs.Directory.Rename(oldpath, newpath);
+		if (result.IsSuccess() == false)
+		{
+			UnityEngine.Debug.LogError($"nn.fs.File.Rename ʧ�� {oldpath} to {newpath} : result=>{result.GetErrorInfo()}");
+			return false;
+		}
+		result = nn.fs.FileSystem.Commit(save_name);
+		if (!result.IsSuccess())
+		{
+			UnityEngine.Debug.LogError($"FileSystem.Commit({save_name}) ʧ��: " + result.GetErrorInfo());
+			return false;
+		}
+		return true;
+
+#if UNITY_SWITCH && !UNITY_EDITOR
+        // End preventing the user from quitting the game while saving.
+        UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
+#endif
+#endif
+	}
+	bool EnsureParentDirectory(string filePath, bool bAutoCreateDir = true)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
@@ -339,16 +557,16 @@ public class AxiNSIO
 		// ·����������Ŀ¼
 		UnityEngine.Debug.Log($"��Ŀ¼ {fullDirectoryPath} �Ѵ�������Ч");
 		return true;
-		
+
 #endif
-    }
-    /// <summary>
-    /// ���ָ�����ص��Ƿ�ɷ���
-    /// </summary>
-    /// <param name="pathPrefix">·��ǰ׺������ "save:/" �� "sd:/"</param>
-    /// <returns>���ص��Ƿ�ɷ���</returns>
-    bool IsMountPointAccessible(string pathPrefix)
-    {
+	}
+	/// <summary>
+	/// ���ָ�����ص��Ƿ�ɷ���
+	/// </summary>
+	/// <param name="pathPrefix">·��ǰ׺������ "save:/" �� "sd:/"</param>
+	/// <returns>���ص��Ƿ�ɷ���</returns>
+	bool IsMountPointAccessible(string pathPrefix)
+	{
 #if !UNITY_SWITCH
         return false;
 #else
@@ -386,5 +604,5 @@ public class AxiNSIO
 			return true; // �������ص������ʵ������ʵ��
 		}
 #endif
-    }
+	}
 }
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs
index 0d1bae7c..8b32a30b 100644
--- a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMount.cs
@@ -1,14 +1,17 @@
 #if UNITY_SWITCH
 using nn.account;
+using static AxiHttp;
 #endif
 public class AxiNSMount
 {
     static bool bInMount = false;
     internal static string m_SaveMountName;
-    static bool bInMountForDebug = false;
-    internal static string m_SaveMountForDebugName;
+    static bool bInSdCardMount = false;
+    internal static string m_SdCardMountName;
+	static bool bInSdCardDebugMount = false;
+	internal static string m_SdCardDebugMountName;
 
-    public bool SaveIsMount => bInMount;
+	public bool SaveIsMount => bInMount;
     public string SaveMountName
     {
         get
@@ -47,14 +50,14 @@ public class AxiNSMount
 		bInMount = true;
 		return true;
 	}
-    #endif
+#endif
 
-    public bool MountSDForDebug(string mountName = "sd")
+	public bool MountSDForDebug(string mountName = "dbgsd")
     {
 #if !UNITY_SWITCH
         return false;
 #else
-        if (bInMountForDebug)
+        if (bInSdCardDebugMount)
             return true;
         nn.Result result;
         result = nn.fs.SdCard.MountForDebug(mountName);
@@ -65,35 +68,31 @@ public class AxiNSMount
             return false;
         }
         UnityEngine.Debug.Log($"nn_fs_MountSdCardForDebug->����{mountName}:/ �ɹ� ");
-        m_SaveMountForDebugName = mountName;
-        bInMountForDebug = true;
+		m_SdCardDebugMountName = mountName;
+		bInSdCardDebugMount = true;
         return true;
 #endif
     }
-
     public bool MountSD(string mountName = "sd")
     {
 #if !UNITY_SWITCH
         return false;
 #else
-        if (bInMountForDebug)
+        if (bInSdCardMount)
             return true;
         nn.Result result;
-        result = nn.fs.SdCard.Mount(mountName);
-        //result.abortUnlessSuccess();
+        result = AxiNSSDCard.Mount(mountName);
         if (!result.IsSuccess())
         {
             UnityEngine.Debug.LogError($"nn_fs_MountSdCard->����{mountName}:/ ʧ��: " + result.ToString());
             return false;
         }
         UnityEngine.Debug.Log($"nn_fs_MountSdCard->����{mountName}:/ �ɹ� ");
-        m_SaveMountForDebugName = mountName;
-        bInMountForDebug = true;
+        m_SdCardMountName = mountName;
+        bInSdCardMount = true;
         return true;
 #endif
     }
-
-
     public void UnmountSave()
     {
 #if UNITY_SWITCH
@@ -107,18 +106,30 @@ public class AxiNSMount
         bInMount = false;
 #endif
     }
-
-    public void UnmountSaveForDebug()
+    public void UnmountSDCardForDebug()
     {
 #if UNITY_SWITCH
-        if (!bInMountForDebug)
+        if (!bInSdCardDebugMount)
         {
-            UnityEngine.Debug.LogError($"{m_SaveMountForDebugName}:/ û�б����أ�����ж��");
+            UnityEngine.Debug.LogError($"{m_SdCardDebugMountName}:/ û�б����أ�����ж��");
             return;
         }
-        nn.fs.FileSystem.Unmount(m_SaveMountForDebugName);
-        UnityEngine.Debug.LogError($"UnmountSaveForDebufa->���{m_SaveMountForDebugName}:/ ");
-        bInMountForDebug = false;
+        nn.fs.FileSystem.Unmount(m_SdCardDebugMountName);
+        UnityEngine.Debug.LogError($"UnmountSDCardForDebug->���{m_SdCardDebugMountName}:/ ");
+		bInSdCardDebugMount = false;
 #endif
-    }
+	}
+	public void UnmountSDCard()
+	{
+#if UNITY_SWITCH
+		if (!bInSdCardMount)
+		{
+			UnityEngine.Debug.LogError($"{m_SdCardMountName}:/ û�б����أ�����ж��");
+			return;
+		}
+		nn.fs.FileSystem.Unmount(m_SdCardMountName);
+		UnityEngine.Debug.LogError($"UnmountSDCard->���{m_SdCardMountName}:/ ");
+		bInSdCardMount = false;
+#endif
+	}
 }
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs
new file mode 100644
index 00000000..f1fe28e6
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs
@@ -0,0 +1,23 @@
+#if UNITY_SWITCH
+using nn.account;
+#endif
+public class AxiNSSDCard
+{
+#if UNITY_SWITCH
+
+#if DEVELOPMENT_BUILD || NN_FS_SD_CARD_FOR_DEBUG_ENABLE
+        [DllImport(Nn.DllName,
+            CallingConvention = CallingConvention.Cdecl,
+            EntryPoint = "nn_fs_MountSdCard")]
+        public static extern nn.Result Mount(string name);
+#else
+
+	public static nn.Result Mount(string name)
+	{
+		return new nn.Result();
+	}
+#endif
+
+
+#endif
+}
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs.meta
new file mode 100644
index 00000000..1b9591a5
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSSDCard.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 21fa04ba4da10d74aafd65dd138478b7
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta
new file mode 100644
index 00000000..99d60f26
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e28ed9d2fb16c7f42b28cafb6a2ce0ac
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs
new file mode 100644
index 00000000..009b93e8
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs
@@ -0,0 +1,119 @@
+public abstract class AxiNSWaitBase : UnityEngine.CustomYieldInstruction
+{
+	protected bool IsDone;
+	public abstract void Invoke();
+	public string errmsg = string.Empty;
+	public AxiNSWaitBase()
+	{
+		this.IsDone = false;
+	}
+
+	public void SetDone()
+	{
+		this.IsDone = true;
+	}
+
+	~AxiNSWaitBase()
+	{
+	}
+
+	public override bool keepWaiting
+	{
+		get { return !IsDone; }
+	}
+}
+
+
+
+public struct S_NSWAIT_PathWithBytes
+{
+	public string filePath;
+	public byte[] data;
+}
+
+public class AxiNSWait_FileToSaveWithCreate : AxiNSWaitBase
+{
+	S_NSWAIT_PathWithBytes req;
+	public bool result;
+	public AxiNSWait_FileToSaveWithCreate(string filePath, byte[] data)
+	{
+		req = new S_NSWAIT_PathWithBytes() { filePath = filePath, data = data };
+	}
+
+	public override void Invoke()
+	{
+		result = AxiNS.instance.io.FileToSaveWithCreate(req.filePath, req.data);
+	}
+}
+
+public struct S_NSWAIT_PathWithMS
+{
+	public string filePath;
+	public System.IO.MemoryStream ms;
+}
+
+public class AxiNSWait_FileToSaveByMSWithCreate : AxiNSWaitBase
+{
+	S_NSWAIT_PathWithMS req;
+	public bool result;
+	public AxiNSWait_FileToSaveByMSWithCreate(string filePath, System.IO.MemoryStream ms)
+	{
+		req = new S_NSWAIT_PathWithMS() { filePath = filePath, ms = ms };
+	}
+
+	public override void Invoke()
+	{
+		result = AxiNS.instance.io.FileToSaveWithCreate(req.filePath, req.ms);
+	}
+}
+
+public struct S_NSWAIT_Path
+{
+	public string filePath;
+}
+
+public class AxiNSWait_LoadSwitchDataFile : AxiNSWaitBase
+{
+	S_NSWAIT_Path req;
+	public bool result;
+	public byte[] outputData;
+	public AxiNSWait_LoadSwitchDataFile(string filePath)
+	{
+		req = new S_NSWAIT_Path() { filePath = filePath};
+	}
+
+	public override void Invoke()
+	{
+		result = AxiNS.instance.io.LoadSwitchDataFile(req.filePath, out outputData);
+	}
+}
+
+public class AxiNSWait_DeletePathFile : AxiNSWaitBase
+{
+	S_NSWAIT_Path req;
+	public bool result;
+	public AxiNSWait_DeletePathFile(string filePath)
+	{
+		req = new S_NSWAIT_Path() { filePath = filePath };
+	}
+
+	public override void Invoke()
+	{
+		result = AxiNS.instance.io.DeletePathFile(req.filePath);
+	}
+}
+
+public class AxiNSWait_DeletePathDir : AxiNSWaitBase
+{
+	S_NSWAIT_Path req;
+	public bool result;
+	public AxiNSWait_DeletePathDir(string filePath)
+	{
+		req = new S_NSWAIT_Path() { filePath = filePath };
+	}
+
+	public override void Invoke()
+	{
+		result = AxiNS.instance.io.DeletePathDir(req.filePath);
+	}
+}
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta
new file mode 100644
index 00000000..ff72499f
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.Data.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 46a1a776d2f9dba49b9641d8e0976861
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs
new file mode 100644
index 00000000..a8ba35f0
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+public class AxiNSWaitHandle
+{
+	static AutoResetEvent autoEvent = new AutoResetEvent(false);
+	static Thread waitThread = new Thread(Loop);
+	static bool bSingleInit = false;
+	static Queue<AxiNSWaitBase> m_QueueReady = new Queue<AxiNSWaitBase>();
+	static Queue<AxiNSWaitBase> m_QueueWork = new Queue<AxiNSWaitBase>();
+	public void AddWait(AxiNSWaitBase wait)
+	{
+		InitInternalThread();
+		lock (m_QueueReady)
+		{
+			m_QueueReady.Enqueue(wait);
+		}
+		autoEvent.Set();
+	}
+
+	static void InitInternalThread()
+	{
+		if (bSingleInit) return;
+		waitThread.Start();
+		bSingleInit = true;
+	}
+
+	static void Loop()
+	{
+		while (autoEvent.WaitOne())
+		{
+			lock (m_QueueReady)
+			{
+				while (m_QueueReady.Count > 0)
+				{
+					m_QueueWork.Enqueue(m_QueueReady.Dequeue());
+				}
+			}
+			while (m_QueueWork.Count > 0)
+			{
+				AxiNSWaitBase wait = m_QueueWork.Dequeue();
+				try
+				{
+					wait.Invoke();
+				}
+				catch (Exception ex)
+				{
+					wait.errmsg = ex.ToString();
+					UnityEngine.Debug.Log(ex.ToString());
+				}
+				wait.SetDone();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta
new file mode 100644
index 00000000..46fa015c
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSWaitHandle/AxiNSWaitHandle.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5e36180ba1c4a8f4db3ceed533a43999
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: