diff --git a/BizHawk.Client.Common/BizHawk.Client.Common.csproj b/BizHawk.Client.Common/BizHawk.Client.Common.csproj index d59a5d43ea..10e8a7369e 100644 --- a/BizHawk.Client.Common/BizHawk.Client.Common.csproj +++ b/BizHawk.Client.Common/BizHawk.Client.Common.csproj @@ -150,6 +150,7 @@ + diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs new file mode 100644 index 0000000000..3a29eed8af --- /dev/null +++ b/BizHawk.Client.Common/RomLoader.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.DiscSystem; +using System.IO; +using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; +using BizHawk.Emulation.Cores.Sega.Saturn; +using BizHawk.Emulation.Cores.Sony.PSP; +using BizHawk.Emulation.Cores.Sony.PSX; +using BizHawk.Emulation.Cores.PCEngine; +using BizHawk.Emulation.Cores.Nintendo.Gameboy; +using BizHawk.Emulation.Cores.Nintendo.SNES; +using BizHawk.Emulation.Cores.Sega.MasterSystem; +using BizHawk.Emulation.Cores.Nintendo.NES; +using BizHawk.Emulation.Cores.Intellivision; +using BizHawk.Emulation.Cores.ColecoVision; +using BizHawk.Emulation.Cores.Nintendo.GBA; +using BizHawk.Emulation.Cores.Atari.Atari7800; +using BizHawk.Emulation.Cores.Computers.Commodore64; +using BizHawk.Emulation.Cores.Calculators; +using BizHawk.Emulation.Cores.Atari.Atari2600; +using BizHawk.Emulation.Cores.Nintendo.N64; + +namespace BizHawk.Client.Common +{ + public class RomLoader + { + #region SNES specific stuff - clean up or move elsewhere + + private readonly Dictionary _snesPrepared = new Dictionary(); + + // Contains a mapping: profilename->exepath ; or null if the exe wasnt available + private string SNES_Prepare(string profile) + { + SNES_Check(profile); + if (_snesPrepared[profile] == null) + { + throw new InvalidOperationException("Couldn't locate the executable for SNES emulation for profile: " + profile + ". Please make sure you're using a fresh dearchive of a BizHawk distribution."); + } + + return _snesPrepared[profile]; + } + + private void SNES_Check(string profile) + { + if (_snesPrepared.ContainsKey(profile)) + { + return; + } + + const string bits = "32"; + + // disabled til it works + // if (Win32.Is64BitOperatingSystem) + // bits = "64"; + var exename = "libsneshawk-" + bits + "-" + profile.ToLower() + ".exe"; + var thisDir = PathManager.GetExeDirectoryAbsolute(); + var exePath = Path.Combine(thisDir, exename); + + if (!File.Exists(exePath)) + { + exePath = Path.Combine(Path.Combine(thisDir, "dll"), exename); + } + + if (!File.Exists(exePath)) + { + exePath = null; + } + + _snesPrepared[profile] = exePath; + } + + #endregion + + #region N64 specific stuff - clean up or move elsewhere + + private static VideoPluginSettings N64GenerateVideoSettings(GameInfo game, bool hasmovie) + { + var pluginToUse = String.Empty; + + if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN)) + { + pluginToUse = Global.MovieSession.Movie.Header[HeaderKeys.VIDEOPLUGIN]; + } + + if (pluginToUse == string.Empty || (pluginToUse != "Rice" && pluginToUse != "Glide64")) + { + pluginToUse = Global.Config.N64VidPlugin; + } + + var video_settings = new VideoPluginSettings(pluginToUse, Global.Config.N64VideoSizeX, Global.Config.N64VideoSizeY); + + if (pluginToUse == "Rice") + { + Global.Config.RicePlugin.FillPerGameHacks(game); + video_settings.Parameters = Global.Config.RicePlugin.GetPluginSettings(); + } + else if (pluginToUse == "Glide64") + { + Global.Config.GlidePlugin.FillPerGameHacks(game); + video_settings.Parameters = Global.Config.GlidePlugin.GetPluginSettings(); + } + else if (pluginToUse == "Glide64mk2") + { + Global.Config.Glide64mk2Plugin.FillPerGameHacks(game); + video_settings.Parameters = Global.Config.Glide64mk2Plugin.GetPluginSettings(); + } + + if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN)) + { + var settings = new List(video_settings.Parameters.Keys); + foreach (var setting in settings) + { + if (Global.MovieSession.Movie.Header.ContainsKey(setting)) + { + var Value = Global.MovieSession.Movie.Header[setting]; + if (video_settings.Parameters[setting] is bool) + { + try + { + video_settings.Parameters[setting] = bool.Parse(Value); + } + catch { } + } + else if (video_settings.Parameters[setting] is int) + { + try + { + video_settings.Parameters[setting] = int.Parse(Value); + } + catch { } + } + } + } + } + + return video_settings; + } + + #endregion + + public RomLoader() + { + Deterministic = true; + } + + // TODO: reconsider the need for exposing these; + public IEmulator LoadedEmulator { get; private set; } + public CoreComm NextComm { get; private set; } + public GameInfo Game { get; private set; } + public RomGame Rom { get; private set; } + public string CanonicalFullPath { get; private set; } + + public bool Deterministic { get; private set; } + + public class RomErrorArgs + { + // TODO: think about naming here, what to pass, a lot of potential good information about what went wrong could go here! + public RomErrorArgs(string message, string systemId) + { + Message = message; + AttemptedCoreLoad = systemId; + } + + public string Message { get; private set; } + public string AttemptedCoreLoad { get; private set; } + } + + public delegate void LoadErrorEventHandler(object sener, RomErrorArgs e); + public event LoadErrorEventHandler OnLoadError; + + public Func ChooseArchive; + + public Action CoreCommMessageCallback; // TODO: eww, do we have to do this? + + private int? HandleArchive(HawkFile file) + { + if (ChooseArchive != null) + { + return ChooseArchive(file); + } + + return null; + } + + private void ThrowLoadError(string message, string systemId) + { + if (OnLoadError != null) + { + OnLoadError(this, new RomErrorArgs(message, systemId)); + } + } + + // TODO I'm in mainform.cs and here, move me to a common place that both can call, static method on the config object? + private void CommitCoreSettingsToConfig() + { + // save settings object + Type t = Global.Emulator.GetType(); + Global.Config.PutCoreSettings(Global.Emulator.GetSettings(), t); + + // don't trample config with loaded-from-movie settings + if (!Global.MovieSession.Movie.IsActive) + { + Global.Config.PutCoreSyncSettings(Global.Emulator.GetSyncSettings(), t); + } + } + + // TODO: the hasMovie hack should be obsoleted by the standardized movie sync setting saving/loading + public bool LoadRom(string path, bool hasmovie = 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" }; + + // 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 = ChooseArchive(file); + if (result.HasValue) + { + file.BindArchiveMember(result.Value); + } + else + { + return false; + } + } + + IEmulator nextEmulator = null; + RomGame rom = null; + GameInfo game = null; + var nextComm = new CoreComm(CoreCommMessageCallback); + CoreFileProvider.SyncCoreCommInputSignals(nextComm); + + // this also happens in CloseGame(). but it needs to happen here since if we're restarting with the same core, + // any settings changes that we made need to make it back to config before we try to instantiate that core with + // the new settings objects + CommitCoreSettingsToConfig(); + + 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", Global.Config.GetCoreSyncSettings()); + nextEmulator = genesis; + } + break; + case "SAT": + { + var saturn = new Yabause(nextComm, disc, Global.Config.SaturnUseGL); + nextEmulator = saturn; + } + break; + case "PSP": + { + var psp = new PSP(nextComm, file.Name); + nextEmulator = psp; + } + break; + case "PSX": + { + var psx = new Octoshock(nextComm); + nextEmulator = psx; + psx.LoadCuePath(file.CanonicalFullPath); + nextEmulator.CoreComm.RomStatusDetails = "PSX etc."; + } + break; + case "PCE": + case "PCECD": + { + var biosPath = Global.FirmwareManager.Request("PCECD", "Bios"); + if (File.Exists(biosPath) == false) + { + ThrowLoadError("PCE-CD System Card not found. Please check the BIOS path in Config->Paths->PC Engine." + , game.System); + return false; + } + + rom = new RomGame(new HawkFile(biosPath)); + + if (rom.GameInfo.Status == RomStatus.BadDump) + { + ThrowLoadError( + "The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n" + + "It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!" + , game.System); + } + else if (rom.GameInfo.NotInDatabase) + { + ThrowLoadError( + "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom." + , game.System); + } + else if (rom.GameInfo["BIOS"] == false) + { + ThrowLoadError( + "The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom." + , game.System); + } + + if (rom.GameInfo["SuperSysCard"]) + { + game.AddOption("SuperSysCard"); + } + + if (game["NeedSuperSysCard"] && game["SuperSysCard"] == false) + { + ThrowLoadError( + "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in Config->Paths->PC Engine." + , game.System); + } + + game.FirmwareHash = Util.BytesToHexString(System.Security.Cryptography.SHA1.Create().ComputeHash(rom.RomData)); + nextEmulator = new PCEngine(nextComm, game, disc, rom.RomData, Global.Config.GetCoreSettings()); + break; + } + } + } + else if (file.Extension.ToLower() == ".xml") + { + try + { + var XMLG = XmlGame.Create(file); // if load fails, are we supposed to retry as a bsnes XML???????? + game = XMLG.GI; + + switch (game.System) + { + case "DGB": + + var L = Database.GetGameInfo(XMLG.Assets["LeftRom"], "left.gb"); + var R = Database.GetGameInfo(XMLG.Assets["RightRom"], "right.gb"); + + var gbl = new GambatteLink(nextComm, L, XMLG.Assets["LeftRom"], R, XMLG.Assets["RightRom"], + Global.Config.GetCoreSettings(), + Global.Config.GetCoreSyncSettings()); + nextEmulator = gbl; + + // other stuff todo + break; + + default: + return false; + } + } + catch (Exception ex) + { + ThrowLoadError(ex.ToString(), "XMLGame Load Error"); // TODO: don't pass in XMLGame Load Error as a system ID + } + } + else // most extensions + { + rom = new RomGame(file); + game = rom.GameInfo; + + bool isXml = false; + + // other xml has already been handled + if (file.Extension.ToLower() == ".xml") + { + game.System = "SNES"; + isXml = true; + } + + switch (game.System) + { + case "SNES": + { + game.System = "SNES"; + nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile); + + // 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 snes = new LibsnesCore(nextComm); + nextEmulator = snes; + byte[] romData = isXml ? null : rom.FileData; + byte[] xmlData = isXml ? rom.FileData : null; + snes.Load(game, romData, Deterministic, xmlData); + } + break; + case "SMS": + case "SG": + case "GG": + nextEmulator = new SMS(nextComm, game, rom.RomData, Global.Config.GetCoreSettings(), Global.Config.GetCoreSyncSettings()); + break; + case "A26": + nextEmulator = new Atari2600(nextComm, game, rom.FileData, + Global.Config.GetCoreSettings(), + Global.Config.GetCoreSyncSettings()); + break; + case "PCE": + case "PCECD": + case "SGX": + nextEmulator = new PCEngine(nextComm, game, rom.RomData, Global.Config.GetCoreSettings()); + break; + case "GEN": + { + // nextEmulator = new Genesis(nextComm, game, rom.RomData); + nextEmulator = new GPGX(nextComm, rom.RomData, null, "GEN", Global.Config.GetCoreSyncSettings()); + break; + } + case "TI83": + nextEmulator = new TI83(nextComm, game, rom.RomData); + break; + case "NES": + nextEmulator = new NES(nextComm, game, rom.FileData, + Global.Config.GetCoreSettings(), + Global.MovieSession.Movie.Header.BoardProperties); + break; + case "GB": + case "GBC": + if (!Global.Config.GB_AsSGB) + { + var gb = new Gameboy(nextComm, game, rom.FileData, + Global.Config.GetCoreSettings(), + Global.Config.GetCoreSyncSettings()); + nextEmulator = gb; + } + else + { + try + { + game.System = "SNES"; + game.AddOption("SGB"); + nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile); + var snes = new LibsnesCore(nextComm); + nextEmulator = snes; + snes.Load(game, rom.FileData, Deterministic, null); + } + catch + { + // failed to load SGB bios. to avoid catch-22, disable SGB mode + ThrowLoadError("Failed to load a GB rom in SGB mode. Disabling SGB Mode." + , game.System); + Global.Config.GB_AsSGB = false; + throw; + } + } + break; + case "Coleco": + { + throw new Exception("Natt needs to refactor this!"); + //var c = new ColecoVision(nextComm, game, rom.RomData, Global.Config.ColecoSkipBiosIntro); + //nextEmulator = c; + } + break; + case "INTV": + { + var intv = new Intellivision(nextComm, game, rom.RomData); + nextEmulator = intv; + } + break; + case "A78": + var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv"); + var a78 = new Atari7800(nextComm, game, rom.RomData, gamedbpath); + nextEmulator = a78; + break; + case "C64": + C64 c64 = new C64(nextComm, game, rom.RomData, rom.Extension); + c64.HardReset(); + nextEmulator = c64; + break; + case "GBA": + if (VersionInfo.INTERIM) + { + GBA gba = new GBA(nextComm); + gba.Load(rom.RomData); + nextEmulator = gba; + } + break; + case "N64": + Global.Game = game; + var video_settings = N64GenerateVideoSettings(game, hasmovie); + int SaveType = 0; + if (game.OptionValue("SaveType") == "EEPROM_16K") + { + SaveType = 1; + } + nextEmulator = new N64(nextComm, game, rom.RomData, video_settings, SaveType); + break; + + case "DEBUG": + if (VersionInfo.INTERIM) + { + nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData); + } + break; + } + } + + if (nextEmulator == null) + { + ThrowLoadError("No core could load the rom.", "NULL"); + return false; + } + } + catch (Exception ex) + { + ThrowLoadError("Exception during loadgame:\n\n" + ex, "NULL"); + return false; + } + Rom = rom; + LoadedEmulator = nextEmulator; + NextComm = nextComm; + Game = game; + CanonicalFullPath = file.CanonicalFullPath; + return true; + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 481b88a1b8..3682982d8f 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -970,7 +970,6 @@ namespace BizHawk.Client.EmuHawk private Control _renderTarget; private RetainedViewportPanel _retainedPanel; private readonly SaveSlotManager _stateSlots = new SaveSlotManager(); - private readonly Dictionary _snesPrepared = new Dictionary(); // AVI/WAV state private IVideoWriter _currAviWriter; @@ -1614,47 +1613,6 @@ namespace BizHawk.Client.EmuHawk } } - // Contains a mapping: profilename->exepath ; or null if the exe wasnt available - private string SNES_Prepare(string profile) - { - SNES_Check(profile); - if (_snesPrepared[profile] == null) - { - throw new InvalidOperationException("Couldn't locate the executable for SNES emulation for profile: " + profile + ". Please make sure you're using a fresh dearchive of a BizHawk distribution."); - } - - return _snesPrepared[profile]; - } - - private void SNES_Check(string profile) - { - if (_snesPrepared.ContainsKey(profile)) - { - return; - } - - const string bits = "32"; - - // disabled til it works - // if (Win32.Is64BitOperatingSystem) - // bits = "64"; - var exename = "libsneshawk-" + bits + "-" + profile.ToLower() + ".exe"; - var thisDir = PathManager.GetExeDirectoryAbsolute(); - var exePath = Path.Combine(thisDir, exename); - - if (!File.Exists(exePath)) - { - exePath = Path.Combine(Path.Combine(thisDir, "dll"), exename); - } - - if (!File.Exists(exePath)) - { - exePath = null; - } - - _snesPrepared[profile] = exePath; - } - private void SyncPresentationMode() { GlobalWin.DisplayManager.Suspend(); @@ -1861,69 +1819,6 @@ namespace BizHawk.Client.EmuHawk GlobalWin.OSD.AddMessage("Slot " + Global.Config.SaveSlot + " selected."); } - private static VideoPluginSettings N64GenerateVideoSettings(GameInfo game, bool hasmovie) - { - var pluginToUse = String.Empty; - - if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN)) - { - pluginToUse = Global.MovieSession.Movie.Header[HeaderKeys.VIDEOPLUGIN]; - } - - if (pluginToUse == string.Empty || (pluginToUse != "Rice" && pluginToUse != "Glide64")) - { - pluginToUse = Global.Config.N64VidPlugin; - } - - var video_settings = new VideoPluginSettings(pluginToUse, Global.Config.N64VideoSizeX, Global.Config.N64VideoSizeY); - - if (pluginToUse == "Rice") - { - Global.Config.RicePlugin.FillPerGameHacks(game); - video_settings.Parameters = Global.Config.RicePlugin.GetPluginSettings(); - } - else if (pluginToUse == "Glide64") - { - Global.Config.GlidePlugin.FillPerGameHacks(game); - video_settings.Parameters = Global.Config.GlidePlugin.GetPluginSettings(); - } - else if (pluginToUse == "Glide64mk2") - { - Global.Config.Glide64mk2Plugin.FillPerGameHacks(game); - video_settings.Parameters = Global.Config.Glide64mk2Plugin.GetPluginSettings(); - } - - if (hasmovie && Global.MovieSession.Movie.Header[HeaderKeys.PLATFORM] == "N64" && Global.MovieSession.Movie.Header.ContainsKey(HeaderKeys.VIDEOPLUGIN)) - { - var settings = new List(video_settings.Parameters.Keys); - foreach (var setting in settings) - { - if (Global.MovieSession.Movie.Header.ContainsKey(setting)) - { - var Value = Global.MovieSession.Movie.Header[setting]; - if (video_settings.Parameters[setting] is bool) - { - try - { - video_settings.Parameters[setting] = bool.Parse(Value); - } - catch { } - } - else if (video_settings.Parameters[setting] is int) - { - try - { - video_settings.Parameters[setting] = int.Parse(Value); - } - catch { } - } - } - } - } - - return video_settings; - } - private void Render() { var video = Global.Emulator.VideoProvider; @@ -2980,356 +2875,38 @@ namespace BizHawk.Client.EmuHawk MessageBox.Show(this, message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } - public bool LoadRom(string path, bool deterministicemulation = false, bool hasmovie = false) // Move to client.common + private void ShowLoadError(object sender, RomLoader.RomErrorArgs e) { - if (path == null) + MessageBox.Show(this, e.Message, e.AttemptedCoreLoad + " load warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + // Still needs a good bit of refactoring + public bool LoadRom(string path, bool deterministicemulation = false, bool hasmovie = false) + { + RomLoader loader = new RomLoader(); + loader.ChooseArchive = LoadArhiveChooser; + loader.CoreCommMessageCallback = ShowMessageCoreComm; + loader.OnLoadError += ShowLoadError; + var result = loader.LoadRom(path, hasmovie); + + if (result) { - return false; - } + var nextEmulator = loader.LoadedEmulator; // TODO: just reference the property and get rid of this + var nextComm = loader.NextComm; // Ditto + var game = loader.Game; // Ditto + var rom = loader.Rom; // Ditto + var canonicalPath = loader.CanonicalFullPath; - 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" }; - - // 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) + if (loader.LoadedEmulator is Yabause) { - return false; + SaturnSetPrefs(loader.LoadedEmulator as Yabause); } - - // try binding normal rom extensions first - if (!file.IsBound) + else if (loader.LoadedEmulator is TI83) { - file.BindSoleItemOf(romExtensions); - } - - // if we have an archive and need to bind something, then pop the dialog - if (file.IsArchive && !file.IsBound) - { - var ac = new ArchiveChooser(file); - if (ac.ShowDialog(this) == DialogResult.OK) + if (Global.Config.TI83autoloadKeyPad) { - file.BindArchiveMember(ac.SelectedMemberIndex); + GlobalWin.Tools.Load(); } - else - { - return false; - } - } - - IEmulator nextEmulator = null; - RomGame rom = null; - GameInfo game = null; - var nextComm = new CoreComm(ShowMessageCoreComm); - CoreFileProvider.SyncCoreCommInputSignals(nextComm); - - // this also happens in CloseGame(). but it needs to happen here since if we're restarting with the same core, - // any settings changes that we made need to make it back to config before we try to instantiate that core with - // the new settings objects - CommitCoreSettingsToConfig(); - - 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", GetCoreSyncSettings()); - nextEmulator = genesis; - } - break; - case "SAT": - { - var saturn = new Yabause(nextComm, disc, Global.Config.SaturnUseGL); - nextEmulator = saturn; - SaturnSetPrefs(saturn); - } - break; - case "PSP": - { - var psp = new PSP(nextComm, file.Name); - nextEmulator = psp; - } - break; - case "PSX": - { - var psx = new Octoshock(nextComm); - nextEmulator = psx; - psx.LoadCuePath(file.CanonicalFullPath); - nextEmulator.CoreComm.RomStatusDetails = "PSX etc."; - } - break; - case "PCE": - case "PCECD": - { - var biosPath = Global.FirmwareManager.Request("PCECD", "Bios"); - if (File.Exists(biosPath) == false) - { - MessageBox.Show("PCE-CD System Card not found. Please check the BIOS path in Config->Paths->PC Engine."); - return false; - } - - rom = new RomGame(new HawkFile(biosPath)); - - if (rom.GameInfo.Status == RomStatus.BadDump) - { - MessageBox.Show( - "The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n" - + "It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!"); - } - else if (rom.GameInfo.NotInDatabase) - { - MessageBox.Show( - "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom."); - } - else if (rom.GameInfo["BIOS"] == false) - { - MessageBox.Show( - "The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom."); - } - - if (rom.GameInfo["SuperSysCard"]) - { - game.AddOption("SuperSysCard"); - } - - if (game["NeedSuperSysCard"] && game["SuperSysCard"] == false) - { - MessageBox.Show( - "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in Config->Paths->PC Engine."); - } - - game.FirmwareHash = Util.BytesToHexString(System.Security.Cryptography.SHA1.Create().ComputeHash(rom.RomData)); - nextEmulator = new PCEngine(nextComm, game, disc, rom.RomData, Global.Config.GetCoreSettings()); - break; - } - } - } - else if (file.Extension.ToLower() == ".xml") - { - try - { - var XMLG = XmlGame.Create(file); // if load fails, are we supposed to retry as a bsnes XML???????? - game = XMLG.GI; - - switch (game.System) - { - case "DGB": - - var L = Database.GetGameInfo(XMLG.Assets["LeftRom"], "left.gb"); - var R = Database.GetGameInfo(XMLG.Assets["RightRom"], "right.gb"); - - var gbl = new GambatteLink(nextComm, L, XMLG.Assets["LeftRom"], R, XMLG.Assets["RightRom"], - Global.Config.GetCoreSettings(), - GetCoreSyncSettings()); - nextEmulator = gbl; - - // other stuff todo - break; - - default: - return false; - } - } - catch (Exception ex) - { - MessageBox.Show(ex.ToString(), "XMLGame Load Error"); - } - } - else // most extensions - { - rom = new RomGame(file); - game = rom.GameInfo; - - bool isXml = false; - - // other xml has already been handled - if (file.Extension.ToLower() == ".xml") - { - game.System = "SNES"; - isXml = true; - } - - switch (game.System) - { - case "SNES": - { - game.System = "SNES"; - nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile); - - // 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 snes = new LibsnesCore(nextComm); - nextEmulator = snes; - byte[] romData = isXml ? null : rom.FileData; - byte[] xmlData = isXml ? rom.FileData : null; - snes.Load(game, romData, deterministicemulation, xmlData); - } - break; - case "SMS": - case "SG": - case "GG": - nextEmulator = new SMS(nextComm, game, rom.RomData, Global.Config.GetCoreSettings(), GetCoreSyncSettings()); - break; - case "A26": - nextEmulator = new Atari2600(nextComm, game, rom.FileData, - Global.Config.GetCoreSettings(), - GetCoreSyncSettings()); - break; - case "PCE": - case "PCECD": - case "SGX": - nextEmulator = new PCEngine(nextComm, game, rom.RomData, Global.Config.GetCoreSettings()); - break; - case "GEN": - { - // nextEmulator = new Genesis(nextComm, game, rom.RomData); - nextEmulator = new GPGX(nextComm, rom.RomData, null, "GEN", GetCoreSyncSettings()); - break; - } - case "TI83": - nextEmulator = new TI83(nextComm, game, rom.RomData); - if (Global.Config.TI83autoloadKeyPad) - { - GlobalWin.Tools.Load(); - } - break; - case "NES": - nextEmulator = new NES(nextComm, game, rom.FileData, - Global.Config.GetCoreSettings(), - Global.MovieSession.Movie.Header.BoardProperties); - break; - case "GB": - case "GBC": - if (!Global.Config.GB_AsSGB) - { - var gb = new Gameboy(nextComm, game, rom.FileData, - Global.Config.GetCoreSettings(), - GetCoreSyncSettings()); - nextEmulator = gb; - } - else - { - try - { - game.System = "SNES"; - game.AddOption("SGB"); - nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile); - var snes = new LibsnesCore(nextComm); - nextEmulator = snes; - snes.Load(game, rom.FileData, deterministicemulation, null); - } - catch - { - // failed to load SGB bios. to avoid catch-22, disable SGB mode - ShowMessageCoreComm("Failed to load a GB rom in SGB mode. Disabling SGB Mode."); - Global.Config.GB_AsSGB = false; - throw; - } - } - break; - case "Coleco": - { - var c = new ColecoVision(nextComm, game, rom.RomData, GetCoreSyncSettings()); - nextEmulator = c; - } - break; - case "INTV": - { - var intv = new Intellivision(nextComm, game, rom.RomData); - nextEmulator = intv; - } - break; - case "A78": - var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv"); - var a78 = new Atari7800(nextComm, game, rom.RomData, gamedbpath); - nextEmulator = a78; - break; - case "C64": - C64 c64 = new C64(nextComm, game, rom.RomData, rom.Extension); - c64.HardReset(); - nextEmulator = c64; - break; - case "GBA": - if (VersionInfo.INTERIM) - { - GBA gba = new GBA(nextComm); - // var gba = new GarboDev.GbaManager(nextComm); - gba.Load(rom.RomData); - nextEmulator = gba; - } - break; - case "N64": - Global.Game = game; - var video_settings = N64GenerateVideoSettings(game, hasmovie); - int SaveType = 0; - if (game.OptionValue("SaveType") == "EEPROM_16K") - { - SaveType = 1; - } - nextEmulator = new N64(nextComm, game, rom.RomData, video_settings, SaveType); - break; - - case "DEBUG": - if (VersionInfo.INTERIM) - { - nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData); - } - break; - } - } - - if (nextEmulator == null) - { - throw new Exception("No core could load the rom."); - } - } - catch (Exception ex) - { - MessageBox.Show("Exception during loadgame:\n\n" + ex); - return false; } CloseGame(); @@ -3376,13 +2953,13 @@ namespace BizHawk.Client.EmuHawk // restarts the lua console if a different rom is loaded. // im not really a fan of how this is done.. - if (Global.Config.RecentRoms.Empty || Global.Config.RecentRoms[0] != file.CanonicalFullPath) + if (Global.Config.RecentRoms.Empty || Global.Config.RecentRoms[0] != canonicalPath) { GlobalWin.Tools.Restart(); } - Global.Config.RecentRoms.Add(file.CanonicalFullPath); - JumpLists.AddRecentItem(file.CanonicalFullPath); + Global.Config.RecentRoms.Add(canonicalPath); + JumpLists.AddRecentItem(canonicalPath); if (File.Exists(PathManager.SaveRamPath(game))) { LoadSaveRam(); @@ -3403,7 +2980,7 @@ namespace BizHawk.Client.EmuHawk } } - CurrentlyOpenRom = file.CanonicalFullPath; + CurrentlyOpenRom = canonicalPath; HandlePlatformMenus(); _stateSlots.Clear(); UpdateStatusSlots(); @@ -3419,6 +2996,24 @@ namespace BizHawk.Client.EmuHawk ToolHelpers.UpdateCheatRelatedTools(null, null); return true; } + else + { + return false; + } + } + + // This is probably fine the way it is, but consider refactor + private int? LoadArhiveChooser(HawkFile file) + { + var ac = new ArchiveChooser(file); + if (ac.ShowDialog(this) == DialogResult.OK) + { + return ac.SelectedMemberIndex; + } + else + { + return null; + } } public void SaveState(string name) // Move to client.common