using AxibugEmuOnline.Client.ClientCore; using ICSharpCode.SharpZipLib.Zip; using System; using System.Collections; using System.IO; using UnityEngine.Networking; namespace AxibugEmuOnline.Client { public class RomFile { private HttpAPI.Resp_RomInfo webData; private bool hasLocalFile; private EnumPlatform platform; private UnityWebRequest downloadRequest; public bool IsUserRom { get; private set; } /// 指示该Rom文件的存放路径 public string LocalFilePath => IsUserRom ? $"{App.PersistentDataPath}/UserRoms/{platform}/{FileName}" : $"{App.PersistentDataPath}/RemoteRoms/{platform}/{FileName}"; /// 指示该Rom文件是否已下载完毕 public bool RomReady => hasLocalFile; /// 指示是否正在下载Rom文件 public bool IsDownloading => downloadRequest != null && downloadRequest.result == UnityWebRequest.Result.InProgress; public float Progress => IsDownloading ? downloadRequest.downloadProgress : 0; public EnumPlatform Platform => platform; /// 指示该Rom信息是否已填充 public bool InfoReady => webData != null; /// 唯一标识 public int ID => webData != null ? webData.id : -1; /// 别名 public string Alias => IsUserRom ? Path.GetFileNameWithoutExtension(FileName) : webData.romName; /// 描述 public string Descript => IsUserRom ? string.Empty : webData.desc; /// 游戏类型 public string GameTypeDes => IsUserRom ? string.Empty : webData.gType; /// 小图URL public string ImageURL => IsUserRom ? string.Empty : webData.imgUrl; /// 文件名 public string FileName { get; private set; } /// 在查询结果中的索引 public int Index { get; private set; } /// 在查询结果中的所在页 public int Page { get; private set; } public string Hash => webData != null ? webData.hash : string.Empty; public event Action OnDownloadOver; public event Action OnInfoFilled; public RomFile(EnumPlatform platform, int index, int insidePage) { this.platform = platform; Index = index; Page = insidePage; } public void BeginDownload() { if (RomReady) return; if (IsDownloading) return; App.StartCoroutine(DownloadRemoteRom((bytes) => { if (bytes != null) { var directPath = Path.GetDirectoryName(LocalFilePath); Directory.CreateDirectory(directPath); File.WriteAllBytes(LocalFilePath, bytes); hasLocalFile = true; } OnDownloadOver?.Invoke(this); })); } public byte[] GetRomFileData() { if (!IsUserRom && webData == null) throw new Exception("Not Valid Rom"); if (!RomReady) throw new Exception("Rom File Not Downloaded"); var bytes = File.ReadAllBytes(LocalFilePath); if (Path.GetExtension(LocalFilePath).ToLower() == ".zip") { var zip = new ZipInputStream(new MemoryStream(bytes)); while (zip.GetNextEntry() is ZipEntry entry) { if (!entry.Name.ToLower().EndsWith(".nes")) continue; var buffer = new byte[1024]; MemoryStream output = new MemoryStream(); while (true) { var size = zip.Read(buffer, 0, buffer.Length); if (size == 0) break; else output.Write(buffer, 0, size); } output.Flush(); return output.ToArray(); } } else { return bytes; } throw new Exception("Not Valid Rom Data"); } private IEnumerator DownloadRemoteRom(Action callback) { downloadRequest = UnityWebRequest.Get($"{App.httpAPI.WebHost}/{webData.url}"); yield return downloadRequest.SendWebRequest(); var request = downloadRequest; downloadRequest = null; if (request.result != UnityWebRequest.Result.Success) { callback(null); } else { callback(request.downloadHandler.data); } } public void SetWebData(HttpAPI.Resp_RomInfo resp_RomInfo) { webData = resp_RomInfo; FileName = Path.GetFileName(webData.url); FileName = System.Net.WebUtility.UrlDecode(FileName); if (File.Exists(LocalFilePath)) { var fileBytes = File.ReadAllBytes(LocalFilePath); var localHash = RomLib.CalcHash(fileBytes); hasLocalFile = localHash == webData.hash; if (!hasLocalFile) File.Delete(LocalFilePath); } else { hasLocalFile = false; } OnInfoFilled?.Invoke(); } private RomFile() { } public static RomFile CreateExistRom(EnumPlatform platform, string fileName) { var res = new RomFile(); res.IsUserRom = true; res.FileName = fileName; res.hasLocalFile = File.Exists(res.LocalFilePath); return res; } } }