public static Conclusion Reboot(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus(Resources.Rebooting); try { hakchi.Shell.ExecuteSimple("sync; umount -ar; reboot -f", 100); } catch { } return(Conclusion.Success); }
public static Conclusion Shutdown(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus(Resources.PoweringOff); try { hakchi.Shell.ExecuteSimple("sync; umount -ar; poweroff -f", 100); } catch { } return(Conclusion.Success); }
public static Conclusion CheckExternalStorage(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus("hakchi checkExtStorage"); using (var eventStream = new EventStream()) using (var splitStream = new SplitterStream()) { eventStream.OnData += (byte[] buffer) => { tasker.SetStatus(Encoding.UTF8.GetString(buffer)); }; splitStream.AddStreams(Program.debugStreams); splitStream.AddStreams(eventStream); hakchi.Shell.Execute("hakchi checkExtStorage", null, splitStream, splitStream); return(Conclusion.Success); } return(Conclusion.Error); }
public static Conclusion UnmountBase(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus("hakchi umount_base"); return(hakchi.Shell.Execute("hakchi umount_base") == 0 ? Conclusion.Success : Conclusion.Error); }
private Tasker.Conclusion InstallSDPart2(Tasker tasker, Object sync) { var splitStream = new SplitterStream(Program.debugStreams); tasker.SetStatus(Resources.MountingSDCard); if (DialogOptions.MakeBootable) { hakchi.Shell.Execute("sh /tmp/init mount", null, splitStream, splitStream, 0, true); } else { hakchi.Shell.Execute("mkdir -p /data/", null, null, null, 0, true); hakchi.Shell.Execute("mount /dev/mmcblk0p1 /data/", null, null, null, 0, true); } hakchi.Shell.Execute("mkdir -p /data/hakchi/games/", null, null, null, 0, true); if (!DialogOptions.MakeBootable && DialogOptions.StoreSaves) { hakchi.Shell.Execute("mkdir -p /data/hakchi/saves/", null, null, null, 0, true); } if (DialogOptions.CopyType != SDFormatResult.CopyTypes.None) { using (EventStream copyDataProgress = new EventStream()) { var userDataDeviceName = Sunxi.NandInfo.GetNandInfo().GetDataPartition().Device; splitStream.AddStreams(copyDataProgress); copyDataProgress.OnData += (byte[] buffer) => tasker.SetStatus(Encoding.ASCII.GetString(buffer)); tasker.SetStatus(Resources.CopyingNandDataToSDCard); hakchi.Shell.Execute($"mkdir -p /{userDataDeviceName} && mount /dev/{userDataDeviceName} /{userDataDeviceName}", null, null, null, 0, true); if (DialogOptions.CopyType == SDFormatResult.CopyTypes.Everything) { hakchi.Shell.Execute($"rsync -avc /{userDataDeviceName}/ /data/", null, splitStream, splitStream, 0, true); } else { var nandPath = DialogOptions.MakeBootable ? $"/{userDataDeviceName}/clover" : $"/{userDataDeviceName}/clover/profiles/0"; var dataPath = DialogOptions.MakeBootable ? "/data/clover" : "/data/hakchi/saves"; if (hakchi.Shell.Execute($"[ -d {nandPath} ]") == 0) { hakchi.Shell.Execute($"rsync -avc {nandPath} {dataPath}", null, splitStream, splitStream, 0, true); } } hakchi.Shell.Execute($"umount /{userDataDeviceName}/ && rmdir /{userDataDeviceName}/", null, null, null, 0, true); splitStream.RemoveStream(copyDataProgress); copyDataProgress.Dispose(); } } if (DialogOptions.MakeBootable) { tasker.SetStatus(Resources.CopyingHakchiToSDCard); hakchi.Shell.Execute("sh /tmp/init copy", null, splitStream, splitStream, 0, true); tasker.SetStatus(Resources.UnmountingSDCard); hakchi.Shell.Execute("sh /tmp/init unmount", null, splitStream, splitStream, 0, true); } return(Tasker.Conclusion.Success); }
private Tasker.Conclusion InstallSDPart1(Tasker tasker, Object sync) { tasker.SetStatus(Resources.InstallingHakchi); if (hakchi.Shell.Execute("[ -b /dev/mmcblk0 ]") != 0) { throw new Exception(Resources.NoSDCard); } var splitStream = new SplitterStream(Program.debugStreams); hakchi.Shell.Execute("mkdir -p /squashtools /tmp", null, null, null, 0, true); //hakchi.Shell.Execute("umount /newroot"); //hakchi.Shell.Execute("losetup -d /dev/loop2"); //hakchi.Shell.Execute("umount /firmware"); //hakchi.Shell.Execute("mkdir -p /sd-temp/", null, null, null, 0, true); //tasker.SetStatus(Resources.ExtractingHakchiToTemporaryFolder); //hakchi.Shell.Execute("tar -xzvf - -C /sd-temp/", hakchi.Hmod.GetHmodStream(), null, null, 0, true); // 16 //tasker.SetProgress(16, 161); tasker.SetStatus(Resources.ClearingTheFirst32MBOfSDCard); hakchi.Shell.Execute("dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=32", null, null, null, 0, true); // 32 tasker.SetProgress(48, 161); if (DialogOptions.MakeBootable) { tasker.SetStatus(Resources.AddingHakchiMBR); hakchi.Shell.Execute("printf \"hakchi\\n%s\\n\" \"$(cat \"/sd-temp/var/version\")\" | dd \"of=/dev/mmcblk0\"", null, null, null, 0, true); tasker.SetProgress(49, 161); tasker.SetStatus(Resources.WritingFATFilesystem); hakchi.Shell.Execute("gunzip -c /sd-temp/sd/data.vfat.gz | dd of=/dev/mmcblk0 bs=1M seek=32", null, null, null, 0, true); // 96 tasker.SetProgress(145, 161); tasker.SetStatus(Resources.WritingBoot0); hakchi.Shell.Execute("dd if=/sd-temp/sd/boot0.bin of=/dev/mmcblk0 bs=1K seek=8", null, null, null, 0, true); // 1 tasker.SetProgress(146, 161); tasker.SetStatus(Resources.WritingUboot); hakchi.Shell.Execute("dd if=/sd-temp/sd/uboot.bin of=/dev/mmcblk0 bs=1K seek=19096", null, null, null, 0, true); // 1 tasker.SetProgress(147, 161); tasker.SetStatus(Resources.WritingKernel); hakchi.Shell.Execute("dd if=/sd-temp/sd/kernel.img of=/dev/mmcblk0 bs=1K seek=20480", null, null, null, 0, true); // 4 tasker.SetProgress(151, 161); tasker.SetStatus(Resources.WritingSquashFS); hakchi.Shell.Execute("dd \"if=/sd-temp/sd/squash.hsqs\" of=/dev/mmcblk0 bs=1K seek=40", null, null, null, 0, true); // 10 tasker.SetProgress(161, 161); tasker.SetStatus(Resources.MountingSquashFS); hakchi.Shell.Execute($"losetup -o {1024 * 40} /dev/loop1 /dev/mmcblk0", null, null, null, 0, true); hakchi.Shell.Execute("mount /dev/loop1 /squashtools", null, null, null, 0, true); hakchi.Shell.Execute("cp /squashtools/init /tmp/init", null, null, null, 0, true); hakchi.Shell.Execute("sh /tmp/init partition", null, splitStream, splitStream, 0, true); } else { hakchi.Shell.Execute("echo sdprep | dd \"of=/dev/mmcblk0\"", null, null, null, 0, true); //hakchi.Shell.Execute("mount /sd-temp/sd/squash.hsqs /squashtools", null, null, null, 0, true); using (var sfdisk = File.OpenRead(Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "sfdisk.static"))) hakchi.Shell.Execute("cat > /tmp/sfdisk", sfdisk, throwOnNonZero: true); hakchi.Shell.Execute("chmod +x /tmp/sfdisk", throwOnNonZero: true); hakchi.Shell.Execute("/tmp/sfdisk /dev/mmcblk0", new MemoryStream(Encoding.ASCII.GetBytes("128M,,L\n")), splitStream, splitStream, 0, true); hakchi.Shell.Execute("rm /tmp/sfdisk", throwOnNonZero: true); } return(Tasker.Conclusion.Success); }
public Tasker.Conclusion ScrapeGames(Tasker tasker, Object syncObject = null) { if (Program.TheGamesDBAPI == null) { return(Tasker.Conclusion.Success); } try { var idList = new Dictionary <UInt32, int>(); foreach (var app in NewGames) { if (app.Metadata.OriginalCrc32 != 0 && data.GamesDB.HashLookup.ContainsKey(app.Metadata.OriginalCrc32) && data.GamesDB.HashLookup[app.Metadata.OriginalCrc32].TgdbId.Count > 0) { if (!idList.ContainsKey(app.Metadata.OriginalCrc32)) { idList.Add(app.Metadata.OriginalCrc32, data.GamesDB.HashLookup[app.Metadata.OriginalCrc32].TgdbId.First()); } } } var api = Program.TheGamesDBAPI; var infoList = new Dictionary <int, IScraperData>(); foreach (var chunk in idList.Values.Distinct().ToList().ChunkBy(20)) { var apiResponse = api.GetInfoByID(chunk.ToArray()); while (true) { apiResponse.Wait(); foreach (var result in apiResponse.Result.Items) { infoList.Add(int.Parse(result.ID), result); } if (apiResponse.Result.HasNextPage) { apiResponse = apiResponse.Result.GetNextPage(); } else { break; } } } var counter = 0; foreach (var app in NewGames) { tasker.SetProgress(++counter, NewGames.Count); tasker.SetStatus(string.Format(Resources.Scraping0, app.Name)); int tgdbId; if (app.Metadata.OriginalCrc32 != 0 && data.GamesDB.HashLookup.ContainsKey(app.Metadata.OriginalCrc32) && data.GamesDB.HashLookup[app.Metadata.OriginalCrc32].TgdbId.Count > 0 && infoList.ContainsKey(tgdbId = data.GamesDB.HashLookup[app.Metadata.OriginalCrc32].TgdbId.First())) { try { var apiResult = infoList[tgdbId]; if (apiResult.Name != null) { var name = GamesDB.HashLookup[app.Metadata.OriginalCrc32].Name; if (name != null) { name = Shared.CleanName(name, true); } app.Desktop.Name = name ?? apiResult.Name; app.Desktop.SortName = Shared.GetSortName(app.Desktop.Name); } if (apiResult.Publishers != null && apiResult.Publishers.Length > 0) { app.Desktop.Publisher = String.Join(", ", apiResult.Publishers).ToUpper(); } else if (apiResult.Developers != null && apiResult.Developers.Length > 0) { if (apiResult.ReleaseDate != null) { app.Desktop.Copyright = $"© {apiResult.ReleaseDate.Year} {String.Join(", ", apiResult.Developers)}"; } else { app.Desktop.Copyright = $"© {String.Join(", ", apiResult.Developers)}"; } } if (apiResult.Description != null) { app.Desktop.Description = apiResult.Description; } if (apiResult.ReleaseDate != null) { app.Desktop.ReleaseDate = apiResult.ReleaseDate.ToString("yyyy-MM-dd"); } if (apiResult.PlayerCount > 0) { app.Desktop.Players = Convert.ToByte(apiResult.PlayerCount); app.Desktop.Simultaneous = apiResult.PlayerCount == 2; } if (apiResult.Genres != null && apiResult.Genres.Length > 0) { foreach (var genre in apiResult.Genres) { var match = Genre.GenreList.Where(g => g.GamesDbId.Contains(genre.ID)).Select(g => g); if (match.Count() > 0) { var firstGenre = match.First(); app.Desktop.Genre = firstGenre.DesktopName; break; } } } using (var wc = new HakchiWebClient()) { try { var front = apiResult.Images.Where(i => i.Type == TeamShinkansen.Scrapers.Enums.ArtType.Front).ToArray(); if (front.Length > 0 && !app.CoverArtMatchSuccess) { tasker.SetStatus(string.Format(Resources.DownloadingFrontArtFor0, apiResult.Name)); var data = wc.DownloadData(front[0].Url); using (var ms = new MemoryStream(data)) using (var bm = new Bitmap(ms)) { app.SetImage(bm); } } } catch (WebException ex) { } try { tasker.SetStatus(string.Format(Resources.DownloadingClearLogoFor0, apiResult.Name)); var imageData = wc.DownloadData($"https://cdn.thegamesdb.net/images/original/clearlogo/{apiResult.ID}.png"); using (var ms = new MemoryStream(imageData)) using (var clearLogo = File.OpenWrite(Path.Combine(app.BasePath, $"{app.Code}_logo.png"))) { ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(clearLogo); ms.Seek(0, SeekOrigin.Begin); tasker.SetStatus(string.Format(Resources.GeneratingSpineFor0, apiResult.Name)); using (var bm = new Bitmap(ms)) using (var cl = new SystemDrawingBitmap(bm)) using (var spineImage = (Program.SpineTemplates.Where(e => e.Value.Name == "Custom (Black Grid)").First().Value as SpineTemplate <Bitmap>).Process(cl).Bitmap) { app.SetMdMini(spineImage, NesMenuElementBase.GameImageType.MdSpine); } } } catch (WebException ex) { } } } catch (Exception innerEx) { } } } } catch (Exception ex) { } return(Tasker.Conclusion.Success); }
public Tasker.Conclusion AddGames(Tasker tasker, Object syncObject = null) { tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.AddingGames); tasker.SetTitle(Resources.AddingGames); tasker.SetStatusImage(Resources.sign_cogs); // static presets NesApplication.ParentForm = tasker.HostForm; NesApplication.NeedPatch = null; NesApplication.Need3rdPartyEmulator = null; NesApplication.CachedCoverFiles = null; NesGame.IgnoreMapper = null; SnesGame.NeedAutoDownloadCover = null; int total = files.Count(); int count = 0; var gamesWithMultipleArt = new List <NesApplication>(); foreach (var sourceFileName in files) { NesApplication app = null; try { tasker.SetStatus(string.Format(Resources.AddingGame, Path.GetFileName(sourceFileName))); var fileName = sourceFileName; var ext = Path.GetExtension(sourceFileName).ToLower(); byte[] rawData = null; string tmp = null; if (!asIs && (ext == ".7z" || ext == ".zip" || ext == ".rar" || ext == ".clvg")) { if (ext == ".clvg") { tmp = TempHelpers.getUniqueTempPath(); Directory.CreateDirectory(tmp); using (var file = File.OpenRead(sourceFileName)) using (var reader = ReaderFactory.Open(file)) { reader.WriteAllToDirectory(tmp, new ExtractionOptions() { ExtractFullPath = true, PreserveFileTime = true }); } var gameFilesInArchive = Directory.GetFiles(tmp, "*.desktop").Select(o => new DirectoryInfo(o)).Cast <DirectoryInfo>().ToArray(); switch (gameFilesInArchive.LongLength) { case 0: // no files found break; case 1: // one file found fileName = gameFilesInArchive[0].FullName; break; default: // multiple files found var r = SelectFile(tasker, gameFilesInArchive.Select(o => o.FullName).ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } break; } } else { using (var extractor = ArchiveFactory.Open(sourceFileName)) { var filesInArchive = extractor.Entries; var gameFilesInArchive = new List <string>(); foreach (var f in extractor.Entries) { if (!f.IsDirectory) { var e = Path.GetExtension(f.Key).ToLower(); if (e == ".desktop") { gameFilesInArchive.Clear(); gameFilesInArchive.Add(f.Key); break; } else if (CoreCollection.Extensions.Contains(e)) { gameFilesInArchive.Add(f.Key); } } } if (gameFilesInArchive.Count == 1) // Only one known file (or app) { fileName = gameFilesInArchive[0]; } else if (gameFilesInArchive.Count > 1) // Many known files, need to select { var r = SelectFile(tasker, gameFilesInArchive.ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } else if (filesInArchive.Count() == 1) // No known files but only one another file { fileName = filesInArchive.First().Key; } else // Need to select { var r = SelectFile(tasker, filesInArchive.Select(f => f.Key).ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } if (fileName != sourceFileName) { var o = new MemoryStream(); if (Path.GetExtension(fileName).ToLower() == ".desktop" || // App in archive, need the whole directory filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".jpg") || // Or it has cover in archive filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".png") || filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".ips") // Or IPS file ) { tmp = Path.Combine(tempDirectory, fileName); Directory.CreateDirectory(tmp); extractor.WriteToDirectory(tmp, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true }); fileName = Path.Combine(tmp, fileName); } else { extractor.Entries.Where(f => f.Key == fileName).First().WriteTo(o); rawData = new byte[o.Length]; o.Seek(0, SeekOrigin.Begin); o.Read(rawData, 0, (int)o.Length); } } } } } app = NesApplication.Import(fileName, sourceFileName, rawData, asIs); if (ext == ".clvg") { app.SkipCoreSelect = true; } else { if (app.CoverArtMatches != null && app.CoverArtMatches.Count() > 1) { gamesWithMultipleArt.Add(app); } if (ConfigIni.Instance.EnableImportScraper && Program.TheGamesDBAPI != null && app.Metadata.OriginalCrc32 != 0 && data.GamesDB.HashLookup.ContainsKey(app.Metadata.OriginalCrc32) && data.GamesDB.HashLookup[app.Metadata.OriginalCrc32].Length > 0) { var api = Program.TheGamesDBAPI; var task = api.GetInfoByID(data.GamesDB.HashLookup[app.Metadata.OriginalCrc32]); try { task.Wait(); var result = task.Result; if (result.Items.Count() > 0) { var first = result.Items.First(); if (first.Name != null) { app.Desktop.Name = first.Name; app.Desktop.SortName = Shared.GetSortName(first.Name); } if (first.Publishers != null && first.Publishers.Length > 0) { app.Desktop.Publisher = String.Join(", ", first.Publishers).ToUpper(); } else if (first.Developers != null && first.Developers.Length > 0) { if (first.ReleaseDate != null) { app.Desktop.Copyright = $"© {first.ReleaseDate.Year} {String.Join(", ", first.Developers)}"; } else { app.Desktop.Copyright = $"© {String.Join(", ", first.Developers)}"; } } if (first.Description != null) { app.Desktop.Description = first.Description; } if (first.ReleaseDate != null) { app.Desktop.ReleaseDate = first.ReleaseDate.ToString("yyyy-MM-dd"); } if (first.PlayerCount > 0) { app.Desktop.Players = Convert.ToByte(first.PlayerCount); app.Desktop.Simultaneous = first.PlayerCount == 2; } if (first.Genres != null && first.Genres.Length > 0) { foreach (var genre in first.Genres) { var match = ScraperForm.TheGamesDBGenreLookup.Where(g => g.Value.Contains(genre.ID)).Select(g => g.Key); if (match.Count() > 0) { var firstGenre = match.First(); app.Desktop.Genre = firstGenre; break; } } } using (var wc = new HakchiWebClient()) { try { var front = first.Images.Where(i => i.Type == TeamShinkansen.Scrapers.Enums.ArtType.Front).ToArray(); if (front.Length > 0 && !app.CoverArtMatchSuccess) { var data = wc.DownloadData(front[0].Url); using (var ms = new MemoryStream(data)) using (var bm = new Bitmap(ms)) { app.SetImage(bm); } } } catch (WebException ex) { } try { var imageData = wc.DownloadData($"https://cdn.thegamesdb.net/images/original/clearlogo/{first.ID}.png"); using (var ms = new MemoryStream(imageData)) using (var clearLogo = File.OpenWrite(Path.Combine(app.BasePath, $"{app.Code}_logo.png"))) { ms.Seek(0, SeekOrigin.Begin); ms.CopyTo(clearLogo); } } catch (WebException ex) { } } } } catch (Exception) { } } } if (app is ISupportsGameGenie && Path.GetExtension(fileName).ToLower() == ".nes") { var lGameGeniePath = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xml"); if (File.Exists(lGameGeniePath)) { GameGenieDataBase lGameGenieDataBase = new GameGenieDataBase(app); lGameGenieDataBase.ImportCodes(lGameGeniePath, true); lGameGenieDataBase.Save(); } } if (!string.IsNullOrEmpty(tmp) && Directory.Exists(tmp)) { Directory.Delete(tmp, true); } } catch (Exception ex) { if (ex is ThreadAbortException) { return(Tasker.Conclusion.Abort); } if (ex.InnerException != null && !string.IsNullOrEmpty(ex.InnerException.Message)) { Trace.WriteLine(ex.InnerException.Message + ex.InnerException.StackTrace); tasker.ShowError(ex.InnerException, Path.GetFileName(sourceFileName)); } else { Trace.WriteLine(ex.Message + ex.StackTrace, Path.GetFileName(sourceFileName)); tasker.ShowError(ex); } return(Tasker.Conclusion.Error); } if (app != null) { addedApps.Add(app); } tasker.SetProgress(++count, total); } if (gamesWithMultipleArt.Count > 0) { tasker.HostForm.Invoke(new Action(() => { using (SelectCoverDialog selectCoverDialog = new SelectCoverDialog()) { selectCoverDialog.Games.AddRange(gamesWithMultipleArt); selectCoverDialog.ShowDialog(tasker.HostForm); } })); } return(Tasker.Conclusion.Success); }
public Tasker.Conclusion SyncLocalGames(Tasker tasker, Object syncObject = null) { // now transfer whatever games are remaining Debug.WriteLine("Exporting games: " + Shared.SizeSuffix(stats.TotalSize)); long max = transferGameSet.Sum(afi => afi.FileSize); long value = 0; DateTime startTime = DateTime.Now, lastTime = DateTime.Now; tasker.SetProgress(0, max, Tasker.State.Running, Resources.CopyingGames); foreach (var afi in transferGameSet) { string path = new Uri(exportDirectory + "/" + afi.FilePath).LocalPath; string dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (DateTime.Now.Subtract(lastTime).TotalMilliseconds > UpdateFreq) { transferForm.SetAdvancedProgress(value, max, afi.FilePath); lastTime = DateTime.Now; } // either read actual file, or file stream if (!string.IsNullOrEmpty(afi.LocalFilePath)) { if (afi.FileSize > NesApplication.MaxCompress) { using (var stream = new TrackableFileStream(afi.LocalFilePath, FileMode.Open)) { stream.OnProgress += ((long pos, long len) => { if (DateTime.Now.Subtract(lastTime).TotalMilliseconds > UpdateFreq) { transferForm.SetAdvancedProgress(value + pos, max, afi.FilePath); lastTime = DateTime.Now; } }); using (var f = File.Open(path, FileMode.Create)) stream.CopyTo(f); File.SetLastWriteTimeUtc(path, afi.ModifiedTime); } } else { File.Copy(afi.LocalFilePath, path, true); } } else { if (afi.FileStream == null || !afi.FileStream.CanRead) { Debug.WriteLine($"\"{afi.FilePath}\": no source data or stream or unreadable"); } else { afi.FileStream.Position = 0; using (var f = File.Open(path, FileMode.Create)) afi.FileStream.CopyTo(f); File.SetLastWriteTimeUtc(path, afi.ModifiedTime); } } value += afi.FileSize; } Debug.WriteLine("Uploaded " + (int)(max / 1024) + "kb in " + DateTime.Now.Subtract(startTime).TotalSeconds + " seconds"); // show resulting games directory tasker.SetStatus(Resources.PleaseWait); var process = new Process() { StartInfo = new ProcessStartInfo() { FileName = exportDirectory } }; process.Start(); return(Tasker.Conclusion.Success); }
public Conclusion MembootFel(Tasker tasker, Object syncObject = null) { tasker.SetStatus(Resources.Membooting); if (hakchi.Shell.IsOnline) { return(Conclusion.Abort); } // check and adjust kernel size byte[] kernel = hakchi.GetMembootImage().ToArray(); var size = Shared.CalcKernelSize(kernel); if (size > kernel.Length || size > Fel.transfer_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } // clovershell override "hex-edit" boot.img if (ConfigIni.Instance.ForceClovershell || ConfigIni.Instance.ForceNetwork) { kernel.InPlaceStringEdit(64, 512, 0, (string str) => { str.Replace("hakchi-shell", "").Replace("hakchi-clovershell", ""); if (ConfigIni.Instance.ForceClovershell) { str += " hakchi-clovershell"; } else if (ConfigIni.Instance.ForceNetwork) { str += " hakchi-shell"; } return(str); }); } // upload kernel through fel int progress = 0; int maxProgress = (int)((double)kernel.Length / (double)67000 + 50); fel.WriteMemory(Fel.transfer_base_m, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.WritingMemory: tasker.SetStatus(Resources.UploadingKernel); break; } progress++; tasker.SetProgress(progress, maxProgress); } ); var bootCommand = string.Format("boota {0:x}", Fel.transfer_base_m); tasker.SetStatus(Resources.ExecutingCommand + " " + bootCommand); fel.RunUbootCmd(bootCommand, true); return(Conclusion.Success); }
public Tasker.Conclusion BuildFiles(Tasker tasker, Object syncObject = null) { tasker.SetStatus(Resources.AddingGames); AddMenu(Games, originalGames, copyMode, localGameSet, stats); return(Tasker.Conclusion.Success); }
public Conclusion Memboot(Tasker tasker, Object syncObject = null) { tasker.SetStatus(Resources.Membooting); byte[] kernel; if (stockKernel != null && stockKernel.Length > 0) { kernel = stockKernel.ToArray(); } else { kernel = Shared.GetMembootImage().ToArray(); } if (!hakchi.Shell.IsOnline) { var size = Shared.CalcKernelSize(kernel); if (size > kernel.Length || size > Fel.transfer_max_size) { throw new Exception(Resources.InvalidKernelSize + " " + size); } size = (size + Fel.sector_size - 1) / Fel.sector_size; size = size * Fel.sector_size; if (kernel.Length != size) { var newK = new byte[size]; Array.Copy(kernel, newK, kernel.Length); kernel = newK; } } tasker.SetStatus(Resources.UploadingKernel); if (hakchi.Shell.IsOnline && hakchi.Shell.Execute("[ -f /proc/atags ]") == 0) { // override string addedArgs = ConfigIni.Instance.ForceClovershell ? " hakchi-clovershell" : ""; // do we care about stock kernel if (stockKernel == null) { if (hakchi.MinimalMemboot) // already in minimal memboot? { return(Conclusion.Success); } if (hakchi.Shell.ExecuteSimple("[ -e /bin/detached ] && echo \"1\"") == "1") // detached recovery function? { try { hakchi.Shell.ExecuteSimple("/bin/detached recovery" + addedArgs, 100); } catch { } // no-op return(Conclusion.Success); } } try { hakchi.Shell.ExecuteSimple("uistop"); hakchi.Shell.ExecuteSimple("mkdir -p /tmp/kexec/", throwOnNonZero: true); hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "kexec.static"), "/tmp/kexec/kexec"); TrackableStream kernelStream = new TrackableStream(kernel); kernelStream.OnProgress += tasker.OnProgress; if (stockKernel == null) { hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "detached-fallback"), "/tmp/kexec/detached-fallback"); hakchi.UploadFile(kernelStream, "/tmp/kexec/boot.img", false); try { hakchi.Shell.ExecuteSimple("cd /tmp/kexec/; /bin/sh /tmp/kexec/detached-fallback recovery /tmp/kexec/boot.img" + addedArgs, 100); } catch { } // no-op } else { hakchi.UploadFile( Path.Combine(Program.BaseDirectoryInternal, "tools", "arm", "unpackbootimg.static"), "/tmp/kexec/unpackbootimg"); hakchi.Shell.Execute( command: "cat > /tmp/kexec/boot.img; cd /tmp/kexec/; ./unpackbootimg -i boot.img", stdin: kernelStream, throwOnNonZero: true ); hakchi.Shell.ExecuteSimple("cd /tmp/kexec/ && ./kexec -l -t zImage boot.img-zImage \"--command-line=$(cat boot.img-cmdline)\" --ramdisk=boot.img-ramdisk.gz --atags", 0, true); hakchi.Shell.ExecuteSimple("cd /tmp/; umount -ar", 0); try { hakchi.Shell.ExecuteSimple("/tmp/kexec/kexec -e", 100); } catch { } // no-op } } catch { try { hakchi.Shell.ExecuteSimple("uistart"); } catch { } // no-op throw; } } else { if (stockKernel == null && ConfigIni.Instance.ForceClovershell) { kernel.InPlaceStringEdit(64, 512, 0, (string str) => { if (str.IndexOf("hakchi-shell") != -1) { return(str.Replace("hakchi-shell", "hakchi-clovershell")); } else { return(str + " hakchi-clovershell"); } }); } int progress = 0; int maxProgress = (int)((double)kernel.Length / (double)67000 + 50); fel.WriteMemory(Fel.transfer_base_m, kernel, delegate(Fel.CurrentAction action, string command) { switch (action) { case Fel.CurrentAction.WritingMemory: tasker.SetStatus(Resources.UploadingKernel); break; } progress++; tasker.SetProgress(progress, maxProgress); } ); var bootCommand = string.Format("boota {0:x}", Fel.transfer_base_m); tasker.SetStatus(Resources.ExecutingCommand + " " + bootCommand); fel.RunUbootCmd(bootCommand, true); } return(Conclusion.Success); }
public static Tasker SetStatus(this Tasker tasker, Tasker.State state, string status) { tasker.SetState(state); tasker.SetStatus(status); return(tasker); }
public static Tasker.Conclusion ShowSplashScreen(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus(Resources.PleaseWait); return(hakchi.ShowSplashScreen() == 0 ? Tasker.Conclusion.Success : Tasker.Conclusion.Error); }
public Tasker.Conclusion AddGames(Tasker tasker, Object syncObject = null) { tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.AddingGames); tasker.SetTitle(Resources.AddingGames); tasker.SetStatusImage(Resources.sign_cogs); // static presets NesApplication.ParentForm = tasker.HostForm; NesApplication.NeedPatch = null; NesApplication.Need3rdPartyEmulator = null; NesApplication.CachedCoverFiles = null; NesGame.IgnoreMapper = null; SnesGame.NeedAutoDownloadCover = null; int total = files.Count(); int count = 0; var gamesWithMultipleArt = new List <NesApplication>(); foreach (var sourceFileName in files) { NesApplication app = null; try { tasker.SetStatus(string.Format(Resources.AddingGame, Path.GetFileName(sourceFileName))); var fileName = sourceFileName; var ext = Path.GetExtension(sourceFileName).ToLower(); byte[] rawData = null; string tmp = null; if (!asIs && (ext == ".7z" || ext == ".zip" || ext == ".rar" || ext == ".clvg")) { if (ext == ".clvg") { tmp = TempHelpers.getUniqueTempPath(); Directory.CreateDirectory(tmp); using (var file = File.OpenRead(sourceFileName)) using (var reader = ReaderFactory.Open(file)) { reader.WriteAllToDirectory(tmp, new ExtractionOptions() { ExtractFullPath = true, PreserveFileTime = true }); } var gameFilesInArchive = Directory.GetFiles(tmp, "*.desktop").Select(o => new DirectoryInfo(o)).Cast <DirectoryInfo>().ToArray(); switch (gameFilesInArchive.LongLength) { case 0: // no files found break; case 1: // one file found fileName = gameFilesInArchive[0].FullName; break; default: // multiple files found var r = SelectFile(tasker, gameFilesInArchive.Select(o => o.FullName).ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } break; } } else { using (var extractor = ArchiveFactory.Open(sourceFileName)) { var filesInArchive = extractor.Entries; var gameFilesInArchive = new List <string>(); foreach (var f in extractor.Entries) { if (!f.IsDirectory) { var e = Path.GetExtension(f.Key).ToLower(); if (e == ".desktop") { gameFilesInArchive.Clear(); gameFilesInArchive.Add(f.Key); break; } else if (CoreCollection.Extensions.Contains(e)) { gameFilesInArchive.Add(f.Key); } } } if (gameFilesInArchive.Count == 1) // Only one known file (or app) { fileName = gameFilesInArchive[0]; } else if (gameFilesInArchive.Count > 1) // Many known files, need to select { var r = SelectFile(tasker, gameFilesInArchive.ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } else if (filesInArchive.Count() == 1) // No known files but only one another file { fileName = filesInArchive.First().Key; } else // Need to select { var r = SelectFile(tasker, filesInArchive.Select(f => f.Key).ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } if (fileName != sourceFileName) { var o = new MemoryStream(); if (Path.GetExtension(fileName).ToLower() == ".desktop" || // App in archive, need the whole directory filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".jpg") || // Or it has cover in archive filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".png") || filesInArchive.Select(f => f.Key).Contains(Path.GetFileNameWithoutExtension(fileName) + ".ips") // Or IPS file ) { tmp = Path.Combine(tempDirectory, fileName); Directory.CreateDirectory(tmp); extractor.WriteToDirectory(tmp, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true }); fileName = Path.Combine(tmp, fileName); } else { extractor.Entries.Where(f => f.Key == fileName).First().WriteTo(o); rawData = new byte[o.Length]; o.Seek(0, SeekOrigin.Begin); o.Read(rawData, 0, (int)o.Length); } } } } } app = NesApplication.Import(fileName, sourceFileName, rawData, asIs); if (ext == ".clvg") { app.SkipCoreSelect = true; } else { if (app.CoverArtMatches != null && app.CoverArtMatches.Count() > 1) { gamesWithMultipleArt.Add(app); } NewGames.Add(app); } if (app is ISupportsGameGenie && Path.GetExtension(fileName).ToLower() == ".nes") { var lGameGeniePath = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xml"); if (File.Exists(lGameGeniePath)) { GameGenieDataBase lGameGenieDataBase = new GameGenieDataBase(app); lGameGenieDataBase.ImportCodes(lGameGeniePath, true); lGameGenieDataBase.Save(); } } if (!string.IsNullOrEmpty(tmp) && Directory.Exists(tmp)) { Directory.Delete(tmp, true); } } catch (Exception ex) { if (ex is ThreadAbortException) { return(Tasker.Conclusion.Abort); } if (ex.InnerException != null && !string.IsNullOrEmpty(ex.InnerException.Message)) { Trace.WriteLine(ex.InnerException.Message + ex.InnerException.StackTrace); tasker.ShowError(ex.InnerException, Path.GetFileName(sourceFileName)); } else { Trace.WriteLine(ex.Message + ex.StackTrace, Path.GetFileName(sourceFileName)); tasker.ShowError(ex); } return(Tasker.Conclusion.Error); } if (app != null) { addedApps.Add(app); } tasker.SetProgress(++count, total); } if (gamesWithMultipleArt.Count > 0) { tasker.HostForm.Invoke(new Action(() => { using (SelectCoverDialog selectCoverDialog = new SelectCoverDialog()) { selectCoverDialog.Games.AddRange(gamesWithMultipleArt); selectCoverDialog.ShowDialog(tasker.HostForm); } })); } return(Tasker.Conclusion.Success); }
public static Tasker.Conclusion SyncConfig(Tasker tasker = null, Object syncObject = null) { tasker?.SetStatus(Resources.UploadingConfig); hakchi.SyncConfig(ConfigIni.GetConfigDictionary()); return(Tasker.Conclusion.Success); }
public Tasker.Conclusion AddGames(Tasker tasker, Object syncObject = null) { tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.AddingGames); tasker.SetTitle(Resources.AddingGames); tasker.SetStatusImage(Resources.sign_cogs); // static presets NesApplication.ParentForm = tasker.HostForm; NesApplication.NeedPatch = null; NesApplication.Need3rdPartyEmulator = null; NesApplication.CachedCoverFiles = null; NesGame.IgnoreMapper = null; SnesGame.NeedAutoDownloadCover = null; int total = files.Count(); int count = 0; foreach (var sourceFileName in files) { NesApplication app = null; try { tasker.SetStatus(string.Format(Resources.AddingGame, Path.GetFileName(sourceFileName))); var fileName = sourceFileName; var ext = Path.GetExtension(sourceFileName).ToLower(); byte[] rawData = null; string tmp = null; if (ext == ".7z" || ext == ".zip" || ext == ".rar") { using (var szExtractor = new SevenZipExtractor(sourceFileName)) { var filesInArchive = szExtractor.ArchiveFileNames; var gameFilesInArchive = new List <string>(); foreach (var f in szExtractor.ArchiveFileData) { if (!f.IsDirectory) { var e = Path.GetExtension(f.FileName).ToLower(); if (e == ".desktop") { gameFilesInArchive.Clear(); gameFilesInArchive.Add(f.FileName); break; } else if (CoreCollection.Extensions.Contains(e)) { gameFilesInArchive.Add(f.FileName); } } } if (gameFilesInArchive.Count == 1) // Only one known file (or app) { fileName = gameFilesInArchive[0]; } else if (gameFilesInArchive.Count > 1) // Many known files, need to select { var r = SelectFile(tasker, gameFilesInArchive.ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } else if (filesInArchive.Count == 1) // No known files but only one another file { fileName = filesInArchive[0]; } else // Need to select { var r = SelectFile(tasker, filesInArchive.ToArray()); if (r == DialogResult.OK) { fileName = selectedFile; } else if (r == DialogResult.Ignore) { fileName = sourceFileName; } else { continue; } } if (fileName != sourceFileName) { var o = new MemoryStream(); if (Path.GetExtension(fileName).ToLower() == ".desktop" || // App in archive, need the whole directory szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".jpg") || // Or it has cover in archive szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".png") || szExtractor.ArchiveFileNames.Contains(Path.GetFileNameWithoutExtension(fileName) + ".ips") // Or IPS file ) { tmp = Path.Combine(tempDirectory, fileName); Directory.CreateDirectory(tmp); szExtractor.ExtractArchive(tmp); fileName = Path.Combine(tmp, fileName); } else { szExtractor.ExtractFile(fileName, o); rawData = new byte[o.Length]; o.Seek(0, SeekOrigin.Begin); o.Read(rawData, 0, (int)o.Length); } } } } app = NesApplication.Import(fileName, sourceFileName, rawData); if (app is ISupportsGameGenie && Path.GetExtension(fileName).ToLower() == ".nes") { var lGameGeniePath = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".xml"); if (File.Exists(lGameGeniePath)) { GameGenieDataBase lGameGenieDataBase = new GameGenieDataBase(app); lGameGenieDataBase.ImportCodes(lGameGeniePath, true); lGameGenieDataBase.Save(); } } if (!string.IsNullOrEmpty(tmp) && Directory.Exists(tmp)) { Directory.Delete(tmp, true); } } catch (Exception ex) { if (ex is ThreadAbortException) { return(Tasker.Conclusion.Abort); } if (ex.InnerException != null && !string.IsNullOrEmpty(ex.InnerException.Message)) { Trace.WriteLine(ex.InnerException.Message + ex.InnerException.StackTrace); tasker.ShowError(ex.InnerException, Path.GetFileName(sourceFileName)); } else { Trace.WriteLine(ex.Message + ex.StackTrace, Path.GetFileName(sourceFileName)); tasker.ShowError(ex); } return(Tasker.Conclusion.Error); } if (app != null) { addedApps.Add(app); } tasker.SetProgress(++count, total); } return(Tasker.Conclusion.Success); }