예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 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);
 }
예제 #5
0
        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);
        }
예제 #6
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);
                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);
        }
예제 #7
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);
        }
예제 #8
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.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);
        }
예제 #9
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 (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);
        }
예제 #10
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);
        }
예제 #11
0
 public Tasker.Conclusion BuildFiles(Tasker tasker, Object syncObject = null)
 {
     tasker.SetStatus(Resources.AddingGames);
     AddMenu(Games, originalGames, copyMode, localGameSet, stats);
     return(Tasker.Conclusion.Success);
 }
예제 #12
0
        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);
        }
예제 #13
0
파일: Tasker.cs 프로젝트: yeager/Hakchi2-CE
 public static Tasker SetStatus(this Tasker tasker, Tasker.State state, string status)
 {
     tasker.SetState(state);
     tasker.SetStatus(status);
     return(tasker);
 }
예제 #14
0
 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);
 }
예제 #15
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.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);
        }
예제 #16
0
 public static Tasker.Conclusion SyncConfig(Tasker tasker = null, Object syncObject = null)
 {
     tasker?.SetStatus(Resources.UploadingConfig);
     hakchi.SyncConfig(ConfigIni.GetConfigDictionary());
     return(Tasker.Conclusion.Success);
 }
예제 #17
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.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);
        }