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: