public List <HawkFileArchiveItem> Scan()
        {
            var ret = new List <HawkFileArchiveItem>();

            for (int i = 0; i < _extractor.ArchiveFileData.Count; i++)
            {
                var afd = _extractor.ArchiveFileData[i];
                if (afd.IsDirectory)
                {
                    continue;
                }

                var ai = new HawkFileArchiveItem
                {
                    Name = HawkFile.Util_FixArchiveFilename(afd.FileName),
                    Size = (long)afd.Size, ArchiveIndex = i, Index = ret.Count
                };

                ret.Add(ai);
            }

            return(ret);
        }
Ejemplo n.º 2
0
        private IMovie PreLoadMovieFile(HawkFile hf, bool force)
        {
            var movie = MovieService.Get(hf.CanonicalFullPath);

            try
            {
                movie.PreLoadHeaderAndLength(hf);

                // Don't do this from browse
                if (movie.Hash == Global.Game.Hash ||
                    Global.Config.PlayMovie_MatchHash == false || force)
                {
                    return(movie);
                }
            }
            catch (Exception ex)
            {
                // TODO: inform the user that a movie failed to parse in some way
                Console.WriteLine(ex.Message);
            }

            return(null);
        }
Ejemplo n.º 3
0
        private int?AddMovieToList(string filename, bool force)
        {
            using (var file = new HawkFile(filename))
            {
                if (!file.Exists)
                {
                    return(null);
                }

                //System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start();
                var movie = PreLoadMovieFile(file, force);
                if (movie == null)
                {
                    return(null);
                }
                //watch.Stop(); Console.WriteLine("[{0}] {1}",watch.ElapsedMilliseconds,Path.GetFileName(filename));

                int?index;
                lock (_movieList)
                {
                    //need to check IsDuplicateOf within the lock
                    index = IsDuplicateOf(filename);
                    if (index.HasValue)
                    {
                        return(index);
                    }

                    _movieList.Add(movie);
                    index = _movieList.Count - 1;
                }

                _sortReverse = false;
                _sortedCol   = string.Empty;

                return(index);
            }
        }
Ejemplo n.º 4
0
        private void buttonPal_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                InitialDirectory = PathManager.MakeAbsolutePath(Global.Config.PathEntries["NES", "Palettes"].Path, "NES"),
                Filter           = "Palette Files (.pal)|*.PAL|All Files (*.*)|*.*",
                RestoreDirectory = true
            };

            var result = ofd.ShowDialog();

            if (result != DialogResult.OK)
            {
                return;
            }
            HawkFile palette = new HawkFile(ofd.FileName);

            if (palette != null && palette.Exists)
            {
                var data = Emulation.Cores.Nintendo.NES.Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(palette.Name));
                Settings.SetNesHawkPalette(data);
                SetPaletteImage();
            }
        }
Ejemplo n.º 5
0
        private byte[,] ResolvePalette(bool showmsg = false)
        {
            if (AutoLoadPalette.Checked)             // checkbox checked: try to load palette from file
            {
                if (PalettePath.Text.Length > 0)
                {
                    HawkFile palette = new HawkFile(PalettePath.Text);

                    if (palette != null && palette.Exists)
                    {
                        var data = Palettes.Load_FCEUX_Palette(HawkFile.ReadAllBytes(palette.Name));
                        if (showmsg)
                        {
                            GlobalWin.OSD.AddMessage("Palette file loaded: " + palette.Name);
                        }
                        return(data);
                    }
                    else
                    {
                        return(settings.Palette);
                    }
                }
                else                 // no filename: interpret this as "reset to default"
                {
                    if (showmsg)
                    {
                        GlobalWin.OSD.AddMessage("Standard Palette set");
                    }
                    return((byte[, ])Palettes.QuickNESPalette.Clone());
                }
            }
            else             // checkbox unchecked: we're reusing whatever palette was set
            {
                return(settings.Palette);
            }
        }
Ejemplo n.º 6
0
        public bool LoadRom(string path, CoreComm nextComm, bool forceAccurateCore = false)         // forceAccurateCore is currently just for Quicknes vs Neshawk but could be used for other situations
        {
            bool cancel = false;

            if (path == null)
            {
                return(false);
            }

            using (var file = new HawkFile())
            {
                var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC", "GBA" };

                // lets not use this unless we need to
                // file.NonArchiveExtensions = romExtensions;
                file.Open(path);

                // if the provided file doesnt even exist, give up!
                if (!file.Exists)
                {
                    return(false);
                }

                // try binding normal rom extensions first
                if (!file.IsBound)
                {
                    file.BindSoleItemOf(romExtensions);
                }

                // if we have an archive and need to bind something, then pop the dialog
                if (file.IsArchive && !file.IsBound)
                {
                    int?result = HandleArchive(file);
                    if (result.HasValue)
                    {
                        file.BindArchiveMember(result.Value);
                    }
                    else
                    {
                        return(false);
                    }
                }

                // set this here so we can see what file we tried to load even if an error occurs
                CanonicalFullPath = file.CanonicalFullPath;

                IEmulator nextEmulator = null;
                RomGame   rom          = null;
                GameInfo  game         = null;

                try
                {
                    var ext = file.Extension.ToLower();
                    if (ext == ".m3u")
                    {
                        //HACK ZONE - currently only psx supports m3u
                        M3U_File m3u;
                        using (var sr = new StreamReader(path))
                            m3u = M3U_File.Read(sr);
                        if (m3u.Entries.Count == 0)
                        {
                            throw new InvalidOperationException("Can't load an empty M3U");
                        }
                        //load discs for all the m3u
                        m3u.Rebase(Path.GetDirectoryName(path));
                        List <Disc>   discs     = new List <Disc>();
                        List <string> discNames = new List <string>();
                        foreach (var e in m3u.Entries)
                        {
                            Disc   disc     = null;
                            string discPath = e.Path;
                            string discExt  = Path.GetExtension(discPath).ToLower();
                            if (discExt == ".iso")
                            {
                                disc = Disc.FromIsoPath(discPath);
                            }
                            if (discExt == ".cue")
                            {
                                disc = Disc.FromCuePath(discPath, new CueBinPrefs());
                            }
                            if (discExt == ".ccd")
                            {
                                disc = Disc.FromCCDPath(discPath);
                            }
                            if (disc == null)
                            {
                                throw new InvalidOperationException("Can't load one of the files specified in the M3U");
                            }
                            discNames.Add(Path.GetFileNameWithoutExtension(discPath));
                            discs.Add(disc);
                        }
                        nextEmulator = new Octoshock(nextComm, discs, discNames, null, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                        nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
                        game = new GameInfo {
                            Name = Path.GetFileNameWithoutExtension(file.Name)
                        };
                        game.System = "PSX";
                    }
                    else if (ext == ".iso" || ext == ".cue" || ext == ".ccd")
                    {
                        if (file.IsArchive)
                        {
                            throw new InvalidOperationException("Can't load CD files from archives!");
                        }

                        Disc disc = null;
                        if (ext == ".iso")
                        {
                            disc = Disc.FromIsoPath(path);
                        }
                        if (ext == ".cue")
                        {
                            disc = Disc.FromCuePath(path, new CueBinPrefs());
                        }
                        if (ext == ".ccd")
                        {
                            disc = Disc.FromCCDPath(path);
                        }

                        var hash = disc.GetHash();
                        game = Database.CheckDatabase(hash);
                        if (game == null)
                        {
                            // try to use our wizard methods
                            game = new GameInfo {
                                Name = Path.GetFileNameWithoutExtension(file.Name), Hash = hash
                            };

                            switch (disc.DetectDiscType())
                            {
                            case DiscType.SegaSaturn:
                                game.System = "SAT";
                                break;

                            case DiscType.SonyPSP:
                                game.System = "PSP";
                                break;

                            default:
                            case DiscType.SonyPSX:
                                game.System = "PSX";
                                break;

                            case DiscType.MegaCD:
                                game.System = "GEN";
                                break;

                            case DiscType.TurboCD:
                            case DiscType.UnknownCDFS:
                            case DiscType.UnknownFormat:
                                game.System = "PCECD";
                                break;
                            }
                        }

                        switch (game.System)
                        {
                        case "GEN":
                            var genesis = new GPGX(
                                nextComm, null, disc, GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>());
                            nextEmulator = genesis;
                            break;

                        case "SAT":
                            nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings <Yabause>());
                            break;

                        case "PSP":
                            nextEmulator = new PSP(nextComm, file.Name);
                            break;

                        case "PSX":
                            nextEmulator = new Octoshock(nextComm, new List <Disc>(new[] { disc }), new List <string>(new[] { Path.GetFileNameWithoutExtension(path) }), null, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                            nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
                            break;

                        case "PCE":
                        case "PCECD":
                            nextEmulator = new PCEngine(nextComm, game, disc, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>());
                            break;
                        }
                    }
                    else if (file.Extension.ToLower() == ".xml")
                    {
                        try
                        {
                            var xmlGame = XmlGame.Create(file);                             // if load fails, are we supposed to retry as a bsnes XML????????
                            game = xmlGame.GI;

                            switch (game.System)
                            {
                            case "DGB":
                                var left  = Database.GetGameInfo(xmlGame.Assets["LeftRom"], "left.gb");
                                var right = Database.GetGameInfo(xmlGame.Assets["RightRom"], "right.gb");
                                nextEmulator = new GambatteLink(
                                    nextComm,
                                    left,
                                    xmlGame.Assets["LeftRom"],
                                    right,
                                    xmlGame.Assets["RightRom"],
                                    GetCoreSettings <GambatteLink>(),
                                    GetCoreSyncSettings <GambatteLink>(),
                                    Deterministic);

                                // other stuff todo
                                break;

                            case "AppleII":
                                var assets = xmlGame.Assets.Select(a => Database.GetGameInfo(a.Value, a.Key));
                                var roms   = xmlGame.Assets.Select(a => a.Value);
                                nextEmulator = new AppleII(
                                    nextComm,
                                    assets,
                                    roms,
                                    GetCoreSettings <AppleII>());
                                break;

                            default:
                                return(false);
                            }
                        }
                        catch (Exception ex)
                        {
                            try
                            {
                                // need to get rid of this hack at some point
                                rom = new RomGame(file);
                                ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", String.Empty));                                 // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
                                byte[] romData = null;
                                byte[] xmlData = rom.FileData;

                                game        = rom.GameInfo;
                                game.System = "SNES";

                                var snes = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                nextEmulator = snes;
                            }
                            catch
                            {
                                DoLoadErrorCallback(ex.ToString(), "DGB", LoadErrorType.XML);
                                return(false);
                            }
                        }
                    }
                    else                     // most extensions
                    {
                        rom = new RomGame(file);

                        //hacky for now
                        if (file.Extension.ToLower() == ".exe")
                        {
                            rom.GameInfo.System = "PSX";
                        }

                        if (string.IsNullOrEmpty(rom.GameInfo.System))
                        {
                            // Has the user picked a preference for this extension?
                            if (PreferredPlatformIsDefined(rom.Extension.ToLower()))
                            {
                                rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLower()];
                            }
                            else if (ChoosePlatform != null)
                            {
                                var result = ChoosePlatform(rom);
                                if (!string.IsNullOrEmpty(result))
                                {
                                    rom.GameInfo.System = ChoosePlatform(rom);
                                }
                                else
                                {
                                    cancel = true;
                                }
                            }
                        }

                        game = rom.GameInfo;

                        var isXml = false;

                        // other xml has already been handled
                        if (file.Extension.ToLower() == ".xml")
                        {
                            game.System = "SNES";
                            isXml       = true;
                        }


                        CoreInventory.Core core = null;

                        switch (game.System)
                        {
                        default:
                            core = CoreInventory.Instance[game.System];
                            break;

                        case null:
                            // The user picked nothing in the Core picker
                            break;

                        case "83P":
                            var ti83Bios     = ((CoreFileProvider)nextComm.CoreFileProvider).GetFirmware("TI83", "Rom", true);
                            var ti83BiosPath = ((CoreFileProvider)nextComm.CoreFileProvider).GetFirmwarePath("TI83", "Rom", true);
                            using (var ti83AsHawkFile = new HawkFile())
                            {
                                ti83AsHawkFile.Open(ti83BiosPath);
                                var ti83BiosAsRom = new RomGame(ti83AsHawkFile);
                                var ti83          = new TI83(nextComm, ti83BiosAsRom.GameInfo, ti83Bios, GetCoreSettings <TI83>());
                                ti83.LinkPort.SendFileToCalc(File.OpenRead(path), false);
                                nextEmulator = ti83;
                            }
                            break;

                        case "SNES":
                            if (Global.Config.SNES_InSnes9x && VersionInfo.DeveloperBuild)
                            {
                                core = CoreInventory.Instance["SNES", "Snes9x"];
                            }
                            else
                            {
                                // need to get rid of this hack at some point
                                ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", String.Empty));                                         // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
                                var romData = isXml ? null : rom.FileData;
                                var xmlData = isXml ? rom.FileData : null;
                                var snes    = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                nextEmulator = snes;
                            }

                            break;

                        case "NES":
                            if (!Global.Config.NES_InQuickNES || forceAccurateCore)
                            {
                                core = CoreInventory.Instance["NES", "NesHawk"];
                            }
                            else
                            {
                                core = CoreInventory.Instance["NES", "QuickNes"];
                            }

                            break;

                        case "GB":
                        case "GBC":
                            if (!Global.Config.GB_AsSGB)
                            {
                                core = CoreInventory.Instance["GB", "Gambatte"];
                            }
                            else
                            {
                                try
                                {
                                    game.System = "SNES";
                                    game.AddOption("SGB");
                                    var snes = new LibsnesCore(game, rom.FileData, Deterministic, null, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                    nextEmulator = snes;
                                }
                                catch
                                {
                                    // failed to load SGB bios or game does not support SGB mode.
                                    // To avoid catch-22, disable SGB mode
                                    Global.Config.GB_AsSGB = false;
                                    throw;
                                }
                            }

                            break;

                        case "A78":
                            var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
                            nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath);
                            break;

                        case "C64":
                            var c64 = new C64(nextComm, game, rom.RomData, rom.Extension);
                            nextEmulator = c64;
                            break;

                        case "AppleII":
                            var appleII = new AppleII(nextComm, game, rom.RomData, rom.Extension);
                            nextEmulator = appleII;
                            break;

                        case "GBA":
                            //core = CoreInventory.Instance["GBA", "Meteor"];
                            core = CoreInventory.Instance["GBA", "VBA-Next"];
                            break;

                        case "PSX":
                            nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                            nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
                            break;

                        case "DEBUG":
                            if (VersionInfo.DeveloperBuild)
                            {
                                nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData);
                            }

                            break;
                        }

                        if (core != null)
                        {
                            // use coreinventory
                            nextEmulator = core.Create(nextComm, game, rom.RomData, rom.FileData, Deterministic, GetCoreSettings(core.Type), GetCoreSyncSettings(core.Type));
                        }
                    }

                    if (nextEmulator == null)
                    {
                        if (!cancel)
                        {
                            DoLoadErrorCallback("No core could load the rom.", null);
                        }
                        return(false);
                    }
                }
                catch (Exception ex)
                {
                    string system = null;
                    if (game != null)
                    {
                        system = game.System;
                    }

                    // all of the specific exceptions we're trying to catch here aren't expected to have inner exceptions,
                    // so drill down in case we got a TargetInvocationException or something like that
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    // Specific hack here, as we get more cores of the same system, this isn't scalable
                    if (ex is UnsupportedGameException)
                    {
                        if (system == "NES")
                        {
                            DoMessageCallback("Unable to use quicknes, using NESHawk instead");
                        }

                        return(LoadRom(path, nextComm, forceAccurateCore: true));
                    }
                    else if (ex is MissingFirmwareException)
                    {
                        DoLoadErrorCallback(ex.Message, system, LoadErrorType.MissingFirmware);
                    }
                    else if (ex is CGBNotSupportedException)
                    {
                        // Note: GB as SGB was set to false by this point, otherwise we would want to do it here
                        DoMessageCallback("Failed to load a GB rom in SGB mode.  Disabling SGB Mode.");
                        return(LoadRom(path, nextComm));
                    }
                    else
                    {
                        DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system);
                    }

                    return(false);
                }

                Rom            = rom;
                LoadedEmulator = nextEmulator;
                Game           = game;
                return(true);
            }
        }
Ejemplo n.º 7
0
        protected override void RunImport()
        {
            Result.Movie.HeaderEntries[HeaderKeys.Core] = CoreNames.Bsnes;

            var hf = new HawkFile(SourceFile.FullName);

            // .LSMV movies are .zip files containing data files.
            if (!hf.IsArchive)
            {
                Result.Errors.Add("This is not an archive.");
                return;
            }

            var ss = new LibsnesCore.SnesSyncSettings
            {
                LeftPort  = LibsnesControllerDeck.ControllerType.Gamepad,
                RightPort = LibsnesControllerDeck.ControllerType.Gamepad
            };

            _deck = new LibsnesControllerDeck(ss);

            string platform = "SNES";

            foreach (var item in hf.ArchiveItems)
            {
                if (item.Name == "authors")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream     = hf.GetStream();
                    string authors    = Encoding.UTF8.GetString(stream.ReadAllBytes());
                    string authorList = "";
                    string authorLast = "";
                    using (var reader = new StringReader(authors))
                    {
                        string line;

                        // Each author is on a different line.
                        while ((line = reader.ReadLine()) != null)
                        {
                            string author = line.Trim();
                            if (author != "")
                            {
                                if (authorLast != "")
                                {
                                    authorList += $"{authorLast}, ";
                                }

                                authorLast = author;
                            }
                        }
                    }

                    if (authorList != "")
                    {
                        authorList += "and ";
                    }

                    if (authorLast != "")
                    {
                        authorList += authorLast;
                    }

                    Result.Movie.HeaderEntries[HeaderKeys.Author] = authorList;
                    hf.Unbind();
                }
                else if (item.Name == "coreversion")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream      = hf.GetStream();
                    string coreVersion = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.Comments.Add($"CoreOrigin {coreVersion}");
                    hf.Unbind();
                }
                else if (item.Name == "gamename")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream   = hf.GetStream();
                    string gameName = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries[HeaderKeys.GameName] = gameName;
                    hf.Unbind();
                }
                else if (item.Name == "gametype")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream   = hf.GetStream();
                    string gametype = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();

                    // TODO: Handle the other types.
                    switch (gametype)
                    {
                    case "gdmg":
                        platform = "GB";
                        break;

                    case "ggbc":
                    case "ggbca":
                        platform = "GBC";
                        break;

                    case "sgb_ntsc":
                    case "sgb_pal":
                        platform       = "SNES";
                        Config.GbAsSgb = true;
                        break;
                    }

                    bool pal = gametype == "snes_pal" || gametype == "sgb_pal";
                    Result.Movie.HeaderEntries[HeaderKeys.Pal] = pal.ToString();
                    hf.Unbind();
                }
                else if (item.Name == "input")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream = hf.GetStream();
                    string input  = Encoding.UTF8.GetString(stream.ReadAllBytes());

                    int lineNum = 0;
                    using (var reader = new StringReader(input))
                    {
                        lineNum++;
                        string line;
                        while ((line = reader.ReadLine()) != null)
                        {
                            if (line == "")
                            {
                                continue;
                            }

                            // Insert an empty frame in lsmv snes movies
                            // https://github.com/TASVideos/BizHawk/issues/721
                            // Both emulators send the input to bsnes core at the same V interval, but:
                            // lsnes' frame boundary occurs at V = 241, after which the input is read;
                            // BizHawk's frame boundary is just before automatic polling;
                            // This isn't a great place to add this logic but this code is a mess
                            if (lineNum == 1 && platform == "SNES")
                            {
                                // Note that this logic assumes the first non-empty log entry is a valid input log entry
                                // and that it is NOT a subframe input entry.  It seems safe to assume subframe input would not be on the first line
                                Result.Movie.AppendFrame(EmptyLmsvFrame());
                            }

                            ImportTextFrame(line, platform);
                        }
                    }

                    hf.Unbind();
                }
                else if (item.Name.StartsWith("moviesram."))
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream    = hf.GetStream();
                    byte[] movieSram = stream.ReadAllBytes();
                    if (movieSram.Length != 0)
                    {
                        Result.Errors.Add("Movies that begin with SRAM are not supported.");
                        hf.Unbind();
                        return;
                    }
                }
                else if (item.Name == "port1")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream = hf.GetStream();
                    string port1  = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries["port1"] = port1;
                    ss.LeftPort = LibsnesControllerDeck.ControllerType.Gamepad;
                    _deck       = new LibsnesControllerDeck(ss);
                    hf.Unbind();
                }
                else if (item.Name == "port2")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream = hf.GetStream();
                    string port2  = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries["port2"] = port2;
                    ss.RightPort = LibsnesControllerDeck.ControllerType.Gamepad;
                    _deck        = new LibsnesControllerDeck(ss);
                    hf.Unbind();
                }
                else if (item.Name == "projectid")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream    = hf.GetStream();
                    string projectId = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries["ProjectID"] = projectId;
                    hf.Unbind();
                }
                else if (item.Name == "rerecords")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream    = hf.GetStream();
                    string rerecords = Encoding.UTF8.GetString(stream.ReadAllBytes());
                    int    rerecordCount;

                    // Try to parse the re-record count as an integer, defaulting to 0 if it fails.
                    try
                    {
                        rerecordCount = int.Parse(rerecords);
                    }
                    catch
                    {
                        rerecordCount = 0;
                    }

                    Result.Movie.Rerecords = (ulong)rerecordCount;
                    hf.Unbind();
                }
                else if (item.Name.EndsWith(".sha256"))
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream = hf.GetStream();
                    string rom    = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    int    pos    = item.Name.LastIndexOf(".sha256");
                    string name   = item.Name.Substring(0, pos);
                    Result.Movie.HeaderEntries[$"SHA256_{name}"] = rom;
                    hf.Unbind();
                }
                else if (item.Name == "savestate")
                {
                    Result.Errors.Add("Movies that begin with a savestate are not supported.");
                    return;
                }
                else if (item.Name == "subtitles")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream    = hf.GetStream();
                    string subtitles = Encoding.UTF8.GetString(stream.ReadAllBytes());
                    using (var reader = new StringReader(subtitles))
                    {
                        string line;
                        while ((line = reader.ReadLine()) != null)
                        {
                            var subtitle = ImportTextSubtitle(line);
                            if (!string.IsNullOrEmpty(subtitle))
                            {
                                Result.Movie.Subtitles.AddFromString(subtitle);
                            }
                        }
                    }

                    hf.Unbind();
                }
                else if (item.Name == "starttime.second")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream      = hf.GetStream();
                    string startSecond = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries["StartSecond"] = startSecond;
                    hf.Unbind();
                }
                else if (item.Name == "starttime.subsecond")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream         = hf.GetStream();
                    string startSubSecond = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.HeaderEntries["StartSubSecond"] = startSubSecond;
                    hf.Unbind();
                }
                else if (item.Name == "systemid")
                {
                    hf.BindArchiveMember(item.Index);
                    var    stream   = hf.GetStream();
                    string systemId = Encoding.UTF8.GetString(stream.ReadAllBytes()).Trim();
                    Result.Movie.Comments.Add($"{EmulationOrigin} {systemId}");
                    hf.Unbind();
                }
            }

            Result.Movie.HeaderEntries[HeaderKeys.Platform] = platform;
            Result.Movie.SyncSettingsJson = ConfigService.SaveWithType(ss);
            Config.PreferredCores["SNES"] = CoreNames.Bsnes;             // TODO: convert to snes9x if it is the user's preference
        }
Ejemplo n.º 8
0
        public static XmlGame Create(HawkFile f)
        {
            try
            {
                var x = new XmlDocument();
                x.Load(f.GetStream());
                var y = x.SelectSingleNode("./BizHawk-XMLGame");
                if (y == null)
                {
                    return(null);
                }

                var ret = new XmlGame
                {
                    GI =
                    {
                        System = y.Attributes["System"].Value,
                        Name   = y.Attributes["Name"].Value,
                        Status = RomStatus.Unknown
                    },
                    Xml = x
                };

                var n = y.SelectSingleNode("./LoadAssets");
                if (n != null)
                {
                    var HashStream    = new MemoryStream();
                    int?OriginalIndex = null;

                    foreach (XmlNode a in n.ChildNodes)
                    {
                        string filename = a.Attributes["FileName"].Value;
                        byte[] data     = new byte[0];
                        if (filename[0] == '|')
                        {
                            // in same archive
                            var ai = f.FindArchiveMember(filename.Substring(1));
                            if (ai != null)
                            {
                                if (OriginalIndex == null)
                                {
                                    OriginalIndex = f.GetBoundIndex();
                                }

                                f.Unbind();
                                f.BindArchiveMember(ai);
                                data = f.GetStream().ReadAllBytes();
                            }
                            else
                            {
                                throw new Exception("Couldn't load XMLGame Asset \"" + filename + "\"");
                            }
                        }
                        else
                        {
                            // relative path
                            var fullpath = Path.GetDirectoryName(f.CanonicalFullPath.Split('|').First()) ?? string.Empty;
                            fullpath = Path.Combine(fullpath, filename.Split('|').First());
                            try
                            {
                                using (var hf = new HawkFile(fullpath))
                                {
                                    if (hf.IsArchive)
                                    {
                                        var archiveItem = hf.ArchiveItems.First(ai => ai.Name == filename.Split('|').Skip(1).First());
                                        hf.Unbind();
                                        hf.BindArchiveMember(archiveItem);
                                        data = hf.GetStream().ReadAllBytes();
                                    }
                                    else
                                    {
                                        data = File.ReadAllBytes(fullpath.Split('|').First());
                                    }
                                }
                            }
                            catch
                            {
                                throw new Exception("Couldn't load XMLGame LoadAsset \"" + filename + "\"");
                            }
                        }

                        ret.Assets.Add(new KeyValuePair <string, byte[]>(filename, data));

                        using (var sha1 = System.Security.Cryptography.SHA1.Create())
                        {
                            sha1.TransformFinalBlock(data, 0, data.Length);
                            HashStream.Write(sha1.Hash, 0, sha1.Hash.Length);
                        }
                    }

                    ret.GI.Hash = HashStream.GetBuffer().HashSHA1(0, (int)HashStream.Length);
                    HashStream.Close();
                    if (OriginalIndex != null)
                    {
                        f.Unbind();
                        f.BindArchiveMember((int)OriginalIndex);
                    }
                }
                else
                {
                    ret.GI.Hash = "0000000000000000000000000000000000000000";
                }

                return(ret);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(ex.ToString());
            }
        }
Ejemplo n.º 9
0
 public RomGame(HawkFile file) : this(file, null)
 {
 }
Ejemplo n.º 10
0
 private void LoadPSF(string path, CoreComm nextComm, HawkFile file, out IEmulator nextEmulator, out RomGame rom, out GameInfo game)
 {
Ejemplo n.º 11
0
        private void RunImportJob(IEnumerable <string> files)
        {
            bool   didSomething = false;
            var    basepath     = PathManager.MakeAbsolutePath(Global.Config.PathEntries.FirmwaresPathFragment, null);
            string errors       = "";

            foreach (var f in files)
            {
                using (var hf = new HawkFile(f))
                {
                    if (hf.IsArchive)
                    {
                        // blech. the worst extraction code in the universe.
                        string        extractpath = $"{Path.GetTempFileName()}.dir";
                        DirectoryInfo di          = Directory.CreateDirectory(extractpath);

                        try
                        {
                            foreach (var ai in hf.ArchiveItems)
                            {
                                hf.BindArchiveMember(ai);
                                var stream = hf.GetStream();
                                var ms     = new MemoryStream();
                                Util.CopyStream(hf.GetStream(), ms, stream.Length);
                                string outfile = ai.Name;
                                string myname  = Path.GetFileName(outfile);
                                outfile = Path.Combine(extractpath, myname);
                                File.WriteAllBytes(outfile, ms.ToArray());
                                hf.Unbind();

                                if (cbAllowImport.Checked || Manager.CanFileBeImported(outfile))
                                {
                                    didSomething |= RunImportJobSingle(basepath, outfile, ref errors);
                                }
                            }
                        }
                        finally
                        {
                            di.Delete(true);
                        }
                    }
                    else
                    {
                        if (cbAllowImport.Checked || Manager.CanFileBeImported(hf.CanonicalFullPath))
                        {
                            didSomething |= RunImportJobSingle(basepath, f, ref errors);
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(errors))
            {
                MessageBox.Show(errors, "Error importing these files");
            }

            if (didSomething)
            {
                DoScan();
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Load Header information only for displaying file information in dialogs such as play movie
        /// TODO - consider not loading the SavestateBinaryBase64Blob key?
        /// </summary>
        public bool PreLoadHeaderAndLength(HawkFile hawkFile)
        {
            Loaded = false;
            var file = new FileInfo(hawkFile.CanonicalFullPath);

            if (file.Exists == false)
            {
                return(false);
            }

            Header.Clear();
            _log.Clear();

            var origStreamPosn = hawkFile.GetStream().Position;

            hawkFile.GetStream().Position = 0;             // Reset to start

            // No using block because we're sharing the stream and need to give it back undisposed.
            var sr = new StreamReader(hawkFile.GetStream());

            for (;;)
            {
                // read to first space (key/value delimeter), or pipe, or EOF
                int first = sr.Read();

                if (first == -1)
                {
                    break;
                }                 // EOF

                if (first == '|') // pipe: begin input log
                {
                    // NOTE - this code is a bit convoluted due to its predating the basic outline of the parser which was upgraded in may 2014
                    var line = '|' + sr.ReadLine();

                    // how many bytes are left, total?
                    long remain = sr.BaseStream.Length - sr.BaseStream.Position;

                    // try to find out whether we use \r\n or \n
                    // but only look for 1K characters.
                    bool usesR = false;
                    for (int i = 0; i < 1024; i++)
                    {
                        int c = sr.Read();
                        if (c == -1)
                        {
                            break;
                        }

                        if (c == '\r')
                        {
                            usesR = true;
                            break;
                        }

                        if (c == '\n')
                        {
                            break;
                        }
                    }

                    int lineLen = line.Length + 1;                     // account for \n
                    if (usesR)
                    {
                        lineLen++;                         // account for \r
                    }

                    _preloadFramecount = (int)(remain / lineLen); // length is remaining bytes / length per line
                    _preloadFramecount++;                         // account for the current line
                    break;
                }
                else
                {
                    // a header line. finish reading key token, to make sure it isn't one of the FORBIDDEN keys
                    var sbLine = new StringBuilder();
                    sbLine.Append((char)first);
                    for (;;)
                    {
                        int c = sr.Read();
                        if (c == -1 || c == '\n' || c == ' ')
                        {
                            break;
                        }

                        sbLine.Append((char)c);
                    }

                    var line = sbLine.ToString();

                    // ignore these suckers, theyre way too big for preloading. seriously, we will get out of memory errors.
                    var skip = line == HeaderKeys.SAVESTATEBINARYBASE64BLOB;

                    if (skip)
                    {
                        // skip remainder of the line
                        sr.DiscardBufferedData();
                        var stream = sr.BaseStream;
                        for (;;)
                        {
                            int c = stream.ReadByte();
                            if (c == -1 || c == '\n')
                            {
                                break;
                            }
                        }

                        // proceed to next line
                        continue;
                    }

                    var remainder = sr.ReadLine();
                    sbLine.Append(' ');
                    sbLine.Append(remainder);
                    line = sbLine.ToString();

                    if (string.IsNullOrWhiteSpace(line) || Header.ParseLineFromFile(line))
                    {
                        continue;
                    }

                    Header.Comments.Add(line);
                }
            }

            hawkFile.GetStream().Position = origStreamPosn;

            return(true);
        }
Ejemplo n.º 13
0
        } = new List <string>();                                                   // TODO: Hack work around, to avoid having to refactor Assets into a object array, should be refactored!

        /// <exception cref="InvalidOperationException">internal error</exception>
        public static XmlGame Create(HawkFile f)
        {
            try
            {
                var x = new XmlDocument();
                x.Load(f.GetStream());
                var y = x.SelectSingleNode("./BizHawk-XMLGame");
                if (y == null)
                {
                    return(null);
                }

                var ret = new XmlGame
                {
                    GI =
                    {
                        System = y.Attributes["System"].Value,
                        Name   = y.Attributes["Name"].Value,
                        Status = RomStatus.Unknown
                    },
                    Xml = x
                };
                string fullPath = "";

                var n = y.SelectSingleNode("./LoadAssets");
                if (n != null)
                {
                    var hashStream    = new MemoryStream();
                    int?originalIndex = null;

                    foreach (XmlNode a in n.ChildNodes)
                    {
                        string filename = a.Attributes["FileName"].Value;
                        byte[] data;
                        if (filename[0] == '|')
                        {
                            // in same archive
                            var ai = f.FindArchiveMember(filename.Substring(1));
                            if (ai != null)
                            {
                                originalIndex ??= f.BoundIndex;
                                f.Unbind();
                                f.BindArchiveMember(ai.Value);
                                data = f.GetStream().ReadAllBytes();
                            }
                            else
                            {
                                throw new Exception($"Couldn't load XMLGame Asset \"{filename}\"");
                            }
                        }
                        else
                        {
                            // relative path
                            fullPath = Path.GetDirectoryName(f.CanonicalFullPath.Split('|').First()) ?? "";
                            fullPath = Path.Combine(fullPath, filename.Split('|').First());
                            try
                            {
                                using var hf = new HawkFile(fullPath);
                                if (hf.IsArchive)
                                {
                                    var archiveItem = hf.ArchiveItems.First(ai => ai.Name == filename.Split('|').Skip(1).First());
                                    hf.Unbind();
                                    hf.BindArchiveMember(archiveItem);
                                    data = hf.GetStream().ReadAllBytes();

                                    filename = filename.Split('|').Skip(1).First();
                                }
                                else
                                {
                                    data = File.ReadAllBytes(fullPath.Split('|').First());
                                }
                            }
                            catch
                            {
                                throw new Exception($"Couldn't load XMLGame LoadAsset \"{filename}\"");
                            }
                        }

                        ret.Assets.Add(new KeyValuePair <string, byte[]>(filename, data));
                        ret.AssetFullPaths.Add(fullPath);
                        var sha1 = SHA1Checksum.Compute(data);
                        hashStream.Write(sha1, 0, sha1.Length);
                    }

                    ret.GI.Hash = SHA1Checksum.ComputeDigestHex(hashStream.GetBufferAsSpan());
                    hashStream.Close();
                    if (originalIndex != null)
                    {
                        f.Unbind();
                        f.BindArchiveMember((int)originalIndex);
                    }
                }
                else
                {
                    ret.GI.Hash = SHA1Checksum.Zero;
                }

                return(ret);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(ex.ToString());
            }
        }
Ejemplo n.º 14
0
        public bool LoadRom(string path, CoreComm nextComm, bool forceAccurateCore = false,
                            int recursiveCount = 0) // forceAccurateCore is currently just for Quicknes vs Neshawk but could be used for other situations
        {
            if (recursiveCount > 1)                 // hack to stop recursive calls from endlessly rerunning if we can't load it
            {
                DoLoadErrorCallback("Failed multiple attempts to load ROM.", "");
                return(false);
            }

            bool cancel = false;

            if (path == null)
            {
                return(false);
            }

            using (var file = new HawkFile())
            {
                //only try mounting a file if a filename was given
                if (!string.IsNullOrEmpty(path))
                {
                    // lets not use this unless we need to
                    // file.NonArchiveExtensions = romExtensions;
                    file.Open(path);

                    // if the provided file doesnt even exist, give up!
                    if (!file.Exists)
                    {
                        return(false);
                    }
                }

                CanonicalFullPath = file.CanonicalFullPath;

                IEmulator nextEmulator = null;
                RomGame   rom          = null;
                GameInfo  game         = null;

                try
                {
                    string ext = null;

                    if (AsLibretro)
                    {
                        string codePathPart = Path.GetFileNameWithoutExtension(nextComm.LaunchLibretroCore);

                        var retro = new LibRetroEmulator(nextComm, nextComm.LaunchLibretroCore);
                        nextEmulator = retro;

                        //kind of dirty.. we need to stash this, and then we can unstash it in a moment, in case the core doesnt fail
                        var oldGame = Global.Game;

                        if (retro.Description.SupportsNoGame && string.IsNullOrEmpty(path))
                        {
                            //must be done before LoadNoGame (which triggers retro_init and the paths to be consumed by the core)
                            //game name == name of core
                            var gameName = codePathPart;
                            Global.Game = game = new GameInfo {
                                Name = gameName, System = "Libretro"
                            };

                            //if we are allowed to run NoGame and we dont have a game, boot up the core that way
                            bool ret = retro.LoadNoGame();

                            Global.Game = oldGame;

                            if (!ret)
                            {
                                DoLoadErrorCallback("LibretroNoGame failed to load. This is weird", "Libretro");
                                retro.Dispose();
                                return(false);
                            }
                        }
                        else
                        {
                            bool ret;

                            //must be done before LoadNoGame (which triggers retro_init and the paths to be consumed by the core)
                            //game name == name of core + extensionless_game_filename
                            var gameName = Path.Combine(codePathPart, Path.GetFileNameWithoutExtension(file.Name));
                            Global.Game = game = new GameInfo {
                                Name = gameName, System = "Libretro"
                            };

                            //if the core requires an archive file, then try passing the filename of the archive
                            //(but do we ever need to actually load the contents of the archive file into ram?)
                            if (retro.Description.NeedsArchives)
                            {
                                if (file.IsArchiveMember)
                                {
                                    throw new InvalidOperationException("Should not have bound file member for libretro block_extract core");
                                }
                                ret = retro.LoadPath(file.FullPathWithoutMember);
                            }
                            else
                            {
                                //otherwise load the data or pass the filename, as requested. but..
                                if (retro.Description.NeedsRomAsPath && file.IsArchiveMember)
                                {
                                    throw new InvalidOperationException("Cannot pass archive member to libretro needs_fullpath core");
                                }

                                if (retro.Description.NeedsRomAsPath)
                                {
                                    ret = retro.LoadPath(file.FullPathWithoutMember);
                                }
                                else
                                {
                                    ret = HandleArchiveBinding(file);
                                    if (ret)
                                    {
                                        ret = retro.LoadData(file.ReadAllBytes());
                                    }
                                }
                            }

                            Global.Game = oldGame;

                            if (!ret)
                            {
                                DoLoadErrorCallback("Libretro failed to load the given file. This is probably due to a core/content mismatch. Moreover, the process is now likely to be hosed. We suggest you restart the program.", "Libretro");
                                retro.Dispose();
                                return(false);
                            }
                        }
                    }
                    else
                    {
                        //if not libretro:

                        //do extension checknig
                        ext = file.Extension.ToLowerInvariant();

                        //do the archive binding we had to skip
                        if (!HandleArchiveBinding(file))
                        {
                            return(false);
                        }
                    }

                    if (string.IsNullOrEmpty(ext))
                    {
                    }
                    else if (ext == ".m3u")
                    {
                        //HACK ZONE - currently only psx supports m3u
                        M3U_File m3u;
                        using (var sr = new StreamReader(path))
                            m3u = M3U_File.Read(sr);
                        if (m3u.Entries.Count == 0)
                        {
                            throw new InvalidOperationException("Can't load an empty M3U");
                        }
                        //load discs for all the m3u
                        m3u.Rebase(Path.GetDirectoryName(path));
                        List <Disc>   discs     = new List <Disc>();
                        List <string> discNames = new List <string>();
                        StringWriter  sw        = new StringWriter();
                        foreach (var e in m3u.Entries)
                        {
                            Disc   disc     = null;
                            string discPath = e.Path;

                            //--- load the disc in a context which will let us abort if it's going to take too long
                            var discMountJob = new DiscMountJob {
                                IN_FromPath = discPath
                            };
                            discMountJob.IN_SlowLoadAbortThreshold = 8;
                            discMountJob.Run();
                            disc = discMountJob.OUT_Disc;

                            if (discMountJob.OUT_SlowLoadAborted)
                            {
                                DoLoadErrorCallback("This disc would take too long to load. Run it through discohawk first, or find a new rip because this one is probably junk", "", LoadErrorType.DiscError);
                                return(false);
                            }

                            if (discMountJob.OUT_ErrorLevel)
                            {
                                throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
                            }

                            if (disc == null)
                            {
                                throw new InvalidOperationException("Can't load one of the files specified in the M3U");
                            }

                            var discName = Path.GetFileNameWithoutExtension(discPath);
                            discNames.Add(discName);
                            discs.Add(disc);

                            var discType = new DiscIdentifier(disc).DetectDiscType();
                            sw.WriteLine("{0}", Path.GetFileName(discPath));
                            if (discType == DiscType.SonyPSX)
                            {
                                string discHash = new DiscHasher(disc).Calculate_PSX_BizIDHash().ToString("X8");
                                game = Database.CheckDatabase(discHash);
                                if (game == null || game.IsRomStatusBad() || game.Status == RomStatus.NotInDatabase)
                                {
                                    sw.WriteLine("Disc could not be identified as known-good. Look for a better rip.");
                                }
                                else
                                {
                                    sw.WriteLine("Disc was identified (99.99% confidently) as known good with disc id hash CRC32:{0:X8}", discHash);
                                    sw.WriteLine("Nonetheless it could be an unrecognized romhack or patched version.");
                                    sw.WriteLine("According to redump.org, the ideal hash for entire disc is: CRC32:{0:X8}", game.GetStringValue("dh"));
                                    sw.WriteLine("The file you loaded hasn't been hashed entirely (it would take too long)");
                                    sw.WriteLine("Compare it with the full hash calculated by the PSX menu's Hash Discs tool");
                                }
                            }
                            else
                            {
                                sw.WriteLine("Not a PSX disc");
                            }
                            sw.WriteLine("-------------------------");
                        }

                        nextEmulator = new Octoshock(nextComm, discs, discNames, null, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                        nextEmulator.CoreComm.RomStatusDetails = sw.ToString();
                        game = new GameInfo {
                            Name = Path.GetFileNameWithoutExtension(file.Name)
                        };
                        game.System = "PSX";
                    }
                    else if (ext == ".iso" || ext == ".cue" || ext == ".ccd")
                    {
                        if (file.IsArchive)
                        {
                            throw new InvalidOperationException("Can't load CD files from archives!");
                        }

                        string discHash = null;

                        //--- load the disc in a context which will let us abort if it's going to take too long
                        var discMountJob = new DiscMountJob {
                            IN_FromPath = path
                        };
                        discMountJob.IN_SlowLoadAbortThreshold = 8;
                        discMountJob.Run();

                        if (discMountJob.OUT_SlowLoadAborted)
                        {
                            DoLoadErrorCallback("This disc would take too long to load. Run it through discohawk first, or find a new rip because this one is probably junk", "", LoadErrorType.DiscError);
                            return(false);
                        }

                        if (discMountJob.OUT_ErrorLevel)
                        {
                            throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
                        }

                        var disc = discMountJob.OUT_Disc;
                        //-----------

                        //TODO - use more sophisticated IDer
                        var discType = new DiscIdentifier(disc).DetectDiscType();
                        if (discType == DiscType.SonyPSX)
                        {
                            discHash = new DiscHasher(disc).Calculate_PSX_BizIDHash().ToString("X8");
                        }
                        else
                        {
                            discHash = new DiscHasher(disc).OldHash();
                        }

                        game = Database.CheckDatabase(discHash);
                        if (game == null)
                        {
                            // try to use our wizard methods
                            game = new GameInfo {
                                Name = Path.GetFileNameWithoutExtension(file.Name), Hash = discHash
                            };

                            switch (new DiscIdentifier(disc).DetectDiscType())
                            {
                            case DiscType.SegaSaturn:
                                game.System = "SAT";
                                break;

                            case DiscType.SonyPSP:
                                game.System = "PSP";
                                break;

                            default:
                            case DiscType.SonyPSX:
                                game.System = "PSX";
                                break;

                            case DiscType.MegaCD:
                                game.System = "GEN";
                                break;

                            case DiscType.AudioDisc:
                            case DiscType.TurboCD:
                            case DiscType.UnknownCDFS:
                            case DiscType.UnknownFormat:
                                game.System = "PCECD";
                                break;
                            }
                        }

                        switch (game.System)
                        {
                        case "GEN":
                            var genesis = new GPGX(
                                nextComm, null, disc, GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>());
                            nextEmulator = genesis;
                            break;

                        case "SAT":
                            nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings <Yabause>());
                            break;

                        case "PSP":
                            nextEmulator = new PSP(nextComm, file.Name);
                            break;

                        case "PSX":
                            nextEmulator = new Octoshock(nextComm, new List <Disc>(new[] { disc }), new List <string>(new[] { Path.GetFileNameWithoutExtension(path) }), null, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                            if (game.IsRomStatusBad() || game.Status == RomStatus.NotInDatabase)
                            {
                                nextEmulator.CoreComm.RomStatusDetails = "Disc could not be identified as known-good. Look for a better rip.";
                            }
                            else
                            {
                                StringWriter sw = new StringWriter();
                                sw.WriteLine("Disc was identified (99.99% confidently) as known good with disc id hash CRC32:{0:X8}", discHash);
                                sw.WriteLine("Nonetheless it could be an unrecognized romhack or patched version.");
                                sw.WriteLine("According to redump.org, the ideal hash for entire disc is: CRC32:{0:X8}", game.GetStringValue("dh"));
                                sw.WriteLine("The file you loaded hasn't been hashed entirely (it would take too long)");
                                sw.WriteLine("Compare it with the full hash calculated by the PSX menu's Hash Discs tool");
                                nextEmulator.CoreComm.RomStatusDetails = sw.ToString();
                            }
                            break;

                        case "PCE":
                        case "PCECD":
                            nextEmulator = new PCEngine(nextComm, game, disc, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>());
                            break;
                        }
                    }
                    else if (file.Extension.ToLowerInvariant() == ".xml")
                    {
                        try
                        {
                            var xmlGame = XmlGame.Create(file);                             // if load fails, are we supposed to retry as a bsnes XML????????
                            game = xmlGame.GI;

                            switch (game.System)
                            {
                            case "GB":
                            case "DGB":
                                // adelikat: remove need for tags to be hardcoded to left and right, we should clean this up, also maybe the DGB core should just take the xml file and handle it itself
                                var leftBytes  = xmlGame.Assets.First().Value;
                                var rightBytes = xmlGame.Assets.Skip(1).First().Value;

                                var left  = Database.GetGameInfo(leftBytes, "left.gb");
                                var right = Database.GetGameInfo(rightBytes, "right.gb");
                                nextEmulator = new GambatteLink(
                                    nextComm,
                                    left,
                                    leftBytes,
                                    right,
                                    rightBytes,
                                    GetCoreSettings <GambatteLink>(),
                                    GetCoreSyncSettings <GambatteLink>(),
                                    Deterministic);

                                // other stuff todo
                                break;

                            case "AppleII":
                                var assets = xmlGame.Assets.Select(a => Database.GetGameInfo(a.Value, a.Key));
                                var roms   = xmlGame.Assets.Select(a => a.Value);
                                nextEmulator = new AppleII(
                                    nextComm,
                                    assets,
                                    roms,
                                    (AppleII.Settings)GetCoreSettings <AppleII>());
                                break;

                            case "C64":
                                nextEmulator = new C64(
                                    nextComm,
                                    xmlGame.Assets.Select(a => a.Value),
                                    (C64.C64Settings)GetCoreSettings <C64>(),
                                    (C64.C64SyncSettings)GetCoreSyncSettings <C64>()
                                    );
                                break;

                            case "PSX":
                                var entries   = xmlGame.AssetFullPaths;
                                var discs     = new List <Disc>();
                                var discNames = new List <string>();
                                var sw        = new StringWriter();
                                foreach (var e in entries)
                                {
                                    Disc   disc     = null;
                                    string discPath = e;

                                    //--- load the disc in a context which will let us abort if it's going to take too long
                                    var discMountJob = new DiscMountJob {
                                        IN_FromPath = discPath
                                    };
                                    discMountJob.IN_SlowLoadAbortThreshold = 8;
                                    discMountJob.Run();
                                    disc = discMountJob.OUT_Disc;

                                    if (discMountJob.OUT_SlowLoadAborted)
                                    {
                                        DoLoadErrorCallback("This disc would take too long to load. Run it through discohawk first, or find a new rip because this one is probably junk", "PSX", LoadErrorType.DiscError);
                                        return(false);
                                    }

                                    if (discMountJob.OUT_ErrorLevel)
                                    {
                                        throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log);
                                    }

                                    if (disc == null)
                                    {
                                        throw new InvalidOperationException("Can't load one of the files specified in the M3U");
                                    }

                                    var discName = Path.GetFileNameWithoutExtension(discPath);
                                    discNames.Add(discName);
                                    discs.Add(disc);

                                    var discType = new DiscIdentifier(disc).DetectDiscType();
                                    sw.WriteLine("{0}", Path.GetFileName(discPath));
                                    if (discType == DiscType.SonyPSX)
                                    {
                                        string discHash = new DiscHasher(disc).Calculate_PSX_BizIDHash().ToString("X8");
                                        game = Database.CheckDatabase(discHash);
                                        if (game == null || game.IsRomStatusBad() || game.Status == RomStatus.NotInDatabase)
                                        {
                                            sw.WriteLine("Disc could not be identified as known-good. Look for a better rip.");
                                        }
                                        else
                                        {
                                            sw.WriteLine("Disc was identified (99.99% confidently) as known good with disc id hash CRC32:{0:X8}", discHash);
                                            sw.WriteLine("Nonetheless it could be an unrecognized romhack or patched version.");
                                            sw.WriteLine("According to redump.org, the ideal hash for entire disc is: CRC32:{0:X8}", game.GetStringValue("dh"));
                                            sw.WriteLine("The file you loaded hasn't been hashed entirely (it would take too long)");
                                            sw.WriteLine("Compare it with the full hash calculated by the PSX menu's Hash Discs tool");
                                        }
                                    }
                                    else
                                    {
                                        sw.WriteLine("Not a PSX disc");
                                    }
                                    sw.WriteLine("-------------------------");
                                }

                                // todo: copy pasta from PSX .cue section
                                nextEmulator = new Octoshock(nextComm, discs, discNames, null, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                                nextEmulator.CoreComm.RomStatusDetails = sw.ToString();
                                game = new GameInfo {
                                    Name = Path.GetFileNameWithoutExtension(file.Name)
                                };
                                game.System = "PSX";

                                break;

                            default:
                                return(false);
                            }
                        }
                        catch (Exception ex)
                        {
                            try
                            {
                                // need to get rid of this hack at some point
                                rom = new RomGame(file);
                                ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", string.Empty));                                 // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
                                byte[] romData = null;
                                byte[] xmlData = rom.FileData;

                                game        = rom.GameInfo;
                                game.System = "SNES";

                                var snes = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                nextEmulator = snes;
                            }
                            catch
                            {
                                DoLoadErrorCallback(ex.ToString(), "DGB", LoadErrorType.XML);
                                return(false);
                            }
                        }
                    }
                    else if (file.Extension.ToLowerInvariant() == ".psf" || file.Extension.ToLowerInvariant() == ".minipsf")
                    {
                        Func <Stream, int, byte[]> cbDeflater = (Stream instream, int size) =>
                        {
                            var          inflater = new ICSharpCode.SharpZipLib.Zip.Compression.Inflater(false);
                            var          iis      = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(instream, inflater);
                            MemoryStream ret      = new MemoryStream();
                            iis.CopyTo(ret);
                            return(ret.ToArray());
                        };
                        PSF psf = new PSF();
                        psf.Load(path, cbDeflater);
                        nextEmulator = new Octoshock(nextComm, psf, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                        nextEmulator.CoreComm.RomStatusDetails = "It's a PSF, what do you want. Oh, tags maybe?";

                        //total garbage, this
                        rom  = new RomGame(file);
                        game = rom.GameInfo;
                    }
                    else if (ext != null)                     // most extensions
                    {
                        rom = new RomGame(file);

                        //hacky for now
                        if (file.Extension.ToLowerInvariant() == ".exe")
                        {
                            rom.GameInfo.System = "PSX";
                        }
                        else if (file.Extension.ToLowerInvariant() == ".nsf")
                        {
                            rom.GameInfo.System = "NES";
                        }


                        if (string.IsNullOrEmpty(rom.GameInfo.System))
                        {
                            // Has the user picked a preference for this extension?
                            if (PreferredPlatformIsDefined(rom.Extension.ToLowerInvariant()))
                            {
                                rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLowerInvariant()];
                            }
                            else if (ChoosePlatform != null)
                            {
                                var result = ChoosePlatform(rom);
                                if (!string.IsNullOrEmpty(result))
                                {
                                    rom.GameInfo.System = result;
                                }
                                else
                                {
                                    cancel = true;
                                }
                            }
                        }

                        game = rom.GameInfo;

                        var isXml = false;

                        // other xml has already been handled
                        if (file.Extension.ToLowerInvariant() == ".xml")
                        {
                            game.System = "SNES";
                            isXml       = true;
                        }


                        CoreInventory.Core core = null;

                        switch (game.System)
                        {
                        default:
                            core = CoreInventory.Instance[game.System];
                            break;

                        case null:
                            // The user picked nothing in the Core picker
                            break;

                        case "83P":
                            var ti83Bios     = ((CoreFileProvider)nextComm.CoreFileProvider).GetFirmware("TI83", "Rom", true);
                            var ti83BiosPath = ((CoreFileProvider)nextComm.CoreFileProvider).GetFirmwarePath("TI83", "Rom", true);
                            using (var ti83AsHawkFile = new HawkFile())
                            {
                                ti83AsHawkFile.Open(ti83BiosPath);
                                var ti83BiosAsRom = new RomGame(ti83AsHawkFile);
                                var ti83          = new TI83(nextComm, ti83BiosAsRom.GameInfo, ti83Bios, GetCoreSettings <TI83>());
                                ti83.LinkPort.SendFileToCalc(File.OpenRead(path), false);
                                nextEmulator = ti83;
                            }
                            break;

                        case "SNES":
                            if (Global.Config.SNES_InSnes9x && VersionInfo.DeveloperBuild)
                            {
                                core = CoreInventory.Instance["SNES", "Snes9x"];
                            }
                            else
                            {
                                // need to get rid of this hack at some point
                                ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", String.Empty));                                         // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
                                var romData = isXml ? null : rom.FileData;
                                var xmlData = isXml ? rom.FileData : null;
                                var snes    = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                nextEmulator = snes;
                            }

                            break;

                        case "NES":
                            if (!Global.Config.NES_InQuickNES || forceAccurateCore)
                            {
                                core = CoreInventory.Instance["NES", "NesHawk"];
                            }
                            else
                            {
                                core = CoreInventory.Instance["NES", "QuickNes"];
                            }

                            break;

                        case "GB":
                        case "GBC":
                            if (!Global.Config.GB_AsSGB)
                            {
                                core = CoreInventory.Instance["GB", "Gambatte"];
                            }
                            else
                            {
                                try
                                {
                                    game.System = "SNES";
                                    game.AddOption("SGB");
                                    var snes = new LibsnesCore(game, rom.FileData, Deterministic, null, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                    nextEmulator = snes;
                                }
                                catch
                                {
                                    // failed to load SGB bios or game does not support SGB mode.
                                    // To avoid catch-22, disable SGB mode
                                    Global.Config.GB_AsSGB = false;
                                    throw;
                                }
                            }

                            break;

                        case "A78":
                            var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
                            nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath);
                            break;

                        case "C64":
                            var c64 = new C64(nextComm, Enumerable.Repeat(rom.RomData, 1), GetCoreSettings <C64>(), GetCoreSyncSettings <C64>());
                            nextEmulator = c64;
                            break;

                        case "GBA":
                            //core = CoreInventory.Instance["GBA", "Meteor"];
                            if (Global.Config.GBA_UsemGBA)
                            {
                                core = CoreInventory.Instance["GBA", "mGBA"];
                            }
                            else
                            {
                                core = CoreInventory.Instance["GBA", "VBA-Next"];
                            }
                            break;

                        case "PSX":
                            nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings <Octoshock>(), GetCoreSyncSettings <Octoshock>());
                            nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
                            break;
                        }

                        if (core != null)
                        {
                            // use coreinventory
                            nextEmulator = core.Create(nextComm, game, rom.RomData, rom.FileData, Deterministic, GetCoreSettings(core.Type), GetCoreSyncSettings(core.Type));
                        }
                    }

                    if (nextEmulator == null)
                    {
                        if (!cancel)
                        {
                            DoLoadErrorCallback("No core could load the rom.", null);
                        }
                        return(false);
                    }
                }
                catch (Exception ex)
                {
                    string system = null;
                    if (game != null)
                    {
                        system = game.System;
                    }

                    // all of the specific exceptions we're trying to catch here aren't expected to have inner exceptions,
                    // so drill down in case we got a TargetInvocationException or something like that
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    // Specific hack here, as we get more cores of the same system, this isn't scalable
                    if (ex is UnsupportedGameException)
                    {
                        if (system == "NES")
                        {
                            DoMessageCallback("Unable to use quicknes, using NESHawk instead");
                        }

                        return(LoadRom(path, nextComm, true, recursiveCount + 1));
                    }
                    else if (ex is MissingFirmwareException)
                    {
                        DoLoadErrorCallback(ex.Message, system, path, Deterministic, LoadErrorType.MissingFirmware);
                    }
                    else if (ex is CGBNotSupportedException)
                    {
                        // Note: GB as SGB was set to false by this point, otherwise we would want to do it here
                        DoMessageCallback("Failed to load a GB rom in SGB mode.  Disabling SGB Mode.");
                        return(LoadRom(path, nextComm, false, recursiveCount + 1));
                    }
                    else
                    {
                        DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system);
                    }

                    return(false);
                }

                Rom            = rom;
                LoadedEmulator = nextEmulator;
                Game           = game;
                return(true);
            }
        }
Ejemplo n.º 15
0
        private void Download()
        {
            //the temp file is owned by this thread
            var fn = TempFileManager.GetTempFilename("ffmpeg_download", ".7z", false);

            try
            {
                using (var evt = new ManualResetEvent(false))
                {
                    using (var client = new System.Net.WebClient())
                    {
                        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
                        client.DownloadFileAsync(new Uri(FFmpegService.Url), fn);
                        client.DownloadProgressChanged += (object sender, System.Net.DownloadProgressChangedEventArgs e) =>
                        {
                            pct = e.ProgressPercentage;
                        };
                        client.DownloadFileCompleted += (object sender, System.ComponentModel.AsyncCompletedEventArgs e) =>
                        {
                            //we don't really need a status. we'll just try to unzip it when it's done
                            evt.Set();
                        };

                        for (; ;)
                        {
                            if (evt.WaitOne(10))
                            {
                                break;
                            }

                            //if the gui thread ordered an exit, cancel the download and wait for it to acknowledge
                            if (exiting)
                            {
                                client.CancelAsync();
                                evt.WaitOne();
                                break;
                            }
                        }
                    }
                }

                //throw new Exception("test of download failure");

                //if we were ordered to exit, bail without wasting any more time
                if (exiting)
                {
                    return;
                }

                //try acquiring file
                using (var hf = new HawkFile(fn))
                {
                    using (var exe = OSTailoredCode.IsUnixHost ? hf.BindArchiveMember("ffmpeg") : hf.BindFirstOf(".exe"))
                    {
                        var data = exe !.ReadAllBytes();

                        //last chance. exiting, don't dump the new ffmpeg file
                        if (exiting)
                        {
                            return;
                        }

                        DirectoryInfo parentDir = new(Path.GetDirectoryName(FFmpegService.FFmpegPath) !);
                        if (!parentDir.Exists)
                        {
                            parentDir.Create();
                        }
                        File.WriteAllBytes(FFmpegService.FFmpegPath, data);
                        if (OSTailoredCode.IsUnixHost)
                        {
                            OSTailoredCode.ConstructSubshell("chmod", $"+x {FFmpegService.FFmpegPath}", checkStdout: false).Start();
                            Thread.Sleep(50);                             // Linux I/O flush idk
                        }
                    }
                }

                //make sure it worked
                if (!FFmpegService.QueryServiceAvailable())
                {
                    throw new Exception("download failed");
                }

                succeeded = true;
            }
            catch
            {
                failed = true;
            }
            finally
            {
                try { File.Delete(fn); }
                catch { }
            }
        }
Ejemplo n.º 16
0
        private bool LoadDisc(string path, CoreComm nextComm, HawkFile file, string ext, out IEmulator nextEmulator, out GameInfo game)
        {
            var disc = DiscExtensions.CreateAnyType(path, str => DoLoadErrorCallback(str, "???", LoadErrorType.DiscError));

            if (disc == null)
            {
                game         = null;
                nextEmulator = null;
                return(false);
            }

            // TODO - use more sophisticated IDer
            var discType   = new DiscIdentifier(disc).DetectDiscType();
            var discHasher = new DiscHasher(disc);
            var discHash   = discType == DiscType.SonyPSX
                                ? discHasher.Calculate_PSX_BizIDHash().ToString("X8")
                                : discHasher.OldHash();

            game = Database.CheckDatabase(discHash);
            if (game == null)
            {
                // try to use our wizard methods
                game = new GameInfo {
                    Name = Path.GetFileNameWithoutExtension(file.Name), Hash = discHash
                };

                switch (discType)
                {
                case DiscType.SegaSaturn:
                    game.System = "SAT";
                    break;

                case DiscType.SonyPSP:
                    game.System = "PSP";
                    break;

                case DiscType.MegaCD:
                    game.System = "GEN";
                    break;

                case DiscType.PCFX:
                    game.System = "PCFX";
                    break;

                case DiscType.TurboGECD:
                case DiscType.TurboCD:
                    game.System = "PCECD";
                    break;

                case DiscType.Amiga:
                case DiscType.CDi:
                case DiscType.Dreamcast:
                case DiscType.GameCube:
                case DiscType.NeoGeoCD:
                case DiscType.Panasonic3DO:
                case DiscType.Playdia:
                case DiscType.Wii:
                    // no supported emulator core for these (yet)
                    game.System = discType.ToString();
                    throw new NoAvailableCoreException(discType.ToString());

                case DiscType.AudioDisc:
                case DiscType.UnknownCDFS:
                case DiscType.UnknownFormat:
                    game.System = PreferredPlatformIsDefined(ext)
                                                        ? _config.PreferredPlatformsForExtensions[ext]
                                                        : "NULL";
                    break;

                default:                         //"for an unknown disc, default to psx instead of pce-cd, since that is far more likely to be what they are attempting to open" [5e07ab3ec3b8b8de9eae71b489b55d23a3909f55, year 2015]
                case DiscType.SonyPSX:
                    game.System = "PSX";
                    break;
                }
            }

            var cip = new CoreInventoryParameters(this)
            {
                Comm  = nextComm,
                Game  = game,
                Discs =
                {
                    new DiscAsset
                    {
                        DiscData = disc,
                        DiscType = new DiscIdentifier(disc).DetectDiscType(),
                        DiscName = Path.GetFileNameWithoutExtension(path)
                    }
                },
            };

            nextEmulator = MakeCoreFromCoreInventory(cip);
            return(true);
        }
Ejemplo n.º 17
0
        private void tsmiSetCustomization_Click(object sender, EventArgs e)
        {
            using (var ofd = new OpenFileDialog())
            {
                ofd.InitialDirectory = currSelectorDir;
                ofd.RestoreDirectory = true;
                string frmwarePath = PathManager.MakeAbsolutePath(Global.Config.PathEntries.FirmwaresPathFragment, null);

                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    // remember the location we selected this firmware from, maybe there are others
                    currSelectorDir = Path.GetDirectoryName(ofd.FileName);

                    try
                    {
                        using (var hf = new HawkFile(ofd.FileName))
                        {
                            // for each selected item, set the user choice (even though multiple selection for this operation is no longer allowed)
                            foreach (ListViewItem lvi in lvFirmwares.SelectedItems)
                            {
                                var    fr       = lvi.Tag as FirmwareDatabase.FirmwareRecord;
                                string filePath = ofd.FileName;

                                // if the selected file is an archive, allow the user to pick the inside file
                                // to always be copied to the global firmwares directory
                                if (hf.IsArchive)
                                {
                                    var ac     = new ArchiveChooser(new HawkFile(filePath));
                                    int memIdx = -1;

                                    if (ac.ShowDialog(this) == DialogResult.OK)
                                    {
                                        memIdx = ac.SelectedMemberIndex;
                                    }
                                    else
                                    {
                                        return;
                                    }

                                    var insideFile = hf.BindArchiveMember(memIdx);
                                    var fileData   = insideFile.ReadAllBytes();

                                    // write to file in the firmwares folder
                                    File.WriteAllBytes(Path.Combine(frmwarePath, insideFile.Name), fileData);
                                    filePath = Path.Combine(frmwarePath, insideFile.Name);
                                }
                                else
                                {
                                    // selected file is not an archive
                                    // check whether this file is currently outside of the global firmware directory
                                    if (currSelectorDir != frmwarePath)
                                    {
                                        var askMoveResult = MessageBox.Show(this, "The selected custom firmware does not reside in the root of the global firmware directory.\nDo you want to copy it there?", "Import Custom Firmware", MessageBoxButtons.YesNo);
                                        if (askMoveResult == DialogResult.Yes)
                                        {
                                            try
                                            {
                                                FileInfo fi = new FileInfo(filePath);
                                                filePath = Path.Combine(frmwarePath, fi.Name);
                                                File.Copy(ofd.FileName, filePath);
                                            }
                                            catch (Exception ex)
                                            {
                                                MessageBox.Show(this, $"There was an issue copying the file. The customization has NOT been set.\n\n{ex.StackTrace}");
                                                continue;
                                            }
                                        }
                                    }
                                }

                                Global.Config.FirmwareUserSpecifications[fr.ConfigKey] = filePath;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(this, $"There was an issue during the process. The customization has NOT been set.\n\n{ex.StackTrace}");
                        return;
                    }

                    DoScan();
                }
            }
        }
Ejemplo n.º 18
0
 private void LoadM3U(string path, CoreComm nextComm, HawkFile file, out IEmulator nextEmulator, out GameInfo game)
 {
     throw new NotImplementedException("M3U not supported!");
 }
Ejemplo n.º 19
0
        private void LoadOther(CoreComm nextComm, HawkFile file, string forcedCoreName, out IEmulator nextEmulator, out RomGame rom, out GameInfo game, out bool cancel)
        {
            cancel = false;
            rom    = new RomGame(file);

            // hacky for now
            if (file.Extension == ".exe")
            {
                rom.GameInfo.System = "PSX";
            }
            else if (file.Extension == ".nsf")
            {
                rom.GameInfo.System = "NES";
            }

            Debug.WriteLine(rom.GameInfo.System);

            if (string.IsNullOrEmpty(rom.GameInfo.System))
            {
                // Has the user picked a preference for this extension?
                if (PreferredPlatformIsDefined(rom.Extension.ToLowerInvariant()))
                {
                    rom.GameInfo.System = _config.PreferredPlatformsForExtensions[rom.Extension.ToLowerInvariant()];
                }
                else if (ChoosePlatform != null)
                {
                    var result = ChoosePlatform(rom);
                    if (!string.IsNullOrEmpty(result))
                    {
                        rom.GameInfo.System = result;
                    }
                    else
                    {
                        cancel = true;
                    }
                }
            }

            game = rom.GameInfo;

            nextEmulator = null;
            if (game.System == null)
            {
                return;                 // The user picked nothing in the Core picker
            }
            switch (game.System)
            {
            case "GB":
            case "GBC":
                if (_config.GbAsSgb)
                {
                    game.System = "SGB";
                }
                break;

            case "Arcade":
                nextEmulator = new MAME(
                    file.Directory,
                    file.CanonicalName,
                    GetCoreSyncSettings <MAME, MAME.SyncSettings>(),
                    out var gameName
                    );
                rom.GameInfo.Name = gameName;
                return;
            }
            var cip = new CoreInventoryParameters(this)
            {
                Comm = nextComm,
                Game = game,
                Roms =
                {
                    new RomAsset
                    {
                        RomData   = rom.RomData,
                        FileData  = rom.FileData,
                        Extension = rom.Extension,
                        Game      = game
                    }
                },
            };

            nextEmulator = MakeCoreFromCoreInventory(cip, forcedCoreName);
        }
Ejemplo n.º 20
0
        public static ToolStripItem[] RecentMenu(this RecentFiles recent, Action <string> loadFileCallback, bool autoload = false, bool romloading = false)
        {
            var items = new List <ToolStripItem>();

            if (recent.Empty)
            {
                var none = new ToolStripMenuItem {
                    Enabled = false, Text = "None"
                };
                items.Add(none);
            }
            else
            {
                foreach (var filename in recent)
                {
                    string caption      = filename;
                    string path         = filename;
                    string physicalPath = filename;
                    bool   crazyStuff   = true;

                    //sentinel for newer format OpenAdvanced type code
                    if (romloading)
                    {
                        if (filename.StartsWith("*"))
                        {
                            var oa = OpenAdvancedSerializer.ParseWithLegacy(filename);
                            caption = oa.DisplayName;

                            crazyStuff = false;
                            if (oa is OpenAdvanced_OpenRom)
                            {
                                crazyStuff   = true;
                                physicalPath = ((oa as OpenAdvanced_OpenRom).Path);
                            }
                        }
                    }

                    //TODO - do TSMI and TSDD need disposing? yuck
                    var item = new ToolStripMenuItem {
                        Text = caption
                    };
                    items.Add(item);

                    item.Click += (o, ev) =>
                    {
                        loadFileCallback(path);
                    };

                    var tsdd = new ToolStripDropDownMenu();

                    if (crazyStuff)
                    {
                        //TODO - use standard methods to split filename (hawkfile acquire?)
                        var hf = new HawkFile();
                        hf.Parse(physicalPath);
                        bool canExplore = true;
                        if (!File.Exists(hf.FullPathWithoutMember))
                        {
                            canExplore = false;
                        }

                        if (canExplore)
                        {
                            //make a menuitem to show the last modified timestamp
                            var timestamp     = File.GetLastWriteTime(hf.FullPathWithoutMember);
                            var tsmiTimestamp = new ToolStripLabel {
                                Text = timestamp.ToString()
                            };

                            tsdd.Items.Add(tsmiTimestamp);
                            tsdd.Items.Add(new ToolStripSeparator());

                            if (hf.IsArchive)
                            {
                                //make a menuitem to let you copy the path
                                var tsmiCopyCanonicalPath = new ToolStripMenuItem {
                                    Text = "&Copy Canonical Path"
                                };
                                tsmiCopyCanonicalPath.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetText(physicalPath); };
                                tsdd.Items.Add(tsmiCopyCanonicalPath);

                                var tsmiCopyArchivePath = new ToolStripMenuItem {
                                    Text = "Copy Archive Path"
                                };
                                tsmiCopyArchivePath.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetText(hf.FullPathWithoutMember); };
                                tsdd.Items.Add(tsmiCopyArchivePath);

                                var tsmiOpenArchive = new ToolStripMenuItem {
                                    Text = "Open &Archive"
                                };
                                tsmiOpenArchive.Click += (o, ev) => { System.Diagnostics.Process.Start(hf.FullPathWithoutMember); };
                                tsdd.Items.Add(tsmiOpenArchive);
                            }
                            else
                            {
                                //make a menuitem to let you copy the path
                                var tsmiCopyPath = new ToolStripMenuItem {
                                    Text = "&Copy Path"
                                };
                                tsmiCopyPath.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetText(physicalPath); };
                                tsdd.Items.Add(tsmiCopyPath);
                            }

                            tsdd.Items.Add(new ToolStripSeparator());

                            //make a menuitem to let you explore to it
                            var tsmiExplore = new ToolStripMenuItem {
                                Text = "&Explore"
                            };
                            string explorePath = "\"" + hf.FullPathWithoutMember + "\"";
                            tsmiExplore.Click += (o, ev) => { System.Diagnostics.Process.Start("explorer.exe", "/select, " + explorePath); };
                            tsdd.Items.Add(tsmiExplore);

                            var tsmiCopyFile = new ToolStripMenuItem {
                                Text = "Copy &File"
                            };
                            var lame = new System.Collections.Specialized.StringCollection();
                            lame.Add(hf.FullPathWithoutMember);
                            tsmiCopyFile.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetFileDropList(lame); };
                            tsdd.Items.Add(tsmiCopyFile);

                            var tsmiTest = new ToolStripMenuItem {
                                Text = "&Shell Context Menu"
                            };
                            tsmiTest.Click += (o, ev) =>
                            {
                                var si    = new GongSolutions.Shell.ShellItem(hf.FullPathWithoutMember);
                                var scm   = new GongSolutions.Shell.ShellContextMenu(si);
                                var tsddi = o as ToolStripDropDownItem;
                                tsddi.Owner.Update();
                                scm.ShowContextMenu(tsddi.Owner, new System.Drawing.Point(0, 0));
                            };
                            tsdd.Items.Add(tsmiTest);

                            tsdd.Items.Add(new ToolStripSeparator());
                        }
                        else
                        {
                            //make a menuitem to show the last modified timestamp
                            var tsmiMissingFile = new ToolStripLabel {
                                Text = "-Missing-"
                            };
                            tsdd.Items.Add(tsmiMissingFile);
                            tsdd.Items.Add(new ToolStripSeparator());
                        }
                    }                     //crazystuff

                    //in any case, make a menuitem to let you remove the item
                    var tsmiRemovePath = new ToolStripMenuItem {
                        Text = "&Remove"
                    };
                    tsmiRemovePath.Click += (o, ev) => {
                        recent.Remove(path);
                    };
                    tsdd.Items.Add(tsmiRemovePath);

                    ////experiment of popping open a submenu. doesnt work well.
                    //item.MouseDown += (o, mev) =>
                    //{
                    //  if (mev.Button != MouseButtons.Right) return;
                    //  //location of the menu containing this item that was just rightclicked
                    //  var pos = item.Owner.Bounds.Location;
                    //  //the offset within that menu of this item
                    //  var tsddi = item as ToolStripDropDownItem;
                    //  pos.Offset(tsddi.Bounds.Location);
                    //  //the offset of the click
                    //  pos.Offset(mev.Location);
                    //	//tsdd.OwnerItem = item; //has interesting promise, but breaks things otherwise
                    //  tsdd.Show(pos);
                    //};

                    //just add it to the submenu for now. seems to work well enough, even though its a bit odd
                    item.MouseDown += (o, mev) =>
                    {
                        if (mev.Button != MouseButtons.Right)
                        {
                            return;
                        }
                        if (item.DropDown != null)
                        {
                            item.DropDown = tsdd;
                        }
                        item.ShowDropDown();
                    };
                }
            }

            items.Add(new ToolStripSeparator());

            var clearitem = new ToolStripMenuItem {
                Text = "&Clear", Enabled = !recent.Frozen
            };

            clearitem.Click += (o, ev) => recent.Clear();
            items.Add(clearitem);

            var freezeitem = new ToolStripMenuItem {
                Text = recent.Frozen ? "&Unfreeze" : "&Freeze"
            };

            freezeitem.Click += (o, ev) => recent.Frozen ^= true;
            items.Add(freezeitem);

            if (autoload)
            {
                var auto = new ToolStripMenuItem {
                    Text = "&Autoload", Checked = recent.AutoLoad
                };
                auto.Click += (o, ev) => recent.ToggleAutoLoad();
                items.Add(auto);
            }

            var settingsitem = new ToolStripMenuItem {
                Text = "&Recent Settings..."
            };

            settingsitem.Click += (o, ev) =>
            {
                using (var prompt = new InputPrompt
                {
                    TextInputType = InputPrompt.InputType.Unsigned,
                    Message = "Number of recent files to track",
                    InitialValue = recent.MAX_RECENT_FILES.ToString()
                })
                {
                    var result = prompt.ShowDialog();
                    if (result == DialogResult.OK)
                    {
                        int val = int.Parse(prompt.PromptText);
                        if (val > 0)
                        {
                            recent.MAX_RECENT_FILES = val;
                        }
                    }
                }
            };
            items.Add(settingsitem);

            return(items.ToArray());
        }
Ejemplo n.º 21
0
        public BootGodDb(string basePath)
        {
            // notes: there can be multiple each of prg,chr,wram,vram
            // we aren't tracking the individual hashes yet.

            string xmlPath = Path.Combine(basePath, "NesCarts.xml");
            string x7zPath = Path.Combine(basePath, "NesCarts.7z");
            bool   loadXml = File.Exists(xmlPath);

            using var nesCartFile = new HawkFile(loadXml ? xmlPath : x7zPath);
            if (!loadXml)
            {
                nesCartFile.BindFirst();
            }

            var stream = nesCartFile.GetStream();

            // in anticipation of any slowness annoying people, and just for shits and giggles, i made a super fast parser
            int      state     = 0;
            var      xmlReader = XmlReader.Create(stream);
            CartInfo currCart  = null;
            string   currName  = null;

            while (xmlReader.Read())
            {
                switch (state)
                {
                case 0:
                    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "game")
                    {
                        currName = xmlReader.GetAttribute("name");
                        state    = 1;
                    }
                    break;

                case 2:
                    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "board")
                    {
                        currCart.BoardType = xmlReader.GetAttribute("type");
                        currCart.Pcb       = xmlReader.GetAttribute("pcb");
                        int mapper = int.Parse(xmlReader.GetAttribute("mapper"));
                        if (validate && mapper > 255)
                        {
                            throw new Exception("didnt expect mapper>255!");
                        }
                        // we don't actually use this value at all; only the board name
                        state = 3;
                    }
                    break;

                case 3:
                    if (xmlReader.NodeType == XmlNodeType.Element)
                    {
                        switch (xmlReader.Name)
                        {
                        case "prg":
                            currCart.PrgSize += (short)ParseSize(xmlReader.GetAttribute("size"));
                            break;

                        case "chr":
                            currCart.ChrSize += (short)ParseSize(xmlReader.GetAttribute("size"));
                            break;

                        case "vram":
                            currCart.VramSize += (short)ParseSize(xmlReader.GetAttribute("size"));
                            break;

                        case "wram":
                            currCart.WramSize += (short)ParseSize(xmlReader.GetAttribute("size"));
                            if (xmlReader.GetAttribute("battery") != null)
                            {
                                currCart.WramBattery = true;
                            }
                            break;

                        case "pad":
                            currCart.PadH = byte.Parse(xmlReader.GetAttribute("h"));
                            currCart.PadV = byte.Parse(xmlReader.GetAttribute("v"));
                            break;

                        case "chip":
                            currCart.Chips.Add(xmlReader.GetAttribute("type"));
                            if (xmlReader.GetAttribute("battery") != null)
                            {
                                currCart.WramBattery = true;
                            }
                            break;
                        }
                    }
                    else
                    if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "board")
                    {
                        state = 4;
                    }
                    break;

                case 4:
                    if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "cartridge")
                    {
                        _sha1Table[currCart.Sha1].Add(currCart);
                        currCart = null;
                        state    = 5;
                    }
                    break;

                case 5:
                case 1:
                    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "cartridge")
                    {
                        currCart        = new CartInfo();
                        currCart.System = xmlReader.GetAttribute("system");
                        currCart.Sha1   = "sha1:" + xmlReader.GetAttribute("sha1");
                        currCart.Name   = currName;
                        state           = 2;
                    }
                    if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "game")
                    {
                        currName = null;
                        state    = 0;
                    }
                    break;
                }
            }             //end xmlreader loop
        }
Ejemplo n.º 22
0
        /// <exception cref="Exception"><paramref name="file"/> does not exist</exception>
        public RomGame(HawkFile file, string patch)
        {
            if (!file.Exists)
            {
                throw new Exception("The file needs to exist, yo.");
            }

            Extension = file.Extension.ToUpperInvariant();

            var stream     = file.GetStream();
            int fileLength = (int)stream.Length;

            // read the entire contents of the file into memory.
            // unfortunate in the case of large files, but that's what we've got to work with for now.

            // if we're offset exactly 512 bytes from a 1024-byte boundary,
            // assume we have a header of that size. Otherwise, assume it's just all rom.
            // Other 'recognized' header sizes may need to be added.
            int headerOffset = fileLength % BankSize;

            if (headerOffset.In(0, 128, 512) == false)
            {
                Console.WriteLine("ROM was not a multiple of 1024 bytes, and not a recognized header size: {0}. Assume it's purely ROM data.", headerOffset);
                headerOffset = 0;
            }
            else if (headerOffset > 0)
            {
                Console.WriteLine("Assuming header of {0} bytes.", headerOffset);
            }

            // read the entire file into FileData.
            FileData        = new byte[fileLength];
            stream.Position = 0;
            stream.Read(FileData, 0, fileLength);

            // if there was no header offset, RomData is equivalent to FileData
            // (except in cases where the original interleaved file data is necessary.. in that case we'll have problems..
            // but this whole architecture is not going to withstand every peculiarity and be fast as well.
            if (headerOffset == 0)
            {
                RomData = FileData;
            }
            else if (file.Extension == ".dsk" || file.Extension == ".tap" || file.Extension == ".tzx" ||
                     file.Extension == ".pzx" || file.Extension == ".csw" || file.Extension == ".wav" || file.Extension == ".cdt")
            {
                // these are not roms. unfortunately if treated as such there are certain edge-cases
                // where a header offset is detected. This should mitigate this issue until a cleaner solution is found
                // (-Asnivor)
                RomData = FileData;
            }
            else
            {
                // if there was a header offset, read the whole file into FileData and then copy it into RomData (this is unfortunate, in case RomData isn't needed)
                int romLength = fileLength - headerOffset;
                RomData = new byte[romLength];
                Buffer.BlockCopy(FileData, headerOffset, RomData, 0, romLength);
            }

            if (file.Extension == ".smd")
            {
                RomData = DeInterleaveSMD(RomData);
            }

            if (file.Extension == ".z64" || file.Extension == ".n64" || file.Extension == ".v64")
            {
                RomData = MutateSwapN64(RomData);
            }

            // note: this will be taking several hashes, of a potentially large amount of data.. yikes!
            GameInfo = Database.GetGameInfo(RomData, file.Name);

            if (GameInfo.NotInDatabase && headerOffset == 128 && file.Extension == ".a78")
            {
                // if the game is not in the DB, add the header back in so the core can use it
                // for now only .A78 games, but probably should be for other systems as well
                RomData = FileData;
            }

            CheckForPatchOptions();

            if (patch != null)
            {
                using var patchFile = new HawkFile(patch);
                patchFile.BindFirstOf(".ips");
                if (patchFile.IsBound)
                {
                    RomData = IPS.Patch(RomData, patchFile.GetStream());
                }
            }
        }
Ejemplo n.º 23
0
        public RomGame(HawkFile file, string patch)
        {
            if (!file.Exists)
            {
                throw new Exception("The file needs to exist, yo.");
            }

            Extension = file.Extension;

            var stream     = file.GetStream();
            int fileLength = (int)stream.Length;

            // read the entire contents of the file into memory.
            // unfortunate in the case of large files, but thats what we've got to work with for now.

            // if we're offset exactly 512 bytes from a 1024-byte boundary,
            // assume we have a header of that size. Otherwise, assume it's just all rom.
            // Other 'recognized' header sizes may need to be added.
            int headerOffset = fileLength % BankSize;

            if (headerOffset.In(0, 512) == false)
            {
                Console.WriteLine("ROM was not a multiple of 1024 bytes, and not a recognized header size: {0}. Assume it's purely ROM data.", headerOffset);
                headerOffset = 0;
            }
            else if (headerOffset > 0)
            {
                Console.WriteLine("Assuming header of {0} bytes.", headerOffset);
            }

            // read the entire file into FileData.
            FileData = new byte[fileLength];
            stream.Read(FileData, 0, fileLength);

            // if there was no header offset, RomData is equivalent to FileData
            // (except in cases where the original interleaved file data is necessary.. in that case we'll have problems..
            // but this whole architecture is not going to withstand every peculiarity and be fast as well.
            if (headerOffset == 0)
            {
                RomData = FileData;
            }
            else
            {
                // if there was a header offset, read the whole file into FileData and then copy it into RomData (this is unfortunate, in case RomData isnt needed)
                int romLength = fileLength - headerOffset;
                RomData = new byte[romLength];
                Buffer.BlockCopy(FileData, headerOffset, RomData, 0, romLength);
            }

            if (file.Extension == ".SMD")
            {
                RomData = DeInterleaveSMD(RomData);
            }

            if (file.Extension == ".Z64" || file.Extension == ".N64" || file.Extension == ".V64")
            {
                RomData = MutateSwapN64(RomData);
            }

            // note: this will be taking several hashes, of a potentially large amount of data.. yikes!
            GameInfo = Database.GetGameInfo(RomData, file.Name);

            CheckForPatchOptions();

            if (patch != null)
            {
                using (var patchFile = new HawkFile(patch))
                {
                    patchFile.BindFirstOf("IPS");
                    if (patchFile.IsBound)
                    {
                        IPS.Patch(RomData, patchFile.GetStream());
                    }
                }
            }
        }
Ejemplo n.º 24
0
        private void Download()
        {
            //the temp file is owned by this thread
            var fn = TempFileManager.GetTempFilename("ffmpeg_download", ".7z", false);

            try
            {
                using (var evt = new ManualResetEvent(false))
                {
                    using (var client = new System.Net.WebClient())
                    {
                        System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
                        client.DownloadFileAsync(new Uri(FFmpegService.Url), fn);
                        client.DownloadProgressChanged += (object sender, System.Net.DownloadProgressChangedEventArgs e) =>
                        {
                            pct = e.ProgressPercentage;
                        };
                        client.DownloadFileCompleted += (object sender, System.ComponentModel.AsyncCompletedEventArgs e) =>
                        {
                            //we don't really need a status. we'll just try to unzip it when it's done
                            evt.Set();
                        };

                        for (; ;)
                        {
                            if (evt.WaitOne(10))
                            {
                                break;
                            }

                            //if the gui thread ordered an exit, cancel the download and wait for it to acknowledge
                            if (exiting)
                            {
                                client.CancelAsync();
                                evt.WaitOne();
                                break;
                            }
                        }
                    }
                }

                //throw new Exception("test of download failure");

                //if we were ordered to exit, bail without wasting any more time
                if (exiting)
                {
                    return;
                }

                //try acquiring file
                using (var hf = new HawkFile(fn))
                {
                    using (var exe = hf.BindFirstOf(".exe"))
                    {
                        var data = exe.ReadAllBytes();

                        //last chance. exiting, don't dump the new ffmpeg file
                        if (exiting)
                        {
                            return;
                        }

                        File.WriteAllBytes(FFmpegService.FFmpegPath, data);
                    }
                }

                //make sure it worked
                if (!new FFmpegService().QueryServiceAvailable())
                {
                    throw new Exception("download failed");
                }

                succeeded = true;
            }
            catch
            {
                failed = true;
            }
            finally
            {
                try { File.Delete(fn); }
                catch { }
            }
        }
Ejemplo n.º 25
0
        private void FormDragDrop_internal(DragEventArgs e)
        {
            /*
             *  Refactor, moving the loading of particular files into separate functions that can
             *  then be used by this code, and loading individual files through the file dialogue.
             *
             *  Step 1:
             *	  Build a dictionary of relevant files from everything that was dragged and dropped.
             *	  This includes peeking into all relevant archives and using their files.
             *
             *  Step 2:
             *	  Perhaps ask the user which of a particular file type they want to use.
             *		  Example:  rom1.nes, rom2.smc, rom3.cue are drag-dropped, ask the user which they want to use.
             *
             *  Step 3:
             *	  Load all of the relevant files, in priority order:
             *	  1) The ROM
             *	  2) State
             *	  3) Watch files
             *	  4) Code Data Logger (CDL)
             *	  5) LUA sessions
             *	  6) LUA scripts
             *	  7) Cheat files
             *	  8) Movie Playback Files
             *
             *  Bonus:
             *	  Make that order easy to change in the code, heavily suggesting ROM and playback as first and last respectively.
             */

            var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
            Dictionary <LoadOrdering, List <FileInformation> > sortedFiles = new Dictionary <LoadOrdering, List <FileInformation> >();

            // Initialize the dictionary's lists.
            foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
            {
                sortedFiles.Add(value, new List <FileInformation>());
            }

            ProcessFileList(HawkFile.Util_ResolveLinks(filePaths), ref sortedFiles);

            // For each of the different types of item, if there are no items of that type, skip them.
            // If there is exactly one of that type of item, load it.
            // If there is more than one, ask.

            foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
            {
                switch (sortedFiles[value].Count)
                {
                case 0:
                    break;

                case 1:
                    var    fileInformation = sortedFiles[value].First();
                    string filename        = Path.Combine(new[] { fileInformation.DirectoryName, fileInformation.FileName });

                    switch (value)
                    {
                    case LoadOrdering.Rom:
                        LoadRom(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.State:
                        LoadStateFile(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.Watch:
                        LoadWatch(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.CdFile:
                        LoadCdl(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.LuaSession:
                        LoadLuaSession(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.LuaScript:
                        LoadLuaFile(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.Cheat:
                        LoadCheats(filename, fileInformation.ArchiveName);
                        break;

                    case LoadOrdering.MovieFile:
                    case LoadOrdering.LegacyMovieFile:
                        // I don't really like this hack, but for now, we only want to load one movie file.
                        if (sortedFiles[LoadOrdering.MovieFile].Count + sortedFiles[LoadOrdering.LegacyMovieFile].Count > 1)
                        {
                            break;
                        }

                        if (value == LoadOrdering.MovieFile)
                        {
                            LoadMovie(filename, fileInformation.ArchiveName);
                        }
                        else
                        {
                            LoadLegacyMovie(filename, fileInformation.ArchiveName);
                        }
                        break;
                    }
                    break;
                }
            }
        }
Ejemplo n.º 26
0
        public bool LoadRom(string path, CoreComm nextComm, bool forceAccurateCore = false)         // forceAccurateCore is currently just for Quicknes vs Neshawk but could be used for other situations
        {
            if (path == null)
            {
                return(false);
            }

            using (var file = new HawkFile())
            {
                var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC" };

                // lets not use this unless we need to
                // file.NonArchiveExtensions = romExtensions;
                file.Open(path);

                // if the provided file doesnt even exist, give up!
                if (!file.Exists)
                {
                    return(false);
                }

                // try binding normal rom extensions first
                if (!file.IsBound)
                {
                    file.BindSoleItemOf(romExtensions);
                }

                // if we have an archive and need to bind something, then pop the dialog
                if (file.IsArchive && !file.IsBound)
                {
                    var result = HandleArchive(file);
                    if (result.HasValue)
                    {
                        file.BindArchiveMember(result.Value);
                    }
                    else
                    {
                        return(false);
                    }
                }

                // set this here so we can see what file we tried to load even if an error occurs
                CanonicalFullPath = file.CanonicalFullPath;

                IEmulator nextEmulator = null;
                RomGame   rom          = null;
                GameInfo  game         = null;

                try
                {
                    var ext = file.Extension.ToLower();
                    if (ext == ".iso" || ext == ".cue")
                    {
                        var disc = ext == ".iso" ? Disc.FromIsoPath(path) : Disc.FromCuePath(path, new CueBinPrefs());
                        var hash = disc.GetHash();
                        game = Database.CheckDatabase(hash);
                        if (game == null)
                        {
                            // try to use our wizard methods
                            game = new GameInfo {
                                Name = Path.GetFileNameWithoutExtension(file.Name), Hash = hash
                            };

                            switch (disc.DetectDiscType())
                            {
                            case DiscType.SegaSaturn:
                                game.System = "SAT";
                                break;

                            case DiscType.SonyPSP:
                                game.System = "PSP";
                                break;

                            case DiscType.SonyPSX:
                                game.System = "PSX";
                                break;

                            case DiscType.MegaCD:
                                game.System = "GEN";
                                break;

                            case DiscType.TurboCD:
                            case DiscType.UnknownCDFS:
                            case DiscType.UnknownFormat:
                            default:                                     // PCECD was bizhawk's first CD core,
                                // and during that time, all CDs were blindly sent to it
                                // so this prevents regressions
                                game.System = "PCECD";
                                break;
                            }
                        }

                        switch (game.System)
                        {
                        case "GEN":
                            var genesis = new GPGX(
                                nextComm, null, disc, "GEN", GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>());
                            nextEmulator = genesis;
                            break;

                        case "SAT":
                            nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings <Yabause>());
                            break;

                        case "PSP":
                            nextEmulator = new PSP(nextComm, file.Name);
                            break;

                        case "PSX":
                            nextEmulator = new Octoshock(nextComm);
                            (nextEmulator as Octoshock).LoadCuePath(file.CanonicalFullPath);
                            nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
                            break;

                        case "PCE":
                        case "PCECD":
                            nextEmulator = new PCEngine(nextComm, game, disc, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>());
                            break;
                        }
                    }
                    else if (file.Extension.ToLower() == ".xml")
                    {
                        try
                        {
                            var xmlGame = XmlGame.Create(file);                             // if load fails, are we supposed to retry as a bsnes XML????????
                            game = xmlGame.GI;

                            switch (game.System)
                            {
                            case "DGB":
                                var left  = Database.GetGameInfo(xmlGame.Assets["LeftRom"], "left.gb");
                                var right = Database.GetGameInfo(xmlGame.Assets["RightRom"], "right.gb");
                                nextEmulator = new GambatteLink(
                                    nextComm,
                                    left,
                                    xmlGame.Assets["LeftRom"],
                                    right,
                                    xmlGame.Assets["RightRom"],
                                    GetCoreSettings <GambatteLink>(),
                                    GetCoreSyncSettings <GambatteLink>(),
                                    Deterministic);

                                // other stuff todo
                                break;

                            default:
                                return(false);
                            }
                        }
                        catch (Exception ex)
                        {
                            DoLoadErrorCallback(ex.ToString(), "DGB", LoadErrorType.XML);
                            return(false);
                        }
                    }
                    else                     // most extensions
                    {
                        rom = new RomGame(file);

                        if (string.IsNullOrEmpty(rom.GameInfo.System))
                        {
                            // Has the user picked a preference for this extension?
                            if (PreferredPlatformIsDefined(rom.Extension.ToLower()))
                            {
                                rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLower()];
                            }
                            else if (ChoosePlatform != null)
                            {
                                rom.GameInfo.System = ChoosePlatform(rom);
                            }
                        }

                        game = rom.GameInfo;

                        var isXml = false;

                        // other xml has already been handled
                        if (file.Extension.ToLower() == ".xml")
                        {
                            game.System = "SNES";
                            isXml       = true;
                        }

                        switch (game.System)
                        {
                        case "SNES":
                            if (Global.Config.SNES_InSnes9x && VersionInfo.DeveloperBuild)
                            {
                                var snes = new Emulation.Cores.Nintendo.SNES9X.Snes9x(nextComm, rom.FileData);
                                nextEmulator = snes;
                            }
                            else
                            {
                                // need to get rid of this hack at some point
                                ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", String.Empty));                                         // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
                                var romData = isXml ? null : rom.FileData;
                                var xmlData = isXml ? rom.FileData : null;
                                var snes    = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                nextEmulator = snes;
                            }

                            RACore.OnLoad(RAConsoleID.SNES, rom.GameInfo.Name, rom.GameInfo.Hash);

                            break;

                        case "SMS":
                        case "SG":
                        case "GG":
                            nextEmulator = new SMS(nextComm, game, rom.RomData, GetCoreSettings <SMS>(), GetCoreSyncSettings <SMS>());
                            RACore.OnLoad(RAConsoleID.MasterSystem, rom.GameInfo.Name, rom.GameInfo.Hash);
                            break;

                        case "A26":
                            nextEmulator = new Atari2600(
                                nextComm,
                                game,
                                rom.FileData,
                                GetCoreSettings <Atari2600>(),
                                GetCoreSyncSettings <Atari2600>());
                            break;

                        case "PCE":
                        case "PCECD":
                        case "SGX":
                            nextEmulator = new PCEngine(nextComm, game, rom.RomData, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>());
                            RACore.OnLoad(RAConsoleID.PCEngine, rom.GameInfo.Name, rom.GameInfo.Hash);
                            break;

                        case "GEN":
                            nextEmulator = new GPGX(nextComm, rom.RomData, null, "GEN", GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>());
                            RACore.OnLoad(RAConsoleID.MegaDrive, rom.GameInfo.Name, rom.GameInfo.Hash);
                            break;

                        case "TI83":
                            nextEmulator = new TI83(nextComm, game, rom.RomData, GetCoreSettings <TI83>());
                            break;

                        case "NES":
                            if (!Global.Config.NES_InQuickNES || forceAccurateCore)
                            {
                                nextEmulator = new NES(
                                    nextComm,
                                    game,
                                    rom.FileData,
                                    GetCoreSettings <NES>(),
                                    GetCoreSyncSettings <NES>());
                            }
                            else
                            {
                                nextEmulator = new QuickNES(nextComm, rom.FileData, GetCoreSettings <QuickNES>());
                            }

                            RACore.OnLoad(RAConsoleID.NES, rom.GameInfo.Name, rom.GameInfo.Hash);
                            break;

                        case "GB":
                        case "GBC":
                            if (!Global.Config.GB_AsSGB)
                            {
                                nextEmulator = new Gameboy(
                                    nextComm,
                                    game,
                                    rom.FileData,
                                    GetCoreSettings <Gameboy>(),
                                    GetCoreSyncSettings <Gameboy>(),
                                    Deterministic);
                            }
                            else
                            {
                                try
                                {
                                    game.System = "SNES";
                                    game.AddOption("SGB");
                                    var snes = new LibsnesCore(game, rom.FileData, Deterministic, null, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>());
                                    nextEmulator = snes;
                                }
                                catch
                                {
                                    // failed to load SGB bios or game does not support SGB mode.
                                    // To avoid catch-22, disable SGB mode
                                    Global.Config.GB_AsSGB = false;
                                    throw;
                                }
                            }

                            if (game.System == "GB")
                            {
                                RACore.OnLoad(RAConsoleID.Gameboy, rom.GameInfo.Name, rom.GameInfo.Hash);
                            }
                            else if (game.System == "GBC")
                            {
                                RACore.OnLoad(RAConsoleID.GameboyColor, rom.GameInfo.Name, rom.GameInfo.Hash);
                            }

                            break;

                        case "Coleco":
                            nextEmulator = new ColecoVision(nextComm, game, rom.RomData, GetCoreSyncSettings <ColecoVision>());
                            break;

                        case "INTV":
                            nextEmulator = new Intellivision(nextComm, game, rom.RomData);
                            break;

                        case "A78":
                            var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv");
                            nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath);
                            break;

                        case "C64":
                            var c64 = new C64(nextComm, game, rom.RomData, rom.Extension);
                            nextEmulator = c64;
                            break;

                        case "GBA":
                            if (false)
                            {
                                //var gba = new GBA(nextComm);
                                //gba.Load(rom.RomData);
                                //nextEmulator = gba;
                            }
                            else
                            {
                                var gba = new VBANext(rom.RomData, nextComm);
                                nextEmulator = gba;

                                RACore.OnLoad(RAConsoleID.GameboyAdvance, rom.GameInfo.Name, rom.GameInfo.Hash);
                            }
                            break;

                        case "N64":
                            nextEmulator = new N64(nextComm, game, rom.RomData, GetCoreSettings <N64>(), GetCoreSyncSettings <N64>());
                            RACore.OnLoad(RAConsoleID.Nintendo64, rom.GameInfo.Name, rom.GameInfo.Hash);
                            break;

                        case "WSWAN":
                            nextEmulator = new WonderSwan(nextComm, rom.RomData, Deterministic,
                                                          GetCoreSettings <WonderSwan>(), GetCoreSyncSettings <WonderSwan>());
                            break;

                        case "DEBUG":
                            if (VersionInfo.DeveloperBuild)
                            {
                                nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData);
                            }

                            break;
                        }
                    }

                    if (nextEmulator == null)
                    {
                        DoLoadErrorCallback("No core could load the rom.", null);
                        return(false);
                    }
                }
                catch (Exception ex)
                {
                    string system = null;
                    if (game != null)
                    {
                        system = game.System;
                    }

                    // Specific hack here, as we get more cores of the same system, this isn't scalable
                    if (ex is UnsupportedMapperException)
                    {
                        return(LoadRom(path, nextComm, forceAccurateCore: true));
                    }
                    else if (ex is MissingFirmwareException)
                    {
                        DoLoadErrorCallback(ex.Message, system, LoadErrorType.MissingFirmware);
                    }
                    else if (ex is CGBNotSupportedException)
                    {
                        // Note: GB as SGB was set to false by this point, otherwise we would want to do it here
                        DoMessageCallback("Failed to load a GB rom in SGB mode.  Disabling SGB Mode.");
                        return(LoadRom(path, nextComm));
                    }
                    else
                    {
                        DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system);
                    }

                    return(false);
                }

                Rom            = rom;
                LoadedEmulator = nextEmulator;
                Game           = game;
                return(true);
            }
        }