예제 #1
0
        public Tasker.Conclusion DecompressGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.DecompressingGames);
            tasker.SetStatusImage(Resources.sign_cogs);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.DecompressingGames);

            int i = 0;

            foreach (NesApplication game in Games)
            {
                if (!game.IsOriginalGame)
                {
                    tasker.SetStatus(string.Format(Resources.Decompressing, game.Name));
                    game.Decompress();
                    tasker.SetProgress(++i, Games.Count);
                }
                else
                {
                    tasker.SetStatus(string.Format(Resources.Skipping, game.Name));
                    Thread.Sleep(1);
                }
            }

            return(Tasker.Conclusion.Success);
        }
예제 #2
0
        public Tasker.Conclusion ResetROMHeaders(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.ResettingHeaders);
            tasker.SetStatusImage(Resources.sign_database);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.ResettingHeaders);

            int i = 0;

            foreach (NesApplication game in Games)
            {
                if (game is SnesGame && !(game as SnesGame).IsOriginalGame)
                {
                    tasker.SetStatus(string.Format(Resources.ResettingHeader, game.Name));
                    bool wasCompressed = game.DecompressPossible().Length > 0;
                    if (wasCompressed)
                    {
                        game.Decompress();
                    }
                    SfromToolWrapper.ResetSFROM(game.GameFilePath);
                    if (wasCompressed)
                    {
                        game.Compress();
                    }
                }
                else
                {
                    tasker.SetStatus(string.Format(Resources.Skipping, game.Name));
                    Thread.Sleep(1);
                }

                tasker.SetProgress(++i, Games.Count);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #3
0
        public Tasker.Conclusion DeleteGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.RemovingGames);
            tasker.SetStatusImage(Resources.sign_trashcan);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.RemovingGames);

            int i = 0;

            foreach (NesApplication game in Games)
            {
                if (!game.IsOriginalGame)
                {
                    tasker.SetStatus(string.Format(Resources.Removing, game.Name));
                    game.IsDeleting = true;
                    Directory.Delete(game.BasePath, true);
                    tasker.SetProgress(++i, Games.Count);
                }
                else
                {
                    tasker.SetStatus(string.Format(Resources.Skipping, game.Name));
                    Thread.Sleep(1);
                }
            }

            return(Tasker.Conclusion.Success);
        }
예제 #4
0
        public static Conclusion GetHmods(Tasker tasker, Object modObject)
        {
            if (!(modObject is ModObject))
            {
                return(Conclusion.Error);
            }
            ModObject unboxedObject = (ModObject)modObject;

            unboxedObject.LoadedHmods = new List <Hmod>();
            if (unboxedObject.HmodsToLoad == null)
            {
                return(Conclusion.Error);
            }
            tasker.SetStatus(Properties.Resources.LoadingHmods);
            int progress = 0;

            foreach (string mod in unboxedObject.HmodsToLoad)
            {
                unboxedObject.LoadedHmods.Add(new Hmod(mod, unboxedObject.InstalledHmods));
                progress++;
                tasker.SetProgress(progress, unboxedObject.HmodsToLoad.Count);
            }
            tasker.SetProgress(1, 1);
            return(Conclusion.Success);
        }
예제 #5
0
        public Tasker.Conclusion ScanCovers(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.ScanningCovers);
            tasker.SetStatusImage(Resources.sign_file_picture);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.ScanningCovers);
            var unknownApps = new List <NesApplication>();
            int i           = 0;

            foreach (NesApplication game in Games)
            {
                tasker.SetStatus(string.Format(Resources.ScanningCover, game.Name));
                try
                {
                    uint   crc32    = game.Metadata.OriginalCrc32;
                    string gameFile = game.GameFilePath;
                    if (crc32 == 0 && !game.IsOriginalGame && gameFile != null && File.Exists(gameFile))
                    {
                        using (var stream = game.GameFileStream)
                        {
                            if (stream != null)
                            {
                                stream.Position             = 0;
                                crc32                       = Shared.CRC32(stream);
                                game.Metadata.OriginalCrc32 = crc32;
                                game.SaveMetadata();
                            }
                        }
                    }
                    else
                    {
                        gameFile = game.BasePath;
                    }
                    game.FindCover(game.Metadata.OriginalFilename ?? Path.GetFileName(gameFile), crc32, game.Name);
                    if (!game.CoverArtMatchSuccess && game.CoverArtMatches.Any())
                    {
                        unknownApps.Add(game);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Error trying to finding cover art for game " + game.Name);
                    Debug.WriteLine(ex.Message + ex.StackTrace);
                }
                tasker.SetProgress(++i, Games.Count);
            }

            if (unknownApps.Count > 0)
            {
                tasker.HostForm.Invoke(new Action(() => {
                    using (SelectCoverDialog selectCoverDialog = new SelectCoverDialog())
                    {
                        selectCoverDialog.Games.AddRange(unknownApps);
                        selectCoverDialog.ShowDialog(tasker.HostForm);
                    }
                }));
            }

            return(Tasker.Conclusion.Success);
        }
예제 #6
0
        public Tasker.Conclusion DownloadCovers(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.DownloadAllCoversTitle);
            tasker.SetStatusImage(Resources.sign_globe);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.DownloadAllCoversTitle);
            int i = 0;

            foreach (NesApplication game in Games)
            {
                tasker.SetStatus(Resources.GooglingFor.Trim() + " " + game.Name + "...");
                string[] urls = null;
                for (int tries = 0; tries < 5; tries++)
                {
                    if (urls == null)
                    {
                        try
                        {
                            urls = ImageGooglerForm.GetImageUrls(game);
                            break;
                        }
                        catch (Exception ex)
                        {
                            tasker.SetStatus(Resources.Error + ": " + ex.Message);
                            Thread.Sleep(1500);
                            continue;
                        }
                    }
                }
                if (urls != null && urls.Length == 0)
                {
                    tasker.SetStatus(Resources.NotFound + " " + game.Name);
                }
                for (int tries = 0; urls != null && tries < 5 && tries < urls.Length; tries++)
                {
                    try
                    {
                        var cover = ImageGooglerForm.DownloadImage(urls[tries]);
                        game.Image = cover;
                        break;
                    }
                    catch (Exception ex)
                    {
                        tasker.SetStatus(Resources.Error + ": " + ex.Message);
                        Thread.Sleep(1500);
                        continue;
                    }
                }
                tasker.SetProgress(++i, Games.Count);
                Thread.Sleep(500); // not so fast, Google don't like it
            }
            return(Tasker.Conclusion.Success);
        }
예제 #7
0
        public Tasker.Conclusion DeleteCovers(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.RemovingCovers);
            tasker.SetStatusImage(Resources.sign_trashcan);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.RemovingCovers);

            int i = 0;

            foreach (NesApplication game in Games)
            {
                game.Image = null;
                tasker.SetProgress(++i, Games.Count);
            }
            return(Tasker.Conclusion.Success);
        }
예제 #8
0
        public Tasker.Conclusion SyncOriginalGames(Tasker tasker, Object syncObject = null)
        {
            if (originalGames.Any())
            {
                using (MemoryStream commandBuilder = new MemoryStream())
                {
                    tasker.SetStatus(Resources.UploadingOriginalGames);

                    string data = $"#!/bin/sh\ncd \"/tmp\"\n";
                    commandBuilder.Write(Encoding.UTF8.GetBytes(data), 0, data.Length);
                    foreach (var originalCode in originalGames.Keys)
                    {
                        string originalSyncCode = "";
                        switch (ConfigIni.Instance.ConsoleType)
                        {
                        case hakchi.ConsoleType.NES:
                        case hakchi.ConsoleType.Famicom:
                            originalSyncCode =
                                $"src=\"{hakchi.SquashFsPath}{hakchi.GamesSquashFsPath}/{originalCode}\" && " +
                                $"dst=\"{uploadPath}/{originalGames[originalCode]}/{originalCode}\" && " +
                                $"mkdir -p \"$dst\" && " +
                                $"([ -L \"$dst/autoplay\" ] || ln -s \"$src/autoplay\" \"$dst/\") && " +
                                $"([ -L \"$dst/pixelart\" ] || ln -s \"$src/pixelart\" \"$dst/\")" +
                                "\n";
                            break;

                        case hakchi.ConsoleType.SNES_EUR:
                        case hakchi.ConsoleType.SNES_USA:
                        case hakchi.ConsoleType.SuperFamicom:
                            originalSyncCode =
                                $"src=\"{hakchi.SquashFsPath}{hakchi.GamesSquashFsPath}/{originalCode}\" && " +
                                $"dst=\"{uploadPath}/{originalGames[originalCode]}/{originalCode}\" && " +
                                $"mkdir -p \"$dst\" && " +
                                $"([ -L \"$dst/autoplay\" ] || ln -s \"$src/autoplay\" \"$dst/\")" +
                                "\n";
                            break;
                        }
                        commandBuilder.Write(Encoding.UTF8.GetBytes(originalSyncCode), 0, originalSyncCode.Length);
                    }
                    tasker.SetProgress(1, 2);

                    hakchi.RunTemporaryScript(commandBuilder, "originalgamessync.sh");
                }

                tasker.SetProgress(2, 2);
            }
            return(Tasker.Conclusion.Success);
        }
예제 #9
0
 public static Tasker SetProgress(this Tasker tasker, long value, long maximum, Tasker.State state, string status)
 {
     tasker.SetProgress(value, maximum);
     tasker.SetState(state);
     tasker.SetStatus(status);
     return(tasker);
 }
예제 #10
0
        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 (!string.IsNullOrEmpty(afi.LocalFilePath))
                {
                    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;

                if (DateTime.Now.Subtract(lastTime).TotalMilliseconds > UpdateFreq)
                {
                    transferForm.SetProgress(value, max, afi.FilePath);
                    lastTime = DateTime.Now;
                }
            }
            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);
        }
예제 #11
0
        internal Tasker.Conclusion ArchiveGames(Tasker tasker, object syncObject)
        {
            long counter   = 0;
            long gameCount = Games.Count;

            tasker.SetTitle(gameCount > 1 ? Resources.ArchivingGames : Resources.ArchivingGame);

            string directory = null;

            if (gameCount > 1)
            {
                using (var fbd = new FolderBrowserDialog()
                {
                    SelectedPath = Program.BaseDirectoryExternal
                })
                {
                    if (fbd.ShowDialog() == DialogResult.OK)
                    {
                        directory = fbd.SelectedPath;
                    }
                    else
                    {
                        return(Tasker.Conclusion.Abort);
                    }
                }
            }

            foreach (var game in Games)
            {
                tasker.SetStatus(String.Format(Resources.Archiving, game.Name));
                var fileName = Shared.ReplaceInvalidFilenameCharacters($"{game.Code} - {game.Name}.clvg");

                if (directory == null)
                {
                    using (var sfd = new SaveFileDialog()
                    {
                        Filter = Resources.GameArchive + "(*.clvg)|*.clvg", FileName = fileName
                    })
                    {
                        if (sfd.ShowDialog() == DialogResult.OK)
                        {
                            game.Archive(sfd.FileName);
                        }
                    }
                }
                else
                {
                    var archivePath = Path.Combine(directory, fileName);
                    if (File.Exists(archivePath) && tasker.ShowMessage(Resources.ReplaceFileQ, String.Format(Resources.ReplaceFollowingFileQ, archivePath), Resources.sign_question, new MessageForm.Button[] { MessageForm.Button.Yes, MessageForm.Button.No }) == MessageForm.Button.No)
                    {
                        continue;
                    }
                    game.Archive(archivePath);
                }
                counter++;
                tasker.SetProgress(counter, gameCount);
            }
            return(Tasker.Conclusion.Success);
        }
예제 #12
0
        public Tasker.Conclusion SetCoverArtForMultipleGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.ApplyChanges);
            tasker.SetStatusImage(Resources.sign_file_picture);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.ApplyChanges);

            NesApplication.CachedCoverFiles = null;
            int i = 0, max = GamesChanged.Count;

            foreach (var pair in GamesChanged)
            {
                pair.Key.SetImageFile(pair.Value, ConfigIni.Instance.CompressCover);
                tasker.SetProgress(++i, max);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #13
0
        public Tasker.Conclusion SyncRemoteGamesShell(Tasker tasker, Object syncObject = null)
        {
            // transfer games
            tasker.SetProgress(0, 100, Tasker.State.Running, Resources.UploadingGames);
            bool uploadSuccessful = false;

            if (!transferGameSet.Any())
            {
                Trace.WriteLine("No file to upload");
                uploadSuccessful = true;
            }
            else
            {
                Trace.WriteLine("Uploading through tar file");
                using (var gamesTar = new TarStream(transferGameSet, "."))
                {
                    Trace.WriteLine($"Upload size: " + Shared.SizeSuffix(gamesTar.Length));
                    if (gamesTar.Length > 0)
                    {
                        DateTime startTime = DateTime.Now, lastTime = DateTime.Now;
                        bool     done = false;
                        gamesTar.OnAdvancedReadProgress += delegate(long pos, long len, string filename)
                        {
                            if (done)
                            {
                                return;
                            }
                            if (DateTime.Now.Subtract(lastTime).TotalMilliseconds >= UpdateFreq)
                            {
                                transferForm.SetAdvancedProgress(pos, len, filename);
                                lastTime = DateTime.Now;
                            }
                        };
                        hakchi.Shell.Execute($"tar -xvC \"{uploadPath}\"", gamesTar, null, null, 0, true);
                        Trace.WriteLine("Uploaded " + (int)(gamesTar.Length / 1024) + "kb in " + DateTime.Now.Subtract(startTime).TotalSeconds + " seconds");

                        uploadSuccessful = true;
                        done             = true;
#if VERY_DEBUG
                        File.Delete(Program.BaseDirectoryExternal + "\\DebugSyncOutput.tar");
                        gamesTar.Position = 0;
                        gamesTar.CopyTo(File.OpenWrite(Program.BaseDirectoryExternal + "\\DebugSyncOutput.tar"));
#endif
                    }
                    transferForm.SetAdvancedProgress(gamesTar.Length, gamesTar.Length, "");
                }
            }

            // don't continue if upload wasn't successful
            if (!uploadSuccessful)
            {
                Trace.WriteLine("Something happened during transfer, cancelling");
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #14
0
        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;
        }
예제 #15
0
        public Tasker.Conclusion RepairGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.RepairGames);
            tasker.SetStatusImage(Resources.sign_cogs);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.RepairGames);

            NesApplication.ParentForm = tasker.HostForm;
            int i = 0, max = Games.Count;

            foreach (var game in Games)
            {
                tasker.SetStatus(string.Format(Resources.RepairingGame, game.Name));
                bool success = game.Repair();
                Debug.WriteLine($"Repairing game \"{game.Name}\" was " + (success ? "successful" : "not successful"));
                tasker.SetProgress(++i, max);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #16
0
        public Tasker.Conclusion LinkGames(Tasker tasker, Object syncObject = null)
        {
            using (MemoryStream commandBuilder = new MemoryStream())
            {
                tasker.SetStatus(Resources.LinkingGames);

                string data = $"#!/bin/sh\ncd \"/tmp\"\n";
                commandBuilder.Write(Encoding.UTF8.GetBytes(data), 0, data.Length);
                foreach (var menuCollection in stats.allMenus)
                {
                    AddSymLinks(menuCollection, commandBuilder);
                }

                tasker.SetProgress(1, 2);
                hakchi.RunTemporaryScript(commandBuilder, "linkgamessync.sh");
            }
            tasker.SetProgress(2, 2);
            return(Tasker.Conclusion.Success);
        }
예제 #17
0
        public Tasker.Conclusion SyncRemoteGamesFTP(Tasker tasker, Object syncObject = null)
        {
            // transfer games
            tasker.SetProgress(0, 100, Tasker.State.Running, Resources.UploadingGames);
            bool uploadSuccessful = false;

            if (!transferGameSet.Any())
            {
                Trace.WriteLine("No file to upload");
                uploadSuccessful = true;
            }
            else
            {
                Trace.WriteLine("Uploading through FTP");
                using (var ftp = new FtpWrapper(transferGameSet))
                {
                    Trace.WriteLine($"Upload size: " + Shared.SizeSuffix(ftp.Length));
                    if (ftp.Length > 0)
                    {
                        DateTime startTime = DateTime.Now, lastTime = DateTime.Now;
                        ftp.OnReadProgress += delegate(long pos, long len, string filename)
                        {
                            if (DateTime.Now.Subtract(lastTime).TotalMilliseconds >= UpdateFreq)
                            {
                                transferForm.SetAdvancedProgress(pos, len, filename);
                                lastTime = DateTime.Now;
                            }
                        };
                        if (ftp.Connect((hakchi.Shell as INetworkShell).IPAddress, 21, hakchi.USERNAME, hakchi.PASSWORD))
                        {
                            ftp.Upload(uploadPath);
                            uploadSuccessful = true;
                            Trace.WriteLine("Uploaded " + (int)(ftp.Length / 1024) + "kb in " + DateTime.Now.Subtract(startTime).TotalSeconds + " seconds");
                        }
                    }
                    transferForm.SetAdvancedProgress(ftp.Length, ftp.Length, "");
                }
            }

            // don't continue if upload wasn't successful
            if (!uploadSuccessful)
            {
                Trace.WriteLine("Something happened during transfer, cancelling");
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #18
0
        // --- scan files and create internal list
        public Tasker.Conclusion LoadGamesFromFiles(Tasker tasker, Object syncObject = null)
        {
            var sync = (LoadGamesSyncObject)syncObject;

            // list original game directories
            var originalGameDirs = new List <string>();

            foreach (var defaultGame in NesApplication.CurrentDefaultGames)
            {
                string gameDir   = Path.Combine(NesApplication.OriginalGamesDirectory, defaultGame);
                string cachedDir = Path.Combine(NesApplication.OriginalGamesCacheDirectory, defaultGame);
                if (Directory.Exists(gameDir) && (!ConfigIni.Instance.AlwaysCopyOriginalGames || Directory.Exists(cachedDir)))
                {
                    originalGameDirs.Add(gameDir);
                }
            }

            // add custom games
            Directory.CreateDirectory(NesApplication.GamesDirectory);
            var gameDirs = Shared.ConcatArrays(Directory.GetDirectories(NesApplication.GamesDirectory), originalGameDirs.ToArray());

            var items = new List <ListViewItem>();
            int i     = 0;

            foreach (var gameDir in gameDirs)
            {
                try
                {
                    var game = NesApplication.FromDirectory(gameDir);
                    items.Add(new ListViewItem(game.Name)
                    {
                        Tag = game
                    });
                }
                catch // remove bad directories if any, no throw
                {
                    Trace.WriteLine($"Game directory \"{gameDir}\" is invalid, deleting");
                    Directory.Delete(gameDir, true);
                }
                tasker.SetProgress(++i, gameDirs.Length);
            }
            sync.items = ConfigIni.Instance.OriginalGamesPosition == MainForm.OriginalGamesPosition.Hidden ?
                         items.Where(item => !(item.Tag as NesApplication).IsOriginalGame).ToArray() :
                         items.ToArray();

            return(Tasker.Conclusion.Success);
        }
예제 #19
0
        public Tasker.Conclusion LoadGames(Tasker tasker, Object syncObject = null)
        {
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.LoadingGames);
            tasker.SetStatusImage(Resources.sign_down);
            tasker.SetTitle(Resources.LoadingGames);

            tasker.SyncObject = new LoadGamesSyncObject();
            tasker.AddTasks(
                CreateListViewGroups,
                this.reloadFromFiles ?
                (Tasker.TaskFunc)LoadGamesFromFiles :
                (Tasker.TaskFunc)LoadGamesFromList,
                AssignGroupsToGames,
                AssignListViewGroups,
                UpdateListView);

            return(Tasker.Conclusion.Success);
        }
        public Tasker.Conclusion UpdateLocal(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.UpdatingLocalCache);
            tasker.SetStatusImage(Resources.sign_sync);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.UpdatingLocalCache);

            var shell = hakchi.Shell;

            if (!shell.IsOnline)
            {
                return(Tasker.Conclusion.Abort);
            }

            string gamesCloverPath = shell.ExecuteSimple("hakchi eval 'echo \"$squashfs$gamepath\"'", 2000, true);
            string cachePath       = Path.Combine(Program.BaseDirectoryExternal, "games_cache");

            try
            {
                var reply = shell.ExecuteSimple($"[ -d {gamesCloverPath} ] && echo YES || echo NO");
                if (reply == "NO")
                {
                    gamesCloverPath = hakchi.GamesPath;
                    reply           = shell.ExecuteSimple($"[ -d {gamesCloverPath} ] && echo YES || echo NO");
                    if (reply == "NO")
                    {
                        throw new Exception("Unable to update local cache. games directory not accessible");
                    }
                }

                int i = 0;
                foreach (NesDefaultGame game in Games)
                {
                    string gamePath = Path.Combine(cachePath, game.Code);

                    if (!Directory.Exists(gamePath))
                    {
                        try
                        {
                            Directory.CreateDirectory(gamePath);
                            using (var tar = new MemoryStream())
                            {
                                string cmd = $"cd {gamesCloverPath}/{game.Code} && tar -c *";
                                shell.Execute(cmd, null, tar, null, 10000, true);
                                tar.Seek(0, SeekOrigin.Begin);
                                using (var szExtractorTar = new SevenZipExtractor(tar))
                                    szExtractorTar.ExtractArchive(gamePath);
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.Message + ex.StackTrace);
                            if (Directory.Exists(gamePath))
                            {
                                Debug.WriteLine($"Exception, erasing \"{gamePath}\".");
                                Directory.Delete(gamePath, true);
                            }
                        }
                    }

                    tasker.SetProgress(++i, Games.Count);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message + ex.StackTrace);
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #21
0
        public ITaskerView SetProgress(long value, long maximum, string fileName)
        {
            // call parent tasker SetProgress to update other views (and this one's progress bar)
            Tasker.SetProgress(value, maximum);

            if (Disposing || value < 0 || maximum < 0)
            {
                return(this);
            }
            try
            {
                if (InvokeRequired)
                {
                    return((ITaskerView)Invoke(new Func <long, long, string, ITaskerView>(SetProgress), new object[] { value, maximum, fileName }));
                }

                // update other elements

                if (value >= maximum)
                {
                    this.labelFileName.Text     = "";
                    this.labelTimeLeft.Text     = Resources.Done;
                    this.labelTransferRate.Text = "";
                    return(this);
                }
                this.labelFileName.Text = System.IO.Path.GetFileName(fileName);

                DateTime now = DateTime.Now;
                if (lastTime == default(DateTime))
                {
                    startTime    = lastTime = now;
                    speedSamples = new Queue <double>();
                    return(this);
                }
                else
                {
                    TimeSpan elapsed = now.Subtract(lastTime);
                    if (elapsed.TotalMilliseconds >= SpeedSampleFreq)
                    {
                        speedSamples.Enqueue(((value - lastData) / elapsed.TotalSeconds));
                        if (speedSamples.Count > SpeedSampleNum)
                        {
                            speedSamples.Dequeue();
                        }
                        lastTime = now;
                        lastData = value;
                    }
                }

                if (speedSamples.Any())
                {
                    double sampledSpeed = speedSamples.Average();
                    double timeLeft     = (maximum - value) / (value / now.Subtract(startTime).TotalSeconds);
                    this.labelTimeLeft.Text     = new TimeSpan(0, 0, (int)timeLeft).ToReadableString() + " (" + Shared.SizeSuffix(value) + " of " + Shared.SizeSuffix(maximum) + " copied)";
                    this.labelTransferRate.Text = Shared.SizeSuffix((long)sampledSpeed) + "/Sec";
                }
                else
                {
                    this.labelTimeLeft.Text     = "(" + Shared.SizeSuffix(value) + " of " + Shared.SizeSuffix(maximum) + " copied)";
                    this.labelTransferRate.Text = "Calculating...";
                }
            }
            catch (InvalidOperationException) { }
            return(this);
        }
예제 #22
0
        public Conclusion Memboot(Tasker tasker, Object syncObject = null)
        {
            // load appropriate kernel
            byte[] kernel;
            if (stockKernel != null && stockKernel.Length > 0)
            {
                kernel = stockKernel.ToArray();
            }
            else
            {
                stockKernel = null; // double-safety
                kernel      = hakchi.GetMembootImage().ToArray();
            }

            tasker.SetStatus(Resources.Membooting);
            if (hakchi.Shell.IsOnline)
            {
                // override arguments
                string addedArgs = ConfigIni.Instance.ForceClovershell ? " hakchi-clovershell" : "";

                // skip to built-in recovery if running latest version
                if (stockKernel == null && hakchi.CanInteract && !hakchi.SystemEligibleForRootfsUpdate())
                {
                    if (hakchi.Shell.Execute("[ -e /bin/detached ]") == 0) // 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
            {
                // check and adjust kernel size
                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 (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");
                        }
                    });
                }

                // 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);
        }
예제 #23
0
        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);
        }
예제 #24
0
        public Tasker.Conclusion SyncOriginalGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.ResettingOriginalGames);
            tasker.SetStatusImage(Resources.sign_sync);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.ResettingOriginalGames);

            string desktopEntriesArchiveFile = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "desktop_entries.tar");
            string originalGamesPath         = Path.Combine(Program.BaseDirectoryExternal, "games_originals");

            if (!Directory.Exists(originalGamesPath))
            {
                Directory.CreateDirectory(originalGamesPath);
            }

            if (!File.Exists(desktopEntriesArchiveFile))
            {
                throw new FileLoadException("desktop_entries.tar data file was deleted, cannot sync original games.");
            }

            try
            {
                var defaultGames = ResetAllOriginalGames ? NesApplication.AllDefaultGames.Select(g => g.Key) : NesApplication.CurrentDefaultGames;
                using (var extractor = ArchiveFactory.Open(desktopEntriesArchiveFile))
                    using (var reader = extractor.ExtractAllEntries())
                    {
                        int i = 0;
                        while (reader.MoveToNextEntry())
                        {
                            if (reader.Entry.IsDirectory)
                            {
                                continue;
                            }

                            var code = Path.GetFileNameWithoutExtension(reader.Entry.Key);
                            if (!defaultGames.Contains(code))
                            {
                                continue;
                            }

                            var ext = Path.GetExtension(reader.Entry.Key).ToLower();
                            if (ext != ".desktop") // sanity check
                            {
                                throw new FileLoadException($"invalid file \"{reader.Entry.Key}\" found in desktop_entries.tar data file.");
                            }

                            string path       = Path.Combine(originalGamesPath, code);
                            string outputFile = Path.Combine(path, code + ".desktop");
                            bool   exists     = File.Exists(outputFile);

                            if (exists && !NonDestructiveSync)
                            {
                                Shared.EnsureEmptyDirectory(path);
                                Thread.Sleep(0);
                            }

                            if (!exists || !NonDestructiveSync)
                            {
                                Directory.CreateDirectory(path);

                                // extract .desktop file from archive
                                using (var o = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
                                {
                                    reader.WriteEntryTo(o);
                                    o.Flush();
                                    if (!this.ResetAllOriginalGames && !ConfigIni.Instance.OriginalGames.Contains(code))
                                    {
                                        ConfigIni.Instance.OriginalGames.Add(code);
                                    }
                                }

                                // create game temporarily to perform cover search
                                Trace.WriteLine(string.Format($"Resetting game \"{NesApplication.AllDefaultGames[code].Name}\"."));
                                var game = NesApplication.FromDirectory(path);
                                game.FindCover(code + ".desktop");
                                game.Save();
                            }

                            tasker.SetProgress(++i, defaultGames.Count());
                        }
                    }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Error synchronizing original games " + ex.Message + ex.StackTrace);
                tasker.ShowError(ex, Resources.ErrorRestoringAllOriginalGames);
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #25
0
        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.ArchiveFileNames)
                            {
                                var e = Path.GetExtension(f).ToLower();
                                if (e == ".desktop")
                                {
                                    gameFilesInArchive.Clear();
                                    gameFilesInArchive.Add(f);
                                    break;
                                }
                                else if (CoreCollection.Extensions.Contains(e))
                                {
                                    gameFilesInArchive.Add(f);
                                }
                            }
                            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))
                    {
                        Debug.WriteLine(ex.InnerException.Message + ex.InnerException.StackTrace);
                        tasker.ShowError(ex.InnerException, Path.GetFileName(sourceFileName));
                    }
                    else
                    {
                        Debug.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);
        }
예제 #26
0
        public Tasker.Conclusion UpdateListView(Tasker tasker, Object syncObject = null)
        {
            if (tasker.HostForm.Disposing)
            {
                return(Tasker.Conclusion.Abort);
            }
            if (tasker.HostForm.InvokeRequired)
            {
                return((Tasker.Conclusion)tasker.HostForm.Invoke(new Func <Tasker, Object, Tasker.Conclusion>(UpdateListView), new object[] { tasker, syncObject }));
            }
            if (addedApps != null)
            {
                tasker.SetTitle(Resources.UpdatingList);

                // show select core dialog if applicable
                var unknownApps = new List <NesApplication>();
                foreach (var app in addedApps)
                {
                    if (app.Metadata.AppInfo.Unknown)
                    {
                        unknownApps.Add(app);
                    }
                }
                if (unknownApps.Count > 0)
                {
                    using (SelectCoreDialog selectCoreDialog = new SelectCoreDialog())
                    {
                        selectCoreDialog.Games.AddRange(unknownApps);
                        selectCoreDialog.ShowDialog(tasker.HostForm);
                    }
                }

                // show select cover dialog if applicable
                unknownApps.Clear();
                foreach (var app in addedApps)
                {
                    if (!app.CoverArtMatchSuccess && app.CoverArtMatches.Any())
                    {
                        unknownApps.Add(app);
                    }
                }
                if (unknownApps.Count > 0)
                {
                    using (SelectCoverDialog selectCoverDialog = new SelectCoverDialog())
                    {
                        selectCoverDialog.Games.AddRange(unknownApps);
                        selectCoverDialog.ShowDialog(tasker.HostForm);
                    }
                }

                // update list view
                try
                {
                    listViewGames.BeginUpdate();
                    foreach (ListViewItem item in listViewGames.Items)
                    {
                        item.Selected = false;
                    }

                    // add games, only new ones
                    var newApps         = addedApps.Distinct(new NesApplication.NesAppEqualityComparer());
                    var newCodes        = from app in newApps select app.Code;
                    var oldAppsReplaced = from app in listViewGames.Items.Cast <ListViewItem>().ToArray()
                                          where (app.Tag is NesApplication) && newCodes.Contains((app.Tag as NesApplication).Code)
                                          select app;

                    // find "new apps" group
                    ListViewGroup newGroup = null;
                    if (listViewGames.Groups.Count > 0)
                    {
                        newGroup = listViewGames.Groups.OfType <ListViewGroup>().Where(group => group.Header == Resources.ListCategoryNew).FirstOrDefault();
                    }

                    int i = 0, max = newApps.Count() + oldAppsReplaced.Count();
                    foreach (var replaced in oldAppsReplaced)
                    {
                        listViewGames.Items.Remove(replaced);
                        tasker.SetProgress(++i, max);
                    }
                    foreach (var newApp in newApps)
                    {
                        var item = new ListViewItem(newApp.Name);
                        item.Group    = newGroup;
                        item.Tag      = newApp;
                        item.Selected = true;
                        item.Checked  = true;
                        listViewGames.Items.Add(item);
                        tasker.SetProgress(++i, max);
                    }
                }
                finally
                {
                    listViewGames.EndUpdate();
                }
            }
            return(Tasker.Conclusion.Success);
        }
예제 #27
0
        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);
                hakchi.Shell.Execute("/squashtools/sfdisk /dev/mmcblk0", new MemoryStream(Encoding.ASCII.GetBytes("128M,,L\n")), splitStream, splitStream, 0, true);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #28
0
        public Tasker.Conclusion SyncOriginalGames(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.ResettingOriginalGames);
            tasker.SetStatusImage(Resources.sign_sync);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.ResettingOriginalGames);

            string desktopEntriesArchiveFile = Path.Combine(Path.Combine(Program.BaseDirectoryInternal, "data"), "desktop_entries.7z");
            string originalGamesPath         = Path.Combine(Program.BaseDirectoryExternal, "games_originals");
            var    selectedGames             = ConfigIni.Instance.SelectedGames;

            if (!Directory.Exists(originalGamesPath))
            {
                Directory.CreateDirectory(originalGamesPath);
            }

            if (!File.Exists(desktopEntriesArchiveFile))
            {
                throw new FileLoadException("desktop_entries.7z data file was deleted, cannot sync original games.");
            }

            try
            {
                var defaultGames = ResetAllOriginalGames ? NesApplication.AllDefaultGames : NesApplication.DefaultGames;

                using (var szExtractor = new SevenZipExtractor(desktopEntriesArchiveFile))
                {
                    int i = 0;
                    foreach (var f in szExtractor.ArchiveFileNames)
                    {
                        var code  = Path.GetFileNameWithoutExtension(f);
                        var query = defaultGames.Where(g => g.Code == code);

                        if (query.Count() != 1)
                        {
                            continue;
                        }

                        var ext = Path.GetExtension(f).ToLower();
                        if (ext != ".desktop") // sanity check
                        {
                            throw new FileLoadException($"invalid file \"{f}\" found in desktop_entries.7z data file.");
                        }

                        string path       = Path.Combine(originalGamesPath, code);
                        string outputFile = Path.Combine(path, code + ".desktop");
                        bool   exists     = File.Exists(outputFile);

                        if (exists && !NonDestructiveSync)
                        {
                            Shared.EnsureEmptyDirectory(path);
                            Thread.Sleep(0);
                        }

                        if (!exists || !NonDestructiveSync)
                        {
                            Directory.CreateDirectory(path);

                            // extract .desktop file from archive
                            using (var o = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
                            {
                                szExtractor.ExtractFile(f, o);
                                o.Flush();
                                if (!this.ResetAllOriginalGames && !selectedGames.Contains(code))
                                {
                                    selectedGames.Add(code);
                                }
                            }

                            // create game temporarily to perform cover search
                            Debug.WriteLine(string.Format("Resetting game \"{0}\".", query.Single().Name));
                            var game = NesApplication.FromDirectory(path);
                            game.FindCover(code + ".desktop");
                            game.Save();
                        }

                        tasker.SetProgress(++i, defaultGames.Length);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error synchronizing original games " + ex.Message + ex.StackTrace);
                tasker.ShowError(ex, Resources.ErrorRestoringAllOriginalGames);
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #29
0
        public Tasker.Conclusion UpdateLocal(Tasker tasker, Object SyncObject = null)
        {
            tasker.SetTitle(Resources.UpdatingLocalCache);
            tasker.SetStatusImage(Resources.sign_sync);
            tasker.SetProgress(-1, -1, Tasker.State.Running, Resources.UpdatingLocalCache);

            var shell = hakchi.Shell;

            if (!shell.IsOnline)
            {
                return(Tasker.Conclusion.Abort);
            }

            string gamesCloverPath = shell.ExecuteSimple("hakchi eval 'echo \"$squashfs$gamepath\"'", 2000, true);
            string cachePath       = Path.Combine(Program.BaseDirectoryExternal, "games_cache");

            try
            {
                var reply = shell.ExecuteSimple($"[ -d \"{gamesCloverPath}\" ] && echo YES || echo NO");
                if (reply == "NO")
                {
                    gamesCloverPath = hakchi.GamesSquashFsPath;
                    reply           = shell.ExecuteSimple($"[ -d \"{gamesCloverPath}\" ] && echo YES || echo NO");
                    if (reply == "NO")
                    {
                        throw new Exception("Unable to update local cache. games directory not accessible");
                    }
                }

                var list = shell.ExecuteSimple($"ls \"{gamesCloverPath}\" -p -1 | grep '/'").Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
                int i    = 0;
                foreach (var folder in list)
                {
                    string gameCode = folder.Substring(0, folder.Length - 1);
                    string gamePath = Path.Combine(cachePath, gameCode);
                    if (!Directory.Exists(gamePath))
                    {
                        try
                        {
                            Directory.CreateDirectory(gamePath);
                            using (var tar = new MemoryStream())
                            {
                                string cmd = $"cd {gamesCloverPath}/{gameCode} && tar -c *";
                                shell.Execute(cmd, null, tar, null, 10000, true);
                                tar.Seek(0, SeekOrigin.Begin);
                                using (var extractorTar = SharpCompress.Archives.Tar.TarArchive.Open(tar))
                                    extractorTar.WriteToDirectory(gamePath, new SharpCompress.Common.ExtractionOptions()
                                    {
                                        ExtractFullPath = true, Overwrite = true
                                    });
                            }
                            ++LoadedGames;
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine(ex.Message + ex.StackTrace);
                            if (Directory.Exists(gamePath))
                            {
                                Trace.WriteLine($"Exception occured while loading data from NES/SNES mini, deleting \"{gamePath}\".");
                                Directory.Delete(gamePath, true);
                            }
                        }
                    }

                    tasker.SetProgress(++i, list.Length);
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.Message + ex.StackTrace);
                return(Tasker.Conclusion.Error);
            }

            return(Tasker.Conclusion.Success);
        }
예제 #30
0
        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 != null && 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);
        }