diff --git a/.gitignore b/.gitignore index d1a3a233d2..379422bb23 100644 --- a/.gitignore +++ b/.gitignore @@ -259,3 +259,6 @@ /output/*.manifest /output/dll/*.iobj /output/dll/*.ipdb +/LuaInterface/Lua/src/.libs +/LuaInterface/Lua/src/Release-LUAPERKS +/LuaInterface/Release-LUAPERKS diff --git a/BizHawk.Client.Common/CoreFileProvider.cs b/BizHawk.Client.Common/CoreFileProvider.cs index 5a3c23f987..0a56502f40 100644 --- a/BizHawk.Client.Common/CoreFileProvider.cs +++ b/BizHawk.Client.Common/CoreFileProvider.cs @@ -27,6 +27,16 @@ namespace BizHawk.Client.Common return Path.Combine(PathManager.GetExeDirectoryAbsolute(), "dll"); } + public string GetSaveRAMPath() + { + return PathManager.SaveRamPath(Global.Game); + } + + public string GetGameBasePath() + { + return PathManager.GetGameBasePath(Global.Game); + } + #region EmuLoadHelper api private void FirmwareWarn(string sysID, string firmwareID, bool required, string msg = null) diff --git a/BizHawk.Client.Common/PathManager.cs b/BizHawk.Client.Common/PathManager.cs index 59e96f5337..008b4f841c 100644 --- a/BizHawk.Client.Common/PathManager.cs +++ b/BizHawk.Client.Common/PathManager.cs @@ -257,6 +257,11 @@ namespace BizHawk.Client.Common public static string FilesystemSafeName(GameInfo game) { var filesystemSafeName = game.Name.Replace("|", "+"); + + // zero 06-nov-2015 - regarding the below, i changed my mind. for libretro i want subdirectories here. + var filesystemDir = Path.GetDirectoryName(filesystemSafeName); + filesystemSafeName = Path.GetFileName(filesystemSafeName); + filesystemSafeName = RemoveInvalidFileSystemChars(filesystemSafeName); // zero 22-jul-2012 - i dont think this is used the same way it used to. game.Name shouldnt be a path, so this stuff is illogical. @@ -267,10 +272,10 @@ namespace BizHawk.Client.Common // This hack is to prevent annoying things like Super Mario Bros..bk2 if (filesystemSafeName.EndsWith(".")) { - return filesystemSafeName.Remove(filesystemSafeName.Length - 1, 1); + filesystemSafeName = filesystemSafeName.Remove(filesystemSafeName.Length - 1, 1); } - return filesystemSafeName; + return Path.Combine(filesystemDir, filesystemSafeName); } public static string SaveRamPath(GameInfo game) @@ -287,6 +292,14 @@ namespace BizHawk.Client.Common return Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name) + ".SaveRAM"; } + public static string GetGameBasePath(GameInfo game) + { + var name = FilesystemSafeName(game); + + var pathEntry = Global.Config.PathEntries[game.System, "Base"]; + return MakeAbsolutePath(pathEntry.Path, game.System); + } + public static string GetSaveStatePath(GameInfo game) { var pathEntry = Global.Config.PathEntries[game.System, "Savestates"] ?? @@ -335,6 +348,12 @@ namespace BizHawk.Client.Common return MakeAbsolutePath(pathEntry.Path, game.System); } + public static string GetPathType(string system, string type) + { + var path = PathManager.GetPathEntryWithFallback(type, system).Path; + return MakeAbsolutePath(path, system); + } + public static string ScreenshotPrefix(GameInfo game) { var name = FilesystemSafeName(game); diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index dfe9b9aa62..61da326679 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -179,6 +179,37 @@ namespace BizHawk.Client.Common return false; } + public bool AsLibretro; + + bool HandleArchiveBinding(HawkFile file) + { + 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" }; + + // 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; + } + } + + CanonicalFullPath = file.CanonicalFullPath; + + return true; + } + 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 { @@ -197,39 +228,21 @@ namespace BizHawk.Client.Common 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) + //only try mounting a file if a filename was given + if (!string.IsNullOrEmpty(path)) { - return false; - } + // lets not use this unless we need to + // file.NonArchiveExtensions = romExtensions; + file.Open(path); - // 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 + // if the provided file doesnt even exist, give up! + if (!file.Exists) { 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; @@ -238,8 +251,89 @@ namespace BizHawk.Client.Common try { - var ext = file.Extension.ToLowerInvariant(); - if (ext == ".m3u") + string ext = null; + + if (AsLibretro) + { + //we'll need to generate a game name for purposes of state/saveram pathing etc. + string gameName; + + string codePathPart = Path.GetFileNameWithoutExtension(nextComm.LaunchLibretroCore); + + var retro = new LibRetroEmulator(nextComm, nextComm.LaunchLibretroCore); + nextEmulator = retro; + + if (retro.Description.SupportsNoGame && string.IsNullOrEmpty(path)) + { + //if we are allowed to run NoGame and we dont have a game, boot up the core that way + bool ret = retro.LoadNoGame(); + if (!ret) + { + DoLoadErrorCallback("LibretroNoGame failed to load. This is weird", "Libretro"); + retro.Dispose(); + return false; + } + + //game name == name of core + gameName = codePathPart; + } + else + { + bool ret; + + //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"); + 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()); + } + + 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; + } + + } + + //game name == name of core + extensionless_game_filename + gameName = Path.Combine(codePathPart, Path.GetFileNameWithoutExtension(file.Name)); + } + + game = new GameInfo { Name = gameName, System = "Libretro" }; + + } + 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; @@ -545,13 +639,13 @@ namespace BizHawk.Client.Common PSF psf = new PSF(); psf.Load(path, cbDeflater); nextEmulator = new Octoshock(nextComm, psf, GetCoreSettings(), GetCoreSyncSettings()); - nextEmulator.CoreComm.RomStatusDetails = "It's a PSF, what do you want."; + 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 // most extensions + else if(ext != null) // most extensions { rom = new RomGame(file); @@ -689,13 +783,6 @@ namespace BizHawk.Client.Common case "PSX": nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings(), GetCoreSyncSettings()); nextEmulator.CoreComm.RomStatusDetails = "PSX etc."; - break; - case "DEBUG": - if (VersionInfo.DeveloperBuild) - { - nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData); - } - break; } diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 4f6347c9ab..2e487fe448 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -470,6 +470,7 @@ namespace BizHawk.Client.Common public bool NES_InQuickNES = true; public bool SNES_InSnes9x = false; public bool GBA_UsemGBA = false; + public string LibretroCore; } // These are used in the defctrl.json or wherever diff --git a/BizHawk.Client.Common/config/PathEntry.cs b/BizHawk.Client.Common/config/PathEntry.cs index 9639041b59..b433af2eee 100644 --- a/BizHawk.Client.Common/config/PathEntry.cs +++ b/BizHawk.Client.Common/config/PathEntry.cs @@ -312,6 +312,14 @@ namespace BizHawk.Client.Common new PathEntry { System = "AppleII", SystemDisplayName = "Apple II", Type = "Savestates", Path= Path.Combine(".", "State"), Ordinal = 2 }, new PathEntry { System = "AppleII", SystemDisplayName = "Apple II", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 }, new PathEntry { System = "AppleII", SystemDisplayName = "Apple II", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 }, + + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Base", Path = Path.Combine(".", "Libretro"), Ordinal = 0 }, + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Cores", Path = Path.Combine(".", "Cores"), Ordinal = 1 }, + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Savestates", Path = Path.Combine(".", "State"), Ordinal = 2 }, + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Save RAM", Path = Path.Combine(".", "SaveRAM"), Ordinal = 3 }, + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Screenshots", Path = Path.Combine(".", "Screenshots"), Ordinal = 4 }, + new PathEntry { System = "Libretro", SystemDisplayName = "Libretro", Type = "Cheats", Path = Path.Combine(".", "Cheats"), Ordinal = 5 }, + }; } } diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index 2e30f760c2..a3adff8f2b 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -618,6 +618,13 @@ NameStateForm.cs + + + Form + + + OpenAdvancedChooser.cs + Form @@ -1325,6 +1332,9 @@ NameStateForm.cs Designer + + OpenAdvancedChooser.cs + PlatformChooser.cs @@ -1971,6 +1981,7 @@ + diff --git a/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs b/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs index 9d73c88eeb..ab65a75bd4 100644 --- a/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs +++ b/BizHawk.Client.EmuHawk/Extensions/ToolExtensions.cs @@ -5,15 +5,16 @@ using System.Windows.Forms; using System.Linq; using BizHawk.Common; - using BizHawk.Emulation.Common; using BizHawk.Client.Common; +//todo - add some more options for libretro types + namespace BizHawk.Client.EmuHawk.ToolExtensions { public static class ToolExtensions { - public static ToolStripItem[] RecentMenu(this RecentFiles recent, Action loadFileCallback, bool autoload = false) + public static ToolStripItem[] RecentMenu(this RecentFiles recent, Action loadFileCallback, bool autoload = false, bool romloading = false) { var items = new List(); @@ -26,97 +27,120 @@ namespace BizHawk.Client.EmuHawk.ToolExtensions { 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 temp = filename; - var item = new ToolStripMenuItem { Text = temp }; + var item = new ToolStripMenuItem { Text = caption }; items.Add(item); item.Click += (o, ev) => { - loadFileCallback(temp); + loadFileCallback(path); }; - - //TODO - use standard methods to split filename (hawkfile acquire?) - var hf = new HawkFile(); - hf.Parse(temp); - bool canExplore = true; - if (!File.Exists(hf.FullPathWithoutMember)) - canExplore = false; var tsdd = new ToolStripDropDownMenu(); - if (canExplore) + if (crazyStuff) { - //make a menuitem to show the last modified timestamp - var timestamp = File.GetLastWriteTime(hf.FullPathWithoutMember); - var tsmiTimestamp = new ToolStripLabel { Text = timestamp.ToString() }; + //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; - tsdd.Items.Add(tsmiTimestamp); - tsdd.Items.Add(new ToolStripSeparator()); - - - - if (hf.IsArchive) + if (canExplore) { - //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(temp); }; - tsdd.Items.Add(tsmiCopyCanonicalPath); + //make a menuitem to show the last modified timestamp + var timestamp = File.GetLastWriteTime(hf.FullPathWithoutMember); + var tsmiTimestamp = new ToolStripLabel { Text = timestamp.ToString() }; - var tsmiCopyArchivePath = new ToolStripMenuItem { Text = "Copy Archive Path" }; - tsmiCopyArchivePath.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetText(hf.FullPathWithoutMember); }; - tsdd.Items.Add(tsmiCopyArchivePath); + tsdd.Items.Add(tsmiTimestamp); + tsdd.Items.Add(new ToolStripSeparator()); - var tsmiOpenArchive = new ToolStripMenuItem { Text = "Open &Archive" }; - tsmiOpenArchive.Click += (o, ev) => { System.Diagnostics.Process.Start(hf.FullPathWithoutMember); }; - tsdd.Items.Add(tsmiOpenArchive); + 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 let you copy the path - var tsmiCopyPath = new ToolStripMenuItem { Text = "&Copy Path" }; - tsmiCopyPath.Click += (o, ev) => { System.Windows.Forms.Clipboard.SetText(temp); }; - tsdd.Items.Add(tsmiCopyPath); + //make a menuitem to show the last modified timestamp + var tsmiMissingFile = new ToolStripLabel { Text = "-Missing-" }; + tsdd.Items.Add(tsmiMissingFile); + tsdd.Items.Add(new ToolStripSeparator()); } - tsdd.Items.Add(new ToolStripSeparator()); + } //crazystuff - //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()); - } - - //in either case, make a menuitem to let you remove the path + //in any case, make a menuitem to let you remove the item var tsmiRemovePath = new ToolStripMenuItem { Text = "&Remove" }; - tsmiRemovePath.Click += (o, ev) => { recent.Remove(temp); }; - + tsmiRemovePath.Click += (o, ev) => { recent.Remove(path); }; tsdd.Items.Add(tsmiRemovePath); ////experiment of popping open a submenu. doesnt work well. @@ -134,7 +158,7 @@ namespace BizHawk.Client.EmuHawk.ToolExtensions // tsdd.Show(pos); //}; - //just add it to the submenu for now + //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; diff --git a/BizHawk.Client.EmuHawk/JumpLists.cs b/BizHawk.Client.EmuHawk/JumpLists.cs index a51e65d238..41efac51ca 100644 --- a/BizHawk.Client.EmuHawk/JumpLists.cs +++ b/BizHawk.Client.EmuHawk/JumpLists.cs @@ -24,13 +24,13 @@ namespace BizHawk.Client.EmuHawk /// add an item to the W7+ jumplist /// /// fully qualified path, can include '|' character for archives - public static void AddRecentItem(string fullpath) + public static void AddRecentItem(string fullpath, string title) { - string title; - if (fullpath.Contains('|')) - title = fullpath.Split('|')[1]; - else - title = Path.GetFileName(fullpath); + //string title; + //if (fullpath.Contains('|')) + // title = fullpath.Split('|')[1]; + //else + // title = Path.GetFileName(fullpath); string exepath = Assembly.GetEntryAssembly().Location; diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index 591a3b3134..e27d349756 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -186,6 +186,7 @@ this.gBAWithMGBAToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator(); this.N64VideoPluginSettingsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.setLibretroCoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator(); this.SaveConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.LoadConfigMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -196,6 +197,7 @@ this.RamSearchMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.HexEditorMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.TraceLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CodeDataLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.DebuggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.TAStudioMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MacroToolMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -405,7 +407,7 @@ this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator(); this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.timerMouseIdle = new System.Windows.Forms.Timer(this.components); - this.CodeDataLoggerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.OpenAdvancedMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MainformMenu.SuspendLayout(); this.MainStatusBar.SuspendLayout(); this.MainFormContextMenu.SuspendLayout(); @@ -451,6 +453,7 @@ // FileSubMenu // this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { +<<<<<<< HEAD this.OpenRomMenuItem, this.RecentRomSubMenu, this.CloseRomMenuItem, @@ -465,6 +468,23 @@ this.ScreenshotSubMenu, this.toolStripSeparator4, this.ExitMenuItem}); +======= + this.OpenRomMenuItem, + this.RecentRomSubMenu, + this.OpenAdvancedMenuItem, + this.CloseRomMenuItem, + this.toolStripMenuItem1, + this.SaveStateSubMenu, + this.LoadStateSubMenu, + this.SaveSlotSubMenu, + this.SaveRAMSubMenu, + this.toolStripMenuItem2, + this.MovieSubMenu, + this.AVSubMenu, + this.ScreenshotSubMenu, + this.toolStripSeparator4, + this.ExitMenuItem}); +>>>>>>> refs/remotes/TASVideos/master this.FileSubMenu.Name = "FileSubMenu"; this.FileSubMenu.Size = new System.Drawing.Size(35, 17); this.FileSubMenu.Text = "&File"; @@ -474,8 +494,8 @@ // this.OpenRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; this.OpenRomMenuItem.Name = "OpenRomMenuItem"; - this.OpenRomMenuItem.Size = new System.Drawing.Size(134, 22); - this.OpenRomMenuItem.Text = "Open ROM"; + this.OpenRomMenuItem.Size = new System.Drawing.Size(152, 22); + this.OpenRomMenuItem.Text = "&Open ROM"; this.OpenRomMenuItem.Click += new System.EventHandler(this.OpenRomMenuItem_Click); // // RecentRomSubMenu @@ -484,27 +504,27 @@ this.toolStripSeparator3}); this.RecentRomSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; this.RecentRomSubMenu.Name = "RecentRomSubMenu"; - this.RecentRomSubMenu.Size = new System.Drawing.Size(134, 22); - this.RecentRomSubMenu.Text = "Recent ROM"; + this.RecentRomSubMenu.Size = new System.Drawing.Size(152, 22); + this.RecentRomSubMenu.Text = "&Recent ROM"; this.RecentRomSubMenu.DropDownOpened += new System.EventHandler(this.RecentRomMenuItem_DropDownOpened); // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(57, 6); + this.toolStripSeparator3.Size = new System.Drawing.Size(149, 6); // // CloseRomMenuItem // this.CloseRomMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Close; this.CloseRomMenuItem.Name = "CloseRomMenuItem"; - this.CloseRomMenuItem.Size = new System.Drawing.Size(134, 22); + this.CloseRomMenuItem.Size = new System.Drawing.Size(152, 22); this.CloseRomMenuItem.Text = "&Close ROM"; this.CloseRomMenuItem.Click += new System.EventHandler(this.CloseRomMenuItem_Click); // // toolStripMenuItem1 // this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(131, 6); + this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6); // // SaveStateSubMenu // @@ -522,8 +542,8 @@ this.toolStripSeparator6, this.SaveNamedStateMenuItem}); this.SaveStateSubMenu.Name = "SaveStateSubMenu"; - this.SaveStateSubMenu.Size = new System.Drawing.Size(134, 22); - this.SaveStateSubMenu.Text = "Save State"; + this.SaveStateSubMenu.Size = new System.Drawing.Size(152, 22); + this.SaveStateSubMenu.Text = "&Save State"; this.SaveStateSubMenu.DropDownOpened += new System.EventHandler(this.SaveStateSubMenu_DropDownOpened); // // SaveState1MenuItem @@ -626,8 +646,8 @@ this.toolStripSeparator21, this.AutoloadLastSlotMenuItem}); this.LoadStateSubMenu.Name = "LoadStateSubMenu"; - this.LoadStateSubMenu.Size = new System.Drawing.Size(134, 22); - this.LoadStateSubMenu.Text = "Load State"; + this.LoadStateSubMenu.Size = new System.Drawing.Size(152, 22); + this.LoadStateSubMenu.Text = "&Load State"; this.LoadStateSubMenu.DropDownOpened += new System.EventHandler(this.LoadStateSubMenu_DropDownOpened); // // LoadState1MenuItem @@ -743,8 +763,8 @@ this.SaveToCurrentSlotMenuItem, this.LoadCurrentSlotMenuItem}); this.SaveSlotSubMenu.Name = "SaveSlotSubMenu"; - this.SaveSlotSubMenu.Size = new System.Drawing.Size(134, 22); - this.SaveSlotSubMenu.Text = "Save Slot"; + this.SaveSlotSubMenu.Size = new System.Drawing.Size(152, 22); + this.SaveSlotSubMenu.Text = "Save S&lot"; this.SaveSlotSubMenu.DropDownOpened += new System.EventHandler(this.SaveSlotSubMenu_DropDownOpened); // // SelectSlot0MenuItem @@ -858,21 +878,21 @@ this.FlushSaveRAMMenuItem}); this.SaveRAMSubMenu.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold); this.SaveRAMSubMenu.Name = "SaveRAMSubMenu"; - this.SaveRAMSubMenu.Size = new System.Drawing.Size(134, 22); - this.SaveRAMSubMenu.Text = "Save RAM"; + this.SaveRAMSubMenu.Size = new System.Drawing.Size(152, 22); + this.SaveRAMSubMenu.Text = "Save &RAM"; // // FlushSaveRAMMenuItem // this.FlushSaveRAMMenuItem.Font = new System.Drawing.Font("Tahoma", 8.25F); this.FlushSaveRAMMenuItem.Name = "FlushSaveRAMMenuItem"; - this.FlushSaveRAMMenuItem.Size = new System.Drawing.Size(150, 22); + this.FlushSaveRAMMenuItem.Size = new System.Drawing.Size(152, 22); this.FlushSaveRAMMenuItem.Text = "&Flush Save Ram"; this.FlushSaveRAMMenuItem.Click += new System.EventHandler(this.FlushSaveRAMMenuItem_Click); // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(131, 6); + this.toolStripMenuItem2.Size = new System.Drawing.Size(149, 6); // // MovieSubMenu // @@ -892,8 +912,8 @@ this.FullMovieLoadstatesMenuItem, this.MovieEndSubMenu}); this.MovieSubMenu.Name = "MovieSubMenu"; - this.MovieSubMenu.Size = new System.Drawing.Size(134, 22); - this.MovieSubMenu.Text = "Movie"; + this.MovieSubMenu.Size = new System.Drawing.Size(152, 22); + this.MovieSubMenu.Text = "&Movie"; this.MovieSubMenu.DropDownOpened += new System.EventHandler(this.MovieSubMenu_DropDownOpened); // // ReadonlyMenuItem @@ -1048,8 +1068,8 @@ this.CaptureOSDMenuItem, this.SynclessRecordingMenuItem}); this.AVSubMenu.Name = "AVSubMenu"; - this.AVSubMenu.Size = new System.Drawing.Size(134, 22); - this.AVSubMenu.Text = "AVI/WAV"; + this.AVSubMenu.Size = new System.Drawing.Size(152, 22); + this.AVSubMenu.Text = "&AVI/WAV"; this.AVSubMenu.DropDownOpened += new System.EventHandler(this.AVSubMenu_DropDownOpened); // // RecordAVMenuItem @@ -1097,8 +1117,8 @@ this.toolStripSeparator20, this.ScreenshotCaptureOSDMenuItem1}); this.ScreenshotSubMenu.Name = "ScreenshotSubMenu"; - this.ScreenshotSubMenu.Size = new System.Drawing.Size(134, 22); - this.ScreenshotSubMenu.Text = "Screenshot"; + this.ScreenshotSubMenu.Size = new System.Drawing.Size(152, 22); + this.ScreenshotSubMenu.Text = "Scree&nshot"; this.ScreenshotSubMenu.DropDownOpening += new System.EventHandler(this.ScreenshotSubMenu_DropDownOpening); // // ScreenshotMenuItem @@ -1148,14 +1168,14 @@ // toolStripSeparator4 // this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(131, 6); + this.toolStripSeparator4.Size = new System.Drawing.Size(149, 6); // // ExitMenuItem // this.ExitMenuItem.Name = "ExitMenuItem"; this.ExitMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4))); - this.ExitMenuItem.Size = new System.Drawing.Size(134, 22); - this.ExitMenuItem.Text = "Exit"; + this.ExitMenuItem.Size = new System.Drawing.Size(152, 22); + this.ExitMenuItem.Text = "E&xit"; this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); // // EmulationSubMenu @@ -1735,12 +1755,22 @@ // CoresSubMenu // this.CoresSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { +<<<<<<< HEAD this.GBInSGBMenuItem, this.NesInQuickNESMenuItem, this.SnesWithSnes9xMenuItem, this.gBAWithMGBAToolStripMenuItem, this.toolStripSeparator8, this.N64VideoPluginSettingsMenuItem}); +======= + this.GBInSGBMenuItem, + this.NesInQuickNESMenuItem, + this.SnesWithSnes9xMenuItem, + this.gBAWithMGBAToolStripMenuItem, + this.toolStripSeparator8, + this.N64VideoPluginSettingsMenuItem, + this.setLibretroCoreToolStripMenuItem}); +>>>>>>> refs/remotes/TASVideos/master this.CoresSubMenu.Name = "CoresSubMenu"; this.CoresSubMenu.Size = new System.Drawing.Size(165, 22); this.CoresSubMenu.Text = "Cores"; @@ -1787,6 +1817,13 @@ this.N64VideoPluginSettingsMenuItem.Text = "N64 Video Plugin Settings"; this.N64VideoPluginSettingsMenuItem.Click += new System.EventHandler(this.N64VideoPluginSettingsMenuItem_Click); // + // setLibretroCoreToolStripMenuItem + // + this.setLibretroCoreToolStripMenuItem.Name = "setLibretroCoreToolStripMenuItem"; + this.setLibretroCoreToolStripMenuItem.Size = new System.Drawing.Size(195, 22); + this.setLibretroCoreToolStripMenuItem.Text = "Set Libretro Core"; + this.setLibretroCoreToolStripMenuItem.Click += new System.EventHandler(this.setLibretroCoreToolStripMenuItem_Click); + // // toolStripSeparator10 // this.toolStripSeparator10.Name = "toolStripSeparator10"; @@ -1881,6 +1918,14 @@ this.TraceLoggerMenuItem.Text = "Trace &Logger"; this.TraceLoggerMenuItem.Click += new System.EventHandler(this.TraceLoggerMenuItem_Click); // + // CodeDataLoggerMenuItem + // + this.CodeDataLoggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.cdlogger; + this.CodeDataLoggerMenuItem.Name = "CodeDataLoggerMenuItem"; + this.CodeDataLoggerMenuItem.Size = new System.Drawing.Size(162, 22); + this.CodeDataLoggerMenuItem.Text = "Code-Data Logger"; + this.CodeDataLoggerMenuItem.Click += new System.EventHandler(this.CodeDataLoggerMenuItem_Click); + // // DebuggerMenuItem // this.DebuggerMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Bug; @@ -3580,12 +3625,12 @@ this.timerMouseIdle.Interval = 2000; this.timerMouseIdle.Tick += new System.EventHandler(this.timerMouseIdle_Tick); // - // CodeDataLoggerMenuItem + // OpenAdvancedMenuItem // - this.CodeDataLoggerMenuItem.Name = "CodeDataLoggerMenuItem"; - this.CodeDataLoggerMenuItem.Size = new System.Drawing.Size(162, 22); - this.CodeDataLoggerMenuItem.Text = "Code-Data Logger"; - this.CodeDataLoggerMenuItem.Click += new System.EventHandler(this.CodeDataLoggerMenuItem_Click); + this.OpenAdvancedMenuItem.Name = "OpenAdvancedMenuItem"; + this.OpenAdvancedMenuItem.Size = new System.Drawing.Size(152, 22); + this.OpenAdvancedMenuItem.Text = "Open Ad&vanced"; + this.OpenAdvancedMenuItem.Click += new System.EventHandler(this.OpenAdvancedMenuItem_Click); // // MainForm // @@ -4004,6 +4049,8 @@ private System.Windows.Forms.ToolStripMenuItem C64SettingsMenuItem; private System.Windows.Forms.ToolStripMenuItem customToolToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem CodeDataLoggerMenuItem; + private System.Windows.Forms.ToolStripMenuItem setLibretroCoreToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem OpenAdvancedMenuItem; } } diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index 6d069292af..7b70d50049 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -58,7 +58,7 @@ namespace BizHawk.Client.EmuHawk { RecentRomSubMenu.DropDownItems.Clear(); RecentRomSubMenu.DropDownItems.AddRange( - Global.Config.RecentRoms.RecentMenu(LoadRomFromRecent, true)); + Global.Config.RecentRoms.RecentMenu(LoadRomFromRecent, true, true)); } private void SaveStateSubMenu_DropDownOpened(object sender, EventArgs e) @@ -300,6 +300,61 @@ namespace BizHawk.Client.EmuHawk OpenRom(); } + private void OpenAdvancedMenuItem_Click(object sender, EventArgs e) + { + var oac = new OpenAdvancedChooser(this); + if (oac.ShowHawkDialog() == System.Windows.Forms.DialogResult.Cancel) + return; + + if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchNoGame) + { + var argsNoGame = new LoadRomArgs(); + argsNoGame.OpenAdvanced = new OpenAdvanced_LibretroNoGame(Global.Config.LibretroCore); + LoadRom("", argsNoGame); + return; + } + + var args = new LoadRomArgs(); + + var filter = RomFilter; + + if (oac.Result == OpenAdvancedChooser.Command.RetroLaunchGame) + { + args.OpenAdvanced = new OpenAdvanced_Libretro(); + filter = oac.SuggestedExtensionFilter; + } + else if (oac.Result == OpenAdvancedChooser.Command.ClassicLaunchGame) + args.OpenAdvanced = new OpenAdvanced_OpenRom(); + else throw new InvalidOperationException("Automatic Alpha Sanitizer"); + + + //----------------- + //CLONE OF CODE FROM OpenRom (mostly) + var ofd = new OpenFileDialog + { + InitialDirectory = PathManager.GetRomsPath(Global.Emulator.SystemId), + Filter = filter, + RestoreDirectory = false, + FilterIndex = _lastOpenRomFilter, + Title = "Open Advanced" + }; + + var result = ofd.ShowHawkDialog(); + if (result != DialogResult.OK) + { + return; + } + + var file = new FileInfo(ofd.FileName); + Global.Config.LastRomPath = file.DirectoryName; + _lastOpenRomFilter = ofd.FilterIndex; + //----------------- + + + + LoadRom(file.FullName, args); + } + private void CloseRomMenuItem_Click(object sender, EventArgs e) { CloseRom(); @@ -1130,6 +1185,34 @@ namespace BizHawk.Client.EmuHawk ThrottleMessage(); } + public void RunLibretroCoreChooser() + { + var ofd = new OpenFileDialog(); + + if (Global.Config.LibretroCore != null) + { + ofd.FileName = Path.GetFileName(Global.Config.LibretroCore); + ofd.InitialDirectory = Path.GetDirectoryName(Global.Config.LibretroCore); + } + else + { + ofd.InitialDirectory = PathManager.GetPathType("Libretro", "Cores"); + } + + ofd.RestoreDirectory = true; + ofd.Filter = "Libretro Cores (*.dll)|*.dll"; + + if (ofd.ShowDialog() == DialogResult.Cancel) + return; + + Global.Config.LibretroCore = ofd.FileName; + } + + private void setLibretroCoreToolStripMenuItem_Click(object sender, EventArgs e) + { + RunLibretroCoreChooser(); + } + #endregion #region Tools @@ -1205,6 +1288,11 @@ namespace BizHawk.Client.EmuHawk private void TAStudioMenuItem_Click(object sender, EventArgs e) { + if (!Global.Emulator.CanPollInput()) + { + MessageBox.Show("Current core does not support input polling. TAStudio can't be used."); + return; + } GlobalWin.Tools.Load(); } @@ -2655,7 +2743,9 @@ namespace BizHawk.Client.EmuHawk } else { - LoadRom(filePaths[0]); + var args = new LoadRomArgs(); + args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filePaths[0] }; + LoadRom(filePaths[0],args); } } diff --git a/BizHawk.Client.EmuHawk/MainForm.Movie.cs b/BizHawk.Client.EmuHawk/MainForm.Movie.cs index 5843066a6a..390a607876 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Movie.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Movie.cs @@ -41,7 +41,7 @@ namespace BizHawk.Client.EmuHawk return false; } - LoadRom(CurrentlyOpenRom); + RebootCore(); if (Global.MovieSession.PreviousNES_InQuickNES.HasValue) { diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 5909abd71d..1426f6783a 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -234,9 +234,11 @@ namespace BizHawk.Client.EmuHawk { if (GlobalWin.Tools.AskSave()) { - CloseGame(); + //zero 03-nov-2015 - close game after other steps. tools might need to unhook themselves from a core. Global.MovieSession.Movie.Stop(); GlobalWin.Tools.Close(); + CloseGame(); + //does this need to be last for any particular reason? do tool dialogs persist settings when closing? SaveConfig(); } else @@ -406,11 +408,11 @@ namespace BizHawk.Client.EmuHawk ToggleFullscreen(); } - if(!Global.Game.IsNullInstance) + if (!Global.Game.IsNullInstance) { - if(cmdLoadState != null) + if (cmdLoadState != null) { - LoadState(cmdLoadState,Path.GetFileName(cmdLoadState)); + LoadState(cmdLoadState, Path.GetFileName(cmdLoadState)); } else if (cmdLoadSlot != null) { @@ -538,7 +540,7 @@ namespace BizHawk.Client.EmuHawk protected override void Dispose(bool disposing) { //NOTE: this gets called twice sometimes. once by using() in Program.cs and once from winforms internals when the form is closed... - + if (GlobalWin.DisplayManager != null) { GlobalWin.DisplayManager.Dispose(); @@ -592,7 +594,8 @@ namespace BizHawk.Client.EmuHawk #region Properties - public string CurrentlyOpenRom; + public string CurrentlyOpenRom; //todo - delete me and use only args instead + LoadRomArgs CurrentlyOpenRomArgs; public bool PauseAVI = false; public bool PressFrameAdvance = false; public bool PressRewind = false; @@ -818,21 +821,25 @@ namespace BizHawk.Client.EmuHawk float x = P.X / (float)video.BufferWidth; return new Tuple("WMouse X", x * 20000 - 10000); } - + if (o.Item1 == "WMouse Y") { var P = GlobalWin.DisplayManager.UntransformPoint(new Point(0, (int)o.Item2)); float y = P.Y / (float)video.BufferHeight; return new Tuple("WMouse Y", y * 20000 - 10000); } - + return o; })); } public void RebootCore() { - LoadRom(CurrentlyOpenRom); + var ioa = OpenAdvancedSerializer.ParseWithLegacy(CurrentlyOpenRom); + if (ioa is OpenAdvanced_LibretroNoGame) + LoadRom("", CurrentlyOpenRomArgs); + else + LoadRom(ioa.SimplePath, CurrentlyOpenRomArgs); } public void PauseEmulator() @@ -875,7 +882,7 @@ namespace BizHawk.Client.EmuHawk { using (var bb = Global.Config.Screenshot_CaptureOSD ? CaptureOSD() : MakeScreenshotImage()) { - using(var img = bb.ToSysdrawingBitmap()) + using (var img = bb.ToSysdrawingBitmap()) Clipboard.SetImage(img); } @@ -903,8 +910,8 @@ namespace BizHawk.Client.EmuHawk { var sequence = string.Format(" ({0})", seq++); fname = string.Format(fmt, prefix, ts, sequence); - } - + } + TakeScreenshot(fname); } @@ -1003,7 +1010,7 @@ namespace BizHawk.Client.EmuHawk } } - public void ToggleFullscreen(bool allowSuppress=false) + public void ToggleFullscreen(bool allowSuppress = false) { AutohideCursor(false); @@ -1017,23 +1024,23 @@ namespace BizHawk.Client.EmuHawk if (_inFullscreen == false) { SuspendLayout(); - #if WINDOWS - //Work around an AMD driver bug in >= vista: - //It seems windows will activate opengl fullscreen mode when a GL control is occupying the exact space of a screen (0,0 and dimensions=screensize) - //AMD cards manifest a problem under these circumstances, flickering other monitors. - //It isnt clear whether nvidia cards are failing to employ this optimization, or just not flickering. - //(this could be determined with more work; other side affects of the fullscreen mode include: corrupted taskbar, no modal boxes on top of GL control, no screenshots) - //At any rate, we can solve this by adding a 1px black border around the GL control - //Please note: It is important to do this before resizing things, otherwise momentarily a GL control without WS_BORDER will be at the magic dimensions and cause the flakeout - if (Global.Config.DispFullscreenHacks) - { - //ATTENTION: this causes the statusbar to not work well, since the backcolor is now set to black instead of SystemColors.Control. - //It seems that some statusbar elements composite with the backcolor. - //Maybe we could add another control under the statusbar. with a different backcolor - Padding = new Padding(1); - BackColor = Color.Black; - } - #endif +#if WINDOWS + //Work around an AMD driver bug in >= vista: + //It seems windows will activate opengl fullscreen mode when a GL control is occupying the exact space of a screen (0,0 and dimensions=screensize) + //AMD cards manifest a problem under these circumstances, flickering other monitors. + //It isnt clear whether nvidia cards are failing to employ this optimization, or just not flickering. + //(this could be determined with more work; other side affects of the fullscreen mode include: corrupted taskbar, no modal boxes on top of GL control, no screenshots) + //At any rate, we can solve this by adding a 1px black border around the GL control + //Please note: It is important to do this before resizing things, otherwise momentarily a GL control without WS_BORDER will be at the magic dimensions and cause the flakeout + if (Global.Config.DispFullscreenHacks) + { + //ATTENTION: this causes the statusbar to not work well, since the backcolor is now set to black instead of SystemColors.Control. + //It seems that some statusbar elements composite with the backcolor. + //Maybe we could add another control under the statusbar. with a different backcolor + Padding = new Padding(1); + BackColor = Color.Black; + } +#endif _windowedLocation = Location; @@ -1050,16 +1057,16 @@ namespace BizHawk.Client.EmuHawk WindowState = FormWindowState.Normal; - #if WINDOWS - //do this even if DispFullscreenHacks arent enabled, to restore it in case it changed underneath us or something - Padding = new Padding(0); - //it's important that we set the form color back to this, because the statusbar icons blend onto the mainform, not onto the statusbar-- - //so we need the statusbar and mainform backdrop color to match - BackColor = SystemColors.Control; - #endif +#if WINDOWS + //do this even if DispFullscreenHacks arent enabled, to restore it in case it changed underneath us or something + Padding = new Padding(0); + //it's important that we set the form color back to this, because the statusbar icons blend onto the mainform, not onto the statusbar-- + //so we need the statusbar and mainform backdrop color to match + BackColor = SystemColors.Control; +#endif _inFullscreen = false; - + SynchChrome(); Location = _windowedLocation; ResumeLayout(); @@ -1108,7 +1115,7 @@ namespace BizHawk.Client.EmuHawk { string ttype = ":(none)"; if (Global.Config.SoundThrottle) { ttype = ":Sound"; } - if (Global.Config.VSyncThrottle) { ttype = string.Format(":Vsync{0}", Global.Config.VSync?"[ena]":"[dis]"); } + if (Global.Config.VSyncThrottle) { ttype = string.Format(":Vsync{0}", Global.Config.VSync ? "[ena]" : "[dis]"); } if (Global.Config.ClockThrottle) { ttype = ":Clock"; } string xtype = _unthrottled ? "Unthrottled" : "Throttled"; string msg = string.Format("{0}{1} ", xtype, ttype); @@ -1732,7 +1739,18 @@ namespace BizHawk.Client.EmuHawk private void LoadRomFromRecent(string rom) { - if (!LoadRom(rom)) + + var ioa = OpenAdvancedSerializer.ParseWithLegacy(rom); + + LoadRomArgs args = new LoadRomArgs() + { + OpenAdvanced = ioa + }; + + //if(ioa is this or that) - for more complex behaviour + rom = ioa.SimplePath; + + if (!LoadRom(rom, args)) { Global.Config.RecentRoms.HandleLoadError(rom); } @@ -1929,8 +1947,8 @@ namespace BizHawk.Client.EmuHawk //private Size _lastVideoSize = new Size(-1, -1), _lastVirtualSize = new Size(-1, -1); var video = Global.Emulator.VideoProvider(); //bool change = false; - Size currVideoSize = new Size(video.BufferWidth,video.BufferHeight); - Size currVirtualSize = new Size(video.VirtualWidth,video.VirtualHeight); + Size currVideoSize = new Size(video.BufferWidth, video.BufferHeight); + Size currVirtualSize = new Size(video.VirtualWidth, video.VirtualHeight); if (currVideoSize != _lastVideoSize || currVirtualSize != _lastVirtualSize) { _lastVideoSize = currVideoSize; @@ -1954,7 +1972,7 @@ namespace BizHawk.Client.EmuHawk typeof(ToolStrip).InvokeMember("ProcessMnemonicInternal", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Instance, null, MainformMenu, new object[] { c }); } - private static string FormatFilter(params string[] args) + public static string FormatFilter(params string[] args) { var sb = new StringBuilder(); if (args.Length % 2 != 0) @@ -1984,7 +2002,7 @@ namespace BizHawk.Client.EmuHawk if (VersionInfo.DeveloperBuild) { return FormatFilter( - "Rom Files", "*.nes;*.fds;*unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.psf;*.minipsf;*.nsf;%ARCH%", + "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.psf;*.minipsf;*.nsf;%ARCH%", "Music Files", "*.psf;*.minipsf;*.sid;*.nsf", "Disc Images", "*.cue;*.ccd;*.m3u", "NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%", @@ -2058,7 +2076,9 @@ namespace BizHawk.Client.EmuHawk var file = new FileInfo(ofd.FileName); Global.Config.LastRomPath = file.DirectoryName; _lastOpenRomFilter = ofd.FilterIndex; - LoadRom(file.FullName); + + var lra = new LoadRomArgs { OpenAdvanced = new OpenAdvanced_OpenRom { Path = file.FullName } }; + LoadRom(file.FullName, lra); } private void CoreSyncSettings(object sender, RomLoader.SettingsLoadArgs e) @@ -3385,7 +3405,7 @@ namespace BizHawk.Client.EmuHawk // Retry loading the ROM here. This leads to recursion, as the original call to LoadRom has not exited yet, // but unless the user tries and fails to set his firmware a lot of times, nothing should happen. // Refer to how RomLoader implemented its LoadRom method for a potential fix on this. - LoadRom(e.RomPath, e.Deterministic); + LoadRom(e.RomPath, CurrentLoadRomArgs); } } } @@ -3417,171 +3437,239 @@ namespace BizHawk.Client.EmuHawk return platformChooser.PlatformChoice; } - // Still needs a good bit of refactoring - public bool LoadRom(string path, bool? deterministicemulation = null) + public class LoadRomArgs { - // If deterministic emulation is passed in, respect that value regardless, else determine a good value (currently that simply means movies require deterministic emulaton) - bool deterministic = deterministicemulation.HasValue ? - deterministicemulation.Value : - Global.MovieSession.QueuedMovie != null; - //Global.MovieSession.Movie.IsActive; - - if (!GlobalWin.Tools.AskSave()) + public bool? Deterministic; + public IOpenAdvanced OpenAdvanced; + } + + LoadRomArgs CurrentLoadRomArgs; + + // Still needs a good bit of refactoring + public bool LoadRom(string path, LoadRomArgs args = null) + { + //default args + if (args == null) args = new LoadRomArgs(); + + //if this is the first call to LoadRom (they will come in recursively) then stash the args + bool firstCall = false; + if (CurrentLoadRomArgs == null) { - return false; + firstCall = true; + CurrentLoadRomArgs = args; + } + else + { + args = CurrentLoadRomArgs; } - var loader = new RomLoader + try + { + // If deterministic emulation is passed in, respect that value regardless, else determine a good value (currently that simply means movies require deterministic emulaton) + bool deterministic = args.Deterministic.HasValue ? + args.Deterministic.Value : + Global.MovieSession.QueuedMovie != null; + //Global.MovieSession.Movie.IsActive; + + if (!GlobalWin.Tools.AskSave()) + { + return false; + } + + bool asLibretro = (args.OpenAdvanced is OpenAdvanced_Libretro || args.OpenAdvanced is OpenAdvanced_LibretroNoGame); + + var loader = new RomLoader { ChooseArchive = LoadArhiveChooser, ChoosePlatform = ChoosePlatformForRom, Deterministic = deterministic, - MessageCallback = GlobalWin.OSD.AddMessage + MessageCallback = GlobalWin.OSD.AddMessage, + AsLibretro = asLibretro }; - Global.FirmwareManager.RecentlyServed.Clear(); + Global.FirmwareManager.RecentlyServed.Clear(); - loader.OnLoadError += ShowLoadError; - loader.OnLoadSettings += CoreSettings; - loader.OnLoadSyncSettings += CoreSyncSettings; + loader.OnLoadError += ShowLoadError; + loader.OnLoadSettings += CoreSettings; + loader.OnLoadSyncSettings += CoreSyncSettings; - // 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(); // adelikat: I Think by reordering things, this isn't necessary anymore - CloseGame(); - - var nextComm = CreateCoreComm(); - CoreFileProvider.SyncCoreCommInputSignals(nextComm); - var result = loader.LoadRom(path, 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(); // adelikat: I Think by reordering things, this isn't necessary anymore + CloseGame(); + + var nextComm = CreateCoreComm(); + + //we need to inform LoadRom which Libretro core to use... + IOpenAdvanced ioa = args.OpenAdvanced; + if (ioa is IOpenAdvancedLibretro) + { + var ioaretro = ioa as IOpenAdvancedLibretro; + + //prepare a core specification + //if it wasnt already specified, use the current default + if (ioaretro.CorePath == null) ioaretro.CorePath = Global.Config.LibretroCore; + nextComm.LaunchLibretroCore = ioaretro.CorePath; + if (nextComm.LaunchLibretroCore == null) + throw new InvalidOperationException("Can't load a file via Libretro until a core is specified"); + } - if (result) - { - Global.Emulator = loader.LoadedEmulator; - Global.Game = loader.Game; CoreFileProvider.SyncCoreCommInputSignals(nextComm); - InputManager.SyncControls(); + var result = loader.LoadRom(path, nextComm); - if (Global.Emulator is TI83 && Global.Config.TI83autoloadKeyPad) + //we need to replace the path in the OpenAdvanced with the canonical one the user chose. + //It can't be done until loder.LoadRom happens (for CanonicalFullPath) + //i'm not sure this needs to be more abstractly engineered yet until we have more OpenAdvanced examples + if (ioa is OpenAdvanced_Libretro) { - GlobalWin.Tools.Load(); + var oaretro = ioa as OpenAdvanced_Libretro; + oaretro.token.Path = loader.CanonicalFullPath; } + if (ioa is OpenAdvanced_OpenRom) ((OpenAdvanced_OpenRom)ioa).Path = loader.CanonicalFullPath; + string loaderName = "*" + OpenAdvancedSerializer.Serialize(ioa); - if (loader.LoadedEmulator is NES) + if (result) { - var nes = loader.LoadedEmulator as NES; - if (!string.IsNullOrWhiteSpace(nes.GameName)) + Global.Emulator = loader.LoadedEmulator; + Global.Game = loader.Game; + CoreFileProvider.SyncCoreCommInputSignals(nextComm); + InputManager.SyncControls(); + + if (Global.Emulator is TI83 && Global.Config.TI83autoloadKeyPad) { - Global.Game.Name = nes.GameName; + GlobalWin.Tools.Load(); } - Global.Game.Status = nes.RomStatus; - } - else if (loader.LoadedEmulator is QuickNES) - { - var qns = loader.LoadedEmulator as QuickNES; - if (!string.IsNullOrWhiteSpace(qns.BootGodName)) + if (loader.LoadedEmulator is NES) { - Global.Game.Name = qns.BootGodName; + var nes = loader.LoadedEmulator as NES; + if (!string.IsNullOrWhiteSpace(nes.GameName)) + { + Global.Game.Name = nes.GameName; + } + + Global.Game.Status = nes.RomStatus; } - if (qns.BootGodStatus.HasValue) + else if (loader.LoadedEmulator is QuickNES) { - Global.Game.Status = qns.BootGodStatus.Value; + var qns = loader.LoadedEmulator as QuickNES; + if (!string.IsNullOrWhiteSpace(qns.BootGodName)) + { + Global.Game.Name = qns.BootGodName; + } + if (qns.BootGodStatus.HasValue) + { + Global.Game.Status = qns.BootGodStatus.Value; + } } - } - Global.Rewinder.ResetRewindBuffer(); + Global.Rewinder.ResetRewindBuffer(); - if (Global.Emulator.CoreComm.RomStatusDetails == null && loader.Rom != null) - { - Global.Emulator.CoreComm.RomStatusDetails = string.Format( - "{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n", - loader.Game.Name, - loader.Rom.RomData.HashSHA1(), - loader.Rom.RomData.HashMD5()); - } - - if (Global.Emulator.BoardName != null) - { - Console.WriteLine("Core reported BoardID: \"{0}\"", Global.Emulator.BoardName); - } - - // 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.MostRecent != loader.CanonicalFullPath) - { - GlobalWin.Tools.Restart(); - } - - Global.Config.RecentRoms.Add(loader.CanonicalFullPath); - JumpLists.AddRecentItem(loader.CanonicalFullPath); - - // Don't load Save Ram if a movie is being loaded - if (!Global.MovieSession.MovieIsQueued && File.Exists(PathManager.SaveRamPath(loader.Game))) - { - LoadSaveRam(); - } - - GlobalWin.Tools.Restart(); - - if (Global.Config.LoadCheatFileByGame) - { - if (Global.CheatList.AttemptToLoadCheatFile()) + if (Global.Emulator.CoreComm.RomStatusDetails == null && loader.Rom != null) { - GlobalWin.OSD.AddMessage("Cheats file loaded"); + Global.Emulator.CoreComm.RomStatusDetails = string.Format( + "{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n", + loader.Game.Name, + loader.Rom.RomData.HashSHA1(), + loader.Rom.RomData.HashMD5()); } - } - SetWindowText(); - CurrentlyOpenRom = loader.CanonicalFullPath; - HandlePlatformMenus(); - _stateSlots.Clear(); - UpdateCoreStatusBarButton(); - UpdateDumpIcon(); - SetMainformMovieInfo(); - - Global.Rewinder.CaptureRewindState(); - - Global.StickyXORAdapter.ClearStickies(); - Global.StickyXORAdapter.ClearStickyFloats(); - Global.AutofireStickyXORAdapter.ClearStickies(); - - RewireSound(); - ToolHelpers.UpdateCheatRelatedTools(null, null); - if (Global.Config.AutoLoadLastSaveSlot && _stateSlots.HasSlot(Global.Config.SaveSlot)) - { - LoadQuickSave("QuickSave" + Global.Config.SaveSlot); - } - - if (Global.FirmwareManager.RecentlyServed.Count > 0) - { - Console.WriteLine("Active Firmwares:"); - foreach (var f in Global.FirmwareManager.RecentlyServed) + if (Global.Emulator.BoardName != null) { - Console.WriteLine(" {0} : {1}", f.FirmwareId, f.Hash); + Console.WriteLine("Core reported BoardID: \"{0}\"", Global.Emulator.BoardName); } + + // 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.MostRecent != loaderName) + { + GlobalWin.Tools.Restart(); + } + + Global.Config.RecentRoms.Add(loaderName); + JumpLists.AddRecentItem(loaderName, ioa.DisplayName); + + // Don't load Save Ram if a movie is being loaded + if (!Global.MovieSession.MovieIsQueued && File.Exists(PathManager.SaveRamPath(loader.Game))) + { + LoadSaveRam(); + } + + GlobalWin.Tools.Restart(); + + if (Global.Config.LoadCheatFileByGame) + { + if (Global.CheatList.AttemptToLoadCheatFile()) + { + GlobalWin.OSD.AddMessage("Cheats file loaded"); + } + } + + SetWindowText(); + CurrentlyOpenRom = loaderName; + HandlePlatformMenus(); + _stateSlots.Clear(); + UpdateCoreStatusBarButton(); + UpdateDumpIcon(); + SetMainformMovieInfo(); + CurrentlyOpenRomArgs = args; + + Global.Rewinder.CaptureRewindState(); + + Global.StickyXORAdapter.ClearStickies(); + Global.StickyXORAdapter.ClearStickyFloats(); + Global.AutofireStickyXORAdapter.ClearStickies(); + + RewireSound(); + ToolHelpers.UpdateCheatRelatedTools(null, null); + if (Global.Config.AutoLoadLastSaveSlot && _stateSlots.HasSlot(Global.Config.SaveSlot)) + { + LoadQuickSave("QuickSave" + Global.Config.SaveSlot); + } + + if (Global.FirmwareManager.RecentlyServed.Count > 0) + { + Console.WriteLine("Active Firmwares:"); + foreach (var f in Global.FirmwareManager.RecentlyServed) + { + Console.WriteLine(" {0} : {1}", f.FirmwareId, f.Hash); + } + } + return true; + } + else + { + //This shows up if there's a problem + // TODO: put all these in a single method or something + + //The ROM has been loaded by a recursive invocation of the LoadROM method. + if (!(Global.Emulator is NullEmulator)) + { + return true; + } +<<<<<<< HEAD } return true; - } - else - { - //This shows up if there's a problem - // TODO: put all these in a single method or something +======= - //The ROM has been loaded by a recursive invocation of the LoadROM method. - if (!(Global.Emulator is NullEmulator)) - { - return true; + HandlePlatformMenus(); + _stateSlots.Clear(); + UpdateStatusSlots(); + UpdateCoreStatusBarButton(); + UpdateDumpIcon(); + SetMainformMovieInfo(); + SetWindowText(); + return false; + } +>>>>>>> refs/remotes/TASVideos/master + } + finally + { + if (firstCall) + { + CurrentLoadRomArgs = null; } - - HandlePlatformMenus(); - _stateSlots.Clear(); - UpdateStatusSlots(); - UpdateCoreStatusBarButton(); - UpdateDumpIcon(); - SetMainformMovieInfo(); - SetWindowText(); - return false; } } @@ -3708,6 +3796,8 @@ namespace BizHawk.Client.EmuHawk PauseOnFrame = null; ToolHelpers.UpdateCheatRelatedTools(null, null); UpdateStatusSlots(); + CurrentlyOpenRom = null; + CurrentlyOpenRomArgs = null; } } @@ -3823,7 +3913,7 @@ namespace BizHawk.Client.EmuHawk return master.Rewind(); } } - + var isRewinding = false; if (Global.Rewinder.RewindActive && (Global.ClientControls["Rewind"] || PressRewind) && !Global.MovieSession.Movie.IsRecording) // Rewind isn't "bulletproof" and can desync a recording movie! @@ -3909,6 +3999,5 @@ namespace BizHawk.Client.EmuHawk nesHawkToolStripMenuItem.Checked = Global.Config.NES_InQuickNES == false; } - } } diff --git a/BizHawk.Client.EmuHawk/MainForm.resx b/BizHawk.Client.EmuHawk/MainForm.resx index ac68a9029a..b1102bdcb9 100644 --- a/BizHawk.Client.EmuHawk/MainForm.resx +++ b/BizHawk.Client.EmuHawk/MainForm.resx @@ -571,6 +571,6 @@ 399, 13 - 65 + 37 \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/OpenAdvanced.cs b/BizHawk.Client.EmuHawk/OpenAdvanced.cs new file mode 100644 index 0000000000..9a9cfc1c91 --- /dev/null +++ b/BizHawk.Client.EmuHawk/OpenAdvanced.cs @@ -0,0 +1,164 @@ +using System; +using System.Text; +using System.IO; +using System.Collections.Generic; + +using BizHawk.Emulation.Cores; + +using Newtonsoft.Json; + +//this file contains some cumbersome self-"serialization" in order to gain a modicum of control over what the serialized output looks like +//I don't want them to look like crufty json + +namespace BizHawk.Client.EmuHawk +{ + public interface IOpenAdvanced + { + string TypeName { get; } + string DisplayName { get; } + + /// + /// returns a sole path to use for opening a rom (not sure if this is a good idea) + /// + string SimplePath { get; } + + void Deserialize(string str); + void Serialize(TextWriter tw); + } + + public interface IOpenAdvancedLibretro + { + string CorePath { get; set; } + } + + public static class OpenAdvancedTypes + { + public const string OpenRom = "OpenRom"; + public const string Libretro = "Libretro"; + public const string LibretroNoGame = "LibretroNoGame"; + } + + + public class OpenAdvancedSerializer + { + + public static IOpenAdvanced ParseWithLegacy(string text) + { + if (text.StartsWith("*")) + return Deserialize(text.Substring(1)); + else return new OpenAdvanced_OpenRom { Path = text }; + } + + private static IOpenAdvanced Deserialize(string text) + { + int idx = text.IndexOf('*'); + string type = text.Substring(0, idx); + string token = text.Substring(idx + 1); + IOpenAdvanced ioa; + if (type == OpenAdvancedTypes.OpenRom) ioa = new OpenAdvanced_OpenRom(); + else if (type == OpenAdvancedTypes.Libretro) ioa = new OpenAdvanced_Libretro(); + else if (type == OpenAdvancedTypes.LibretroNoGame) ioa = new OpenAdvanced_LibretroNoGame(); + else ioa = null; + if (ioa == null) + throw new InvalidOperationException("IOpenAdvanced deserialization error"); + ioa.Deserialize(token); + return ioa; + } + + public static string Serialize(IOpenAdvanced ioa) + { + StringWriter sw = new StringWriter(); + sw.Write("{0}*", ioa.TypeName); + ioa.Serialize(sw); + return sw.ToString(); + } + } + + class OpenAdvanced_Libretro : IOpenAdvanced, IOpenAdvancedLibretro + { + public OpenAdvanced_Libretro() + { + } + + public struct Token + { + public string Path, CorePath; + } + public Token token = new Token(); + + public string TypeName { get { return "Libretro"; } } + public string DisplayName { get { return string.Format("{0}:{1}", Path.GetFileNameWithoutExtension(token.CorePath), token.Path); } } + public string SimplePath { get { return token.Path; } } + + public void Deserialize(string str) + { + token = JsonConvert.DeserializeObject(str); + } + + public void Serialize(TextWriter tw) + { + tw.Write(JsonConvert.SerializeObject(token)); + } + + public string CorePath { get { return token.CorePath; } set { token.CorePath = value; } } + } + + class OpenAdvanced_LibretroNoGame : IOpenAdvanced, IOpenAdvancedLibretro + { + //you might think ideally we'd fetch the libretro core name from the core info inside it + //but that would involve spinning up excess libretro core instances, which probably isnt good for stability, no matter how much we wish otherwise, not to mention slow. + //moreover it's kind of complicated here, + //and finally, I think the Displayname should really be file-based in all cases, since the user is going to be loading cores by filename and + //this is related to the recent roms filename management. + //so, leave it. + + public OpenAdvanced_LibretroNoGame() + { + } + + public OpenAdvanced_LibretroNoGame(string corepath) + { + _corePath = corepath; + } + + string _corePath; + + public string TypeName { get { return "LibretroNoGame"; } } + public string DisplayName { get { return Path.GetFileName(_corePath); } } //assume we like the filename of the core + public string SimplePath { get { return ""; } } //effectively a signal to not use a game + + public void Deserialize(string str) + { + _corePath = str; + } + + public void Serialize(TextWriter tw) + { + tw.Write(_corePath); + } + + public string CorePath { get { return _corePath; } set { _corePath = value; } } + } + + class OpenAdvanced_OpenRom : IOpenAdvanced + { + public OpenAdvanced_OpenRom() + {} + + public string Path; + + public string TypeName { get { return "OpenRom"; } } + public string DisplayName { get { return Path; } } + public string SimplePath { get { return Path; } } + + public void Deserialize(string str) + { + Path = str; + } + + public void Serialize(TextWriter tw) + { + tw.Write(Path); + } + } +} \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs new file mode 100644 index 0000000000..253af15e5e --- /dev/null +++ b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.Designer.cs @@ -0,0 +1,183 @@ +namespace BizHawk.Client.EmuHawk +{ + partial class OpenAdvancedChooser + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.btnLibretroLaunchNoGame = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.txtLibretroCore = new System.Windows.Forms.TextBox(); + this.btnLibretroLaunchGame = new System.Windows.Forms.Button(); + this.btnSetLibretroCore = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.btnClassicLaunchGame = new System.Windows.Forms.Button(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // label3 + // + this.label3.Location = new System.Drawing.Point(6, 25); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(250, 29); + this.label3.TabIndex = 5; + this.label3.Text = "Load a rom with the classic BizHawk autodetection method. But why not just use Op" + + "en Rom?"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(6, 26); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(69, 13); + this.label2.TabIndex = 3; + this.label2.Text = "Current Core:"; + // + // btnLibretroLaunchNoGame + // + this.btnLibretroLaunchNoGame.Location = new System.Drawing.Point(217, 50); + this.btnLibretroLaunchNoGame.Name = "btnLibretroLaunchNoGame"; + this.btnLibretroLaunchNoGame.Size = new System.Drawing.Size(102, 23); + this.btnLibretroLaunchNoGame.TabIndex = 1; + this.btnLibretroLaunchNoGame.Text = "Launch No Game"; + this.btnLibretroLaunchNoGame.UseVisualStyleBackColor = true; + this.btnLibretroLaunchNoGame.Click += new System.EventHandler(this.btnLibretroLaunchNoGame_Click); + // + // btnCancel + // + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(370, 176); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 2; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.txtLibretroCore); + this.groupBox2.Controls.Add(this.btnLibretroLaunchGame); + this.groupBox2.Controls.Add(this.btnSetLibretroCore); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.btnLibretroLaunchNoGame); + this.groupBox2.Location = new System.Drawing.Point(12, 12); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(433, 81); + this.groupBox2.TabIndex = 3; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "Libretro"; + // + // txtLibretroCore + // + this.txtLibretroCore.Location = new System.Drawing.Point(81, 23); + this.txtLibretroCore.Name = "txtLibretroCore"; + this.txtLibretroCore.ReadOnly = true; + this.txtLibretroCore.Size = new System.Drawing.Size(314, 20); + this.txtLibretroCore.TabIndex = 6; + // + // btnLibretroLaunchGame + // + this.btnLibretroLaunchGame.Location = new System.Drawing.Point(325, 50); + this.btnLibretroLaunchGame.Name = "btnLibretroLaunchGame"; + this.btnLibretroLaunchGame.Size = new System.Drawing.Size(102, 23); + this.btnLibretroLaunchGame.TabIndex = 5; + this.btnLibretroLaunchGame.Text = "Launch Game"; + this.btnLibretroLaunchGame.UseVisualStyleBackColor = true; + this.btnLibretroLaunchGame.Click += new System.EventHandler(this.btnLibretroLaunchGame_Click); + // + // btnSetLibretroCore + // + this.btnSetLibretroCore.AutoSize = true; + this.btnSetLibretroCore.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.btnSetLibretroCore.Location = new System.Drawing.Point(401, 21); + this.btnSetLibretroCore.Name = "btnSetLibretroCore"; + this.btnSetLibretroCore.Size = new System.Drawing.Size(26, 23); + this.btnSetLibretroCore.TabIndex = 4; + this.btnSetLibretroCore.Text = "..."; + this.btnSetLibretroCore.UseVisualStyleBackColor = true; + this.btnSetLibretroCore.Click += new System.EventHandler(this.btnSetLibretroCore_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.btnClassicLaunchGame); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Location = new System.Drawing.Point(12, 99); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(277, 100); + this.groupBox3.TabIndex = 6; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "BizHawk Classic"; + // + // btnClassicLaunchGame + // + this.btnClassicLaunchGame.Location = new System.Drawing.Point(169, 71); + this.btnClassicLaunchGame.Name = "btnClassicLaunchGame"; + this.btnClassicLaunchGame.Size = new System.Drawing.Size(102, 23); + this.btnClassicLaunchGame.TabIndex = 6; + this.btnClassicLaunchGame.Text = "Launch Game"; + this.btnClassicLaunchGame.UseVisualStyleBackColor = true; + this.btnClassicLaunchGame.Click += new System.EventHandler(this.btnClassicLaunchGame_Click); + // + // OpenAdvancedChooser + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(457, 208); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.btnCancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OpenAdvancedChooser"; + this.Text = "Open Advanced"; + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button btnLibretroLaunchNoGame; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Button btnSetLibretroCore; + private System.Windows.Forms.TextBox txtLibretroCore; + private System.Windows.Forms.Button btnLibretroLaunchGame; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Button btnClassicLaunchGame; + } +} \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs new file mode 100644 index 0000000000..05aa3e0237 --- /dev/null +++ b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +using BizHawk.Emulation.Cores; +using BizHawk.Client.Common; + +//these match strings from OpenAdvance. should we make them constants in there? + +namespace BizHawk.Client.EmuHawk +{ + public partial class OpenAdvancedChooser : Form + { + MainForm mainForm; + + public enum Command + { + RetroLaunchNoGame, RetroLaunchGame, + ClassicLaunchGame + } + + public Command Result; + public string SuggestedExtensionFilter; + + public OpenAdvancedChooser(MainForm mainForm) + { + this.mainForm = mainForm; + + InitializeComponent(); + + RefreshLibretroCore(true); + } + + private void btnOK_Click(object sender, EventArgs e) + { + DialogResult = System.Windows.Forms.DialogResult.OK; + Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + DialogResult = System.Windows.Forms.DialogResult.Cancel; + Close(); + } + + private void btnSetLibretroCore_Click(object sender, EventArgs e) + { + mainForm.RunLibretroCoreChooser(); + RefreshLibretroCore(false); + } + + LibRetroEmulator.RetroDescription CurrentDescription; + void RefreshLibretroCore(bool bootstrap) + { + txtLibretroCore.Text = ""; + btnLibretroLaunchNoGame.Enabled = false; + btnLibretroLaunchGame.Enabled = false; + + var core = Global.Config.LibretroCore; + if (string.IsNullOrEmpty(core)) + return; + + txtLibretroCore.Text = core; + CurrentDescription = null; + + //scan the current libretro core to see if it can be launched with NoGame,and other stuff + try + { + using (var retro = new LibRetroEmulator(new BizHawk.Emulation.Common.CoreComm(null, null), core)) + { + btnLibretroLaunchGame.Enabled = true; + if (retro.Description.SupportsNoGame) + btnLibretroLaunchNoGame.Enabled = true; + + //print descriptive information + var descr = retro.Description; + CurrentDescription = descr; + Console.WriteLine("core name: {0} version {1}", descr.LibraryName, descr.LibraryVersion); + Console.WriteLine("extensions: ", descr.ValidExtensions); + Console.WriteLine("NeedsRomAsPath: {0}", descr.NeedsRomAsPath); + Console.WriteLine("AcceptsArchives: {0}", descr.NeedsArchives); + Console.WriteLine("SupportsNoGame: {0}", descr.SupportsNoGame); + + foreach (var v in descr.Variables.Values) + Console.WriteLine(v); + } + } + catch + { + if (!bootstrap) + MessageBox.Show("Couldn't load the selected Libretro core for analysis. It won't be available."); + } + } + + private void btnLibretroLaunchGame_Click(object sender, EventArgs e) + { + //build a list of extensions suggested for use for this core + StringWriter sw = new StringWriter(); + foreach(var ext in CurrentDescription.ValidExtensions.Split('|')) + sw.Write("*.{0};",ext); + var filter = sw.ToString(); + filter = filter.Substring(0,filter.Length-1); + List args = new List(); + args.Add("Rom Files"); + if (!CurrentDescription.NeedsArchives) + filter += ";%ARCH%"; + args.Add(filter); + if (!CurrentDescription.NeedsArchives) + { + args.Add("Archive Files"); + args.Add("%ARCH%"); + } + args.Add("All Files"); + args.Add("*.*"); + filter = MainForm.FormatFilter(args.ToArray()); + SuggestedExtensionFilter = filter; + + Result = Command.RetroLaunchGame; + DialogResult = System.Windows.Forms.DialogResult.OK; + Close(); + } + + private void btnClassicLaunchGame_Click(object sender, EventArgs e) + { + Result = Command.ClassicLaunchGame; + DialogResult = System.Windows.Forms.DialogResult.OK; + Close(); + } + + private void btnLibretroLaunchNoGame_Click(object sender, EventArgs e) + { + Result = Command.RetroLaunchNoGame; + DialogResult = System.Windows.Forms.DialogResult.OK; + Close(); + } + } +} diff --git a/BizHawk.Client.EmuHawk/OpenAdvancedChooser.resx b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/BizHawk.Client.EmuHawk/OpenAdvancedChooser.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs index 414d931392..ce125c1389 100644 --- a/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs +++ b/BizHawk.Client.EmuHawk/Properties/Resources.Designer.cs @@ -290,6 +290,16 @@ namespace BizHawk.Client.EmuHawk.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap cdlogger { + get { + object obj = ResourceManager.GetObject("cdlogger", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/BizHawk.Client.EmuHawk/Properties/Resources.resx b/BizHawk.Client.EmuHawk/Properties/Resources.resx index 98ac8ea1e9..98a5f2cd98 100644 --- a/BizHawk.Client.EmuHawk/Properties/Resources.resx +++ b/BizHawk.Client.EmuHawk/Properties/Resources.resx @@ -127,14 +127,14 @@ ..\images\tastudio\ts_v_piano_13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_h_piano_00_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\AudioHS.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\Scan.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_v_piano_02_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\Square.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\ControllerImages\A78Joystick.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -157,8 +157,8 @@ ..\images\FastForward.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\Close.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_h_piano_11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\MoveDown.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -166,8 +166,8 @@ ..\images\ToolBox.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\FindHS.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\ControllerImages\NES_Controller.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\ControllerImages\SNES_Controller.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -232,14 +232,14 @@ ..\images\Triangle.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\NESControllerIcon.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\MoveLeft.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_h_piano_11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\Erase.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_v_piano_11_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_v_piano_17_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_h_piano_01.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -253,8 +253,8 @@ ..\images\tastudio\ts_h_piano_15_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_v_piano_07_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\restart.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\YellowDown.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -274,9 +274,6 @@ ..\images\tastudio\ts_v_piano_18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\Square.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\tastudio\ts_v_arrow_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -313,8 +310,8 @@ ..\images\tastudio\ts_v_piano_18_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_v_piano_15_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\monitor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -337,12 +334,24 @@ ..\images\BlueDown.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_v_piano_11_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\images\cheat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\Previous.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_v_piano_07_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_v_piano_00_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\icon_marker.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\reboot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -355,12 +364,15 @@ ..\images\tastudio\ts_h_arrow_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\TurboFastForward.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_h_piano_17_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\GenesisControllerIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\icon_anchor_lag.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\GameController.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -436,6 +448,9 @@ ..\images\tastudio\ts_h_piano_04_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\TurboFastForward.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\whiteTriLeft.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -490,9 +505,6 @@ ..\images\tastudio\ts_h_piano_00_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_v_piano_17_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\tastudio\ts_h_piano_06_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -523,6 +535,9 @@ ..\images\tastudio\ts_h_piano_07.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\gambatte.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_v_piano_01_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -550,6 +565,9 @@ ..\images\tastudio\ts_v_piano_15_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_v_piano_02_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_v_piano_09_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -589,9 +607,6 @@ ..\images\OpenFile.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_h_piano_17_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\tastudio\ts_h_piano_19_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -625,6 +640,12 @@ ..\images\tastudio\ts_h_piano_06_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_h_piano_00_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\images\Close.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_h_piano_17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -634,11 +655,8 @@ ..\images\TAStudio.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\tastudio\ts_h_piano_08.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\LightOff.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\bsnes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_v_piano_16_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -673,9 +691,6 @@ ..\images\tastudio\ts_v_piano_01.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\MoveLeft.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\tastudio\ts_v_piano_11_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -715,20 +730,20 @@ ..\images\tastudio\ts_h_piano_01_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\LightOn.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\QuickNes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\Erase.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\tastudio\ts_h_piano_07_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_h_piano_14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\gambatte.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_v_piano_15_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_h_piano_04.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -766,8 +781,8 @@ ..\images\Both.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\LightOn.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\ts_h_piano_08.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\Duplicate.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -796,9 +811,6 @@ ..\images\tastudio\ts_h_piano_18_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\AudioHS.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\ControllerImages\TI83Calculator.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -826,9 +838,6 @@ ..\images\tastudio\ts_h_piano_09_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\bsnes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\controllerimages\saturncontroller.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -874,6 +883,9 @@ ..\images\SaveConfig.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\LightOff.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_h_piano_03_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -889,6 +901,9 @@ ..\images\pcb.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\kitchensink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_h_piano_18_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -916,9 +931,6 @@ ..\images\tastudio\ts_v_piano_02.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\Stop.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\images\pcejin1.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -976,11 +988,8 @@ ..\images\tastudio\ts_h_piano_10_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\ControllerImages\NES_Controller.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\cheat.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\NESControllerIcon.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_h_piano_15_green_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -1003,8 +1012,8 @@ ..\images\tastudio\ts_h_piano_06_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\restart.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\tastudio\icon_anchor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\images\tastudio\ts_h_piano_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -1461,6 +1470,9 @@ ..\images\NewFile.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\FindHS.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\images\tastudio\ts_v_piano_00.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -1497,16 +1509,7 @@ ..\images\whiteTriUp.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\images\kitchensink.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\tastudio\icon_anchor_lag.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\tastudio\icon_marker.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\images\tastudio\icon_anchor.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\images\cdlogger.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.Designer.cs b/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.Designer.cs index 1a17a0b9cf..1e38e366f2 100644 --- a/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.Designer.cs +++ b/BizHawk.Client.EmuHawk/config/ControllerConfig/ControllerConfigPanel.Designer.cs @@ -39,12 +39,12 @@ this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.clearToolStripMenuItem}); this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(153, 48); + this.contextMenuStrip1.Size = new System.Drawing.Size(100, 26); // // clearToolStripMenuItem // this.clearToolStripMenuItem.Name = "clearToolStripMenuItem"; - this.clearToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.clearToolStripMenuItem.Size = new System.Drawing.Size(99, 22); this.clearToolStripMenuItem.Text = "&Clear"; this.clearToolStripMenuItem.Click += new System.EventHandler(this.clearToolStripMenuItem_Click); // diff --git a/BizHawk.Client.EmuHawk/images/cdlogger.ico b/BizHawk.Client.EmuHawk/images/cdlogger.ico new file mode 100644 index 0000000000..a401260746 Binary files /dev/null and b/BizHawk.Client.EmuHawk/images/cdlogger.ico differ diff --git a/BizHawk.Client.EmuHawk/tools/CDL.Designer.cs b/BizHawk.Client.EmuHawk/tools/CDL.Designer.cs index 2efe5aab19..7af730a362 100644 --- a/BizHawk.Client.EmuHawk/tools/CDL.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/CDL.Designer.cs @@ -1,3 +1,4 @@ +<<<<<<< HEAD namespace BizHawk.Client.EmuHawk { partial class CDL @@ -238,4 +239,421 @@ private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem; } +======= +namespace BizHawk.Client.EmuHawk +{ + partial class CDL + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CDL)); + this.menuStrip1 = new MenuStripEx(); + this.FileSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.NewMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.OpenMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.SaveAsMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.AppendMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.RecentSubMenu = new System.Windows.Forms.ToolStripMenuItem(); + this.noneToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.ClearMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.DisassembleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.ExitMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.tsbLoggingActive = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.tsbViewUpdate = new System.Windows.Forms.ToolStripButton(); + this.tsbViewStyle = new System.Windows.Forms.ToolStripComboBox(); + this.lvCDL = new BizHawk.Client.EmuHawk.VirtualListView(); + this.colAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colDomain = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colPct = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colMapped = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag01 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag02 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag04 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag08 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag20 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag40 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.colFlag80 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.tsbExportText = new System.Windows.Forms.ToolStripButton(); + this.menuStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.ClickThrough = true; + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FileSubMenu}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(992, 24); + this.menuStrip1.TabIndex = 2; + this.menuStrip1.Text = "menuStrip1"; + // + // FileSubMenu + // + this.FileSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.NewMenuItem, + this.OpenMenuItem, + this.SaveMenuItem, + this.SaveAsMenuItem, + this.AppendMenuItem, + this.RecentSubMenu, + this.toolStripSeparator2, + this.ClearMenuItem, + this.DisassembleMenuItem, + this.toolStripSeparator1, + this.ExitMenuItem}); + this.FileSubMenu.Name = "FileSubMenu"; + this.FileSubMenu.Size = new System.Drawing.Size(35, 20); + this.FileSubMenu.Text = "&File"; + this.FileSubMenu.DropDownOpened += new System.EventHandler(this.FileSubMenu_DropDownOpened); + // + // NewMenuItem + // + this.NewMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.NewFile; + this.NewMenuItem.Name = "NewMenuItem"; + this.NewMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.NewMenuItem.Size = new System.Drawing.Size(193, 22); + this.NewMenuItem.Text = "&New"; + this.NewMenuItem.Click += new System.EventHandler(this.NewMenuItem_Click); + // + // OpenMenuItem + // + this.OpenMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.OpenFile; + this.OpenMenuItem.Name = "OpenMenuItem"; + this.OpenMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.OpenMenuItem.Size = new System.Drawing.Size(193, 22); + this.OpenMenuItem.Text = "&Open..."; + this.OpenMenuItem.Click += new System.EventHandler(this.OpenMenuItem_Click); + // + // SaveMenuItem + // + this.SaveMenuItem.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.SaveAs; + this.SaveMenuItem.Name = "SaveMenuItem"; + this.SaveMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.SaveMenuItem.Size = new System.Drawing.Size(193, 22); + this.SaveMenuItem.Text = "&Save"; + this.SaveMenuItem.Click += new System.EventHandler(this.SaveMenuItem_Click); + // + // SaveAsMenuItem + // + this.SaveAsMenuItem.Name = "SaveAsMenuItem"; + this.SaveAsMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.S))); + this.SaveAsMenuItem.Size = new System.Drawing.Size(193, 22); + this.SaveAsMenuItem.Text = "&Save As..."; + this.SaveAsMenuItem.Click += new System.EventHandler(this.SaveAsMenuItem_Click); + // + // AppendMenuItem + // + this.AppendMenuItem.Name = "AppendMenuItem"; + this.AppendMenuItem.Size = new System.Drawing.Size(193, 22); + this.AppendMenuItem.Text = "&Append File..."; + this.AppendMenuItem.Click += new System.EventHandler(this.AppendMenuItem_Click); + // + // RecentSubMenu + // + this.RecentSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.noneToolStripMenuItem}); + this.RecentSubMenu.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.Recent; + this.RecentSubMenu.Name = "RecentSubMenu"; + this.RecentSubMenu.Size = new System.Drawing.Size(193, 22); + this.RecentSubMenu.Text = "Recent"; + this.RecentSubMenu.DropDownOpened += new System.EventHandler(this.RecentSubMenu_DropDownOpened); + // + // noneToolStripMenuItem + // + this.noneToolStripMenuItem.Name = "noneToolStripMenuItem"; + this.noneToolStripMenuItem.Size = new System.Drawing.Size(99, 22); + this.noneToolStripMenuItem.Text = "None"; + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(190, 6); + // + // ClearMenuItem + // + this.ClearMenuItem.Name = "ClearMenuItem"; + this.ClearMenuItem.Size = new System.Drawing.Size(193, 22); + this.ClearMenuItem.Text = "&Clear"; + this.ClearMenuItem.Click += new System.EventHandler(this.ClearMenuItem_Click); + // + // DisassembleMenuItem + // + this.DisassembleMenuItem.Name = "DisassembleMenuItem"; + this.DisassembleMenuItem.Size = new System.Drawing.Size(193, 22); + this.DisassembleMenuItem.Text = "&Disassemble..."; + this.DisassembleMenuItem.Click += new System.EventHandler(this.DisassembleMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(190, 6); + // + // ExitMenuItem + // + this.ExitMenuItem.Name = "ExitMenuItem"; + this.ExitMenuItem.ShortcutKeyDisplayString = "Alt+F4"; + this.ExitMenuItem.Size = new System.Drawing.Size(193, 22); + this.ExitMenuItem.Text = "&Close"; + this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tsbLoggingActive, + this.toolStripSeparator3, + this.tsbViewUpdate, + this.tsbViewStyle, + this.toolStripSeparator4, + this.tsbExportText}); + this.toolStrip1.Location = new System.Drawing.Point(0, 24); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(992, 25); + this.toolStrip1.TabIndex = 8; + this.toolStrip1.Text = "toolStrip1"; + // + // tsbLoggingActive + // + this.tsbLoggingActive.CheckOnClick = true; + this.tsbLoggingActive.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.tsbLoggingActive.Image = ((System.Drawing.Image)(resources.GetObject("tsbLoggingActive.Image"))); + this.tsbLoggingActive.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbLoggingActive.Name = "tsbLoggingActive"; + this.tsbLoggingActive.Size = new System.Drawing.Size(41, 22); + this.tsbLoggingActive.Text = "Active"; + this.tsbLoggingActive.CheckedChanged += new System.EventHandler(this.tsbLoggingActive_CheckedChanged); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25); + // + // tsbViewUpdate + // + this.tsbViewUpdate.Checked = true; + this.tsbViewUpdate.CheckOnClick = true; + this.tsbViewUpdate.CheckState = System.Windows.Forms.CheckState.Checked; + this.tsbViewUpdate.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.tsbViewUpdate.Image = ((System.Drawing.Image)(resources.GetObject("tsbViewUpdate.Image"))); + this.tsbViewUpdate.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbViewUpdate.Name = "tsbViewUpdate"; + this.tsbViewUpdate.Size = new System.Drawing.Size(46, 22); + this.tsbViewUpdate.Text = "Update"; + // + // tsbViewStyle + // + this.tsbViewStyle.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.tsbViewStyle.Items.AddRange(new object[] { + "Show %", + "Show Bytes", + "Show KBytes"}); + this.tsbViewStyle.Name = "tsbViewStyle"; + this.tsbViewStyle.Size = new System.Drawing.Size(121, 25); + this.tsbViewStyle.SelectedIndexChanged += new System.EventHandler(this.tsbViewStyle_SelectedIndexChanged); + // + // lvCDL + // + this.lvCDL.BlazingFast = false; + this.lvCDL.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.colAddress, + this.colDomain, + this.colPct, + this.colMapped, + this.colSize, + this.colFlag01, + this.colFlag02, + this.colFlag04, + this.colFlag08, + this.colFlag10, + this.colFlag20, + this.colFlag40, + this.colFlag80}); + this.lvCDL.Dock = System.Windows.Forms.DockStyle.Fill; + this.lvCDL.FullRowSelect = true; + this.lvCDL.GridLines = true; + this.lvCDL.ItemCount = 0; + this.lvCDL.Location = new System.Drawing.Point(0, 49); + this.lvCDL.Name = "lvCDL"; + this.lvCDL.SelectAllInProgress = false; + this.lvCDL.selectedItem = -1; + this.lvCDL.Size = new System.Drawing.Size(992, 323); + this.lvCDL.TabIndex = 9; + this.lvCDL.UseCompatibleStateImageBehavior = false; + this.lvCDL.UseCustomBackground = true; + this.lvCDL.View = System.Windows.Forms.View.Details; + this.lvCDL.VirtualMode = true; + this.lvCDL.QueryItemText += new BizHawk.Client.EmuHawk.QueryItemTextHandler(this.lvCDL_QueryItemText); + // + // colAddress + // + this.colAddress.Text = "CDL File @"; + this.colAddress.Width = 107; + // + // colDomain + // + this.colDomain.Text = "Domain"; + this.colDomain.Width = 126; + // + // colPct + // + this.colPct.Text = "%"; + this.colPct.Width = 58; + // + // colMapped + // + this.colMapped.Text = "Mapped"; + this.colMapped.Width = 64; + // + // colSize + // + this.colSize.Text = "Size"; + this.colSize.Width = 102; + // + // colFlag01 + // + this.colFlag01.Text = "0x01"; + // + // colFlag02 + // + this.colFlag02.Text = "0x02"; + // + // colFlag04 + // + this.colFlag04.Text = "0x04"; + // + // colFlag08 + // + this.colFlag08.Text = "0x08"; + // + // colFlag10 + // + this.colFlag10.Text = "0x10"; + // + // colFlag20 + // + this.colFlag20.Text = "0x20"; + // + // colFlag40 + // + this.colFlag40.Text = "0x40"; + // + // colFlag80 + // + this.colFlag80.Text = "0x80"; + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(6, 25); + // + // tsbExportText + // + this.tsbExportText.Image = global::BizHawk.Client.EmuHawk.Properties.Resources.LoadConfig; + this.tsbExportText.ImageTransparentColor = System.Drawing.Color.Magenta; + this.tsbExportText.Name = "tsbExportText"; + this.tsbExportText.Size = new System.Drawing.Size(87, 22); + this.tsbExportText.Text = "To Clipboard"; + this.tsbExportText.Click += new System.EventHandler(this.tsbExportText_Click); + // + // CDL + // + this.AllowDrop = true; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(992, 372); + this.Controls.Add(this.lvCDL); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.menuStrip1; + this.MinimumSize = new System.Drawing.Size(150, 130); + this.Name = "CDL"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Code Data Logger"; + this.Load += new System.EventHandler(this.PCECDL_Load); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.PCECDL_DragDrop); + this.DragEnter += new System.Windows.Forms.DragEventHandler(this.PCECDL_DragEnter); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private MenuStripEx menuStrip1; + private System.Windows.Forms.ToolStripMenuItem FileSubMenu; + private System.Windows.Forms.ToolStripMenuItem ClearMenuItem; + private System.Windows.Forms.ToolStripMenuItem OpenMenuItem; + private System.Windows.Forms.ToolStripMenuItem SaveAsMenuItem; + private System.Windows.Forms.ToolStripMenuItem AppendMenuItem; + private System.Windows.Forms.ToolStripMenuItem NewMenuItem; + private System.Windows.Forms.ToolStripMenuItem DisassembleMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem ExitMenuItem; + private System.Windows.Forms.ToolStripMenuItem SaveMenuItem; + private System.Windows.Forms.ToolStripMenuItem RecentSubMenu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton tsbLoggingActive; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripButton tsbViewUpdate; + private System.Windows.Forms.ToolStripComboBox tsbViewStyle; + private VirtualListView lvCDL; + private System.Windows.Forms.ColumnHeader colAddress; + private System.Windows.Forms.ColumnHeader colDomain; + private System.Windows.Forms.ColumnHeader colPct; + private System.Windows.Forms.ColumnHeader colMapped; + private System.Windows.Forms.ColumnHeader colSize; + private System.Windows.Forms.ColumnHeader colFlag01; + private System.Windows.Forms.ColumnHeader colFlag02; + private System.Windows.Forms.ColumnHeader colFlag04; + private System.Windows.Forms.ColumnHeader colFlag08; + private System.Windows.Forms.ColumnHeader colFlag10; + private System.Windows.Forms.ColumnHeader colFlag20; + private System.Windows.Forms.ColumnHeader colFlag40; + private System.Windows.Forms.ColumnHeader colFlag80; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripButton tsbExportText; + + } +>>>>>>> refs/remotes/TASVideos/master } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/tools/CDL.cs b/BizHawk.Client.EmuHawk/tools/CDL.cs index 3de4f19f44..baec1dbd5e 100644 --- a/BizHawk.Client.EmuHawk/tools/CDL.cs +++ b/BizHawk.Client.EmuHawk/tools/CDL.cs @@ -1,3 +1,4 @@ +<<<<<<< HEAD using System; using System.Collections.Generic; using System.Drawing; @@ -388,3 +389,480 @@ namespace BizHawk.Client.EmuHawk #endregion } } +======= +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Windows.Forms; + +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Common.IEmulatorExtensions; + +using BizHawk.Emulation.Cores.Nintendo.Gameboy; +using BizHawk.Emulation.Cores.Components.H6280; +using BizHawk.Emulation.Cores.PCEngine; +using BizHawk.Emulation.Cores.Consoles.Sega; +using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; + +using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk.ToolExtensions; + +//TODO - select which memorydomains go out to the CDL file. will this cause a problem when re-importing it? + //perhaps missing domains shouldnt fail a check +//OR - just add a contextmenu option to the listview item that selects it for export. +//TODO - add a contextmenu option which warps to the hexeditor with the provided domain selected for visualizing on the hex editor. +//TODO - consider setting colors for columns in CDL +//TODO - option to print domain name in caption instead of 0x01 etc. +//TODO - context menu should have copy option too + +namespace BizHawk.Client.EmuHawk +{ + public partial class CDL : Form, IToolFormAutoConfig + { + private RecentFiles _recent_fld = new RecentFiles(); + + [ConfigPersist] + private RecentFiles _recent + { + get + { return _recent_fld; } + set + { + _recent_fld = value; + if (_recent_fld.AutoLoad) + { + LoadFile(_recent.MostRecent); + SetCurrentFilename(_recent.MostRecent); + } + } + } + + void SetCurrentFilename(string fname) + { + _currentFilename = fname; + if (_currentFilename == null) + Text = "Code Data Logger"; + else Text = string.Format("Code Data Logger - {0}", fname); + } + + [RequiredService] + private IMemoryDomains MemoryDomains { get; set; } + + [RequiredService] + private ICodeDataLogger CodeDataLogger { get; set; } + + private string _currentFilename = null; + private CodeDataLog _cdl; + + public CDL() + { + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + SetStyle(ControlStyles.UserPaint, true); + SetStyle(ControlStyles.OptimizedDoubleBuffer, true); + InitializeComponent(); + + tsbViewStyle.SelectedIndex = 0; + } + + public void UpdateValues() + { + UpdateDisplay(false); + } + + public void FastUpdate() + { + // Do nothing + } + + public void Restart() + { + //don't try to recover the current CDL! + //even though it seems like it might be nice, it might get mixed up between games. even if we use CheckCDL. Switching games with the same memory map will be bad. + _cdl = null; + SetCurrentFilename(null); + SetLoggingActiveCheck(false); + UpdateDisplay(true); + } + + void SetLoggingActiveCheck(bool value) + { + tsbLoggingActive.Checked = value; + } + + string[][] listContents = new string[0][]; + + private void UpdateDisplay(bool force) + { + if (!tsbViewUpdate.Checked && !force) + return; + + + if (_cdl == null) + { + lvCDL.BeginUpdate(); + lvCDL.Items.Clear(); + lvCDL.EndUpdate(); + return; + } + + lvCDL.BeginUpdate(); + + listContents = new string[_cdl.Count][]; + + int idx = 0; + foreach (var kvp in _cdl) + { + int[] totals = new int[8]; + int total = 0; + unsafe + { + int* map = stackalloc int[256]; + for (int i = 0; i < 256; i++) + map[i] = 0; + + fixed (byte* data = kvp.Value) + { + byte* src = data; + byte* end = data + kvp.Value.Length; + while (src < end) + { + byte s = *src++; + map[s]++; + } + } + + for (int i = 0; i < 256; i++) + { + if(i!=0) total += map[i]; + if ((i & 0x01) != 0) totals[0] += map[i]; + if ((i & 0x02) != 0) totals[1] += map[i]; + if ((i & 0x04) != 0) totals[2] += map[i]; + if ((i & 0x08) != 0) totals[3] += map[i]; + if ((i & 0x10) != 0) totals[4] += map[i]; + if ((i & 0x20) != 0) totals[5] += map[i]; + if ((i & 0x40) != 0) totals[6] += map[i]; + if ((i & 0x80) != 0) totals[7] += map[i]; + } + } + + var bm = _cdl.GetBlockMap(); + long addr = bm[kvp.Key]; + + var lvi = listContents[idx++] = new string[13]; + lvi[0] = string.Format("{0:X8}", addr); + lvi[1] = kvp.Key; + lvi[2] = string.Format("{0:0.00}%", total / (float)kvp.Value.Length * 100f); + if (tsbViewStyle.SelectedIndex == 2) + lvi[3] = string.Format("{0:0.00}", total / 1024.0f); + else + lvi[3] = string.Format("{0}", total); + if (tsbViewStyle.SelectedIndex == 2) + { + int n = (int)(kvp.Value.Length / 1024.0f); + float ncheck = kvp.Value.Length / 1024.0f; + lvi[4] = string.Format("of {0}{1} KBytes", n == ncheck ? "" : "~", n); + } + else + lvi[4] = string.Format("of {0} Bytes", kvp.Value.Length); + for (int i = 0; i < 8; i++) + { + if (tsbViewStyle.SelectedIndex == 0) + lvi[5 + i] = string.Format("{0:0.00}%", totals[i] / (float)kvp.Value.Length * 100f); + if (tsbViewStyle.SelectedIndex == 1) + lvi[5 + i] = string.Format("{0}", totals[i]); + if (tsbViewStyle.SelectedIndex == 2) + lvi[5 + i] = string.Format("{0:0.00}", totals[i] / 1024.0f); + } + + } + lvCDL.VirtualListSize = _cdl.Count; + lvCDL.EndUpdate(); + } + + public bool AskSaveChanges() + { + return true; + } + + public bool UpdateBefore + { + get { return false; } + } + + public void LoadFile(string path) + { + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read)) + { + var newCDL = new CodeDataLog(); + newCDL.Load(fs); + + //have the core create a CodeDataLog to check mapping information against + var testCDL = new CodeDataLog(); + CodeDataLogger.NewCDL(testCDL); + if (!newCDL.Check(testCDL)) + { + MessageBox.Show(this, "CDL file does not match emulator's current memory map!"); + return; + } + + //ok, it's all good: + _cdl = newCDL; + CodeDataLogger.SetCDL(null); + if (tsbLoggingActive.Checked) + CodeDataLogger.SetCDL(_cdl); + + SetCurrentFilename(path); + } + + UpdateDisplay(true); + } + + private void FileSubMenu_DropDownOpened(object sender, EventArgs e) + { + SaveMenuItem.Enabled = _currentFilename != null; + SaveAsMenuItem.Enabled = + AppendMenuItem.Enabled = + ClearMenuItem.Enabled = + DisassembleMenuItem.Enabled = + _cdl != null; + } + + private void RecentSubMenu_DropDownOpened(object sender, EventArgs e) + { + RecentSubMenu.DropDownItems.Clear(); + RecentSubMenu.DropDownItems.AddRange(_recent.RecentMenu(LoadFile, true)); + } + + void NewFileLogic() + { + _cdl = new CodeDataLog(); + CodeDataLogger.NewCDL(_cdl); + + if (tsbLoggingActive.Checked) + CodeDataLogger.SetCDL(_cdl); + else CodeDataLogger.SetCDL(null); + + SetCurrentFilename(null); + + UpdateDisplay(true); + } + + private void NewMenuItem_Click(object sender, EventArgs e) + { + //take care not to clobber an existing CDL + if (_cdl != null) + { + var result = MessageBox.Show(this, "OK to create new CDL?", "Query", MessageBoxButtons.YesNo); + if (result != DialogResult.Yes) + return; + } + + NewFileLogic(); + } + + private void OpenMenuItem_Click(object sender, EventArgs e) + { + var file = ToolHelpers.OpenFileDialog( + _currentFilename, + PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null), + "Code Data Logger Files", + "cdl"); + + if (file == null) + return; + + //take care not to clobber an existing CDL + if (_cdl != null) + { + var result = MessageBox.Show(this, "OK to load new CDL?", "Query", MessageBoxButtons.YesNo); + if (result != DialogResult.Yes) + return; + } + + LoadFile(file.FullName); + } + + private void SaveMenuItem_Click(object sender, EventArgs e) + { + if (string.IsNullOrWhiteSpace(_currentFilename)) + { + RunSaveAs(); + return; + } + + using (var fs = new FileStream(_currentFilename, FileMode.Create, FileAccess.Write)) + { + _cdl.Save(fs); + } + } + + void RunSaveAs() + { + if (_cdl == null) + { + MessageBox.Show(this, "Cannot save with no CDL loaded!", "Alert"); + } + else + { + var file = ToolHelpers.SaveFileDialog( + _currentFilename, + PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null), + "Code Data Logger Files", + "cdl"); + + if (file != null) + { + using (var fs = new FileStream(file.FullName, FileMode.Create, FileAccess.Write)) + { + _cdl.Save(fs); + _recent.Add(file.FullName); + SetCurrentFilename(file.FullName); + } + } + } + } + + private void SaveAsMenuItem_Click(object sender, EventArgs e) + { + RunSaveAs(); + } + + private void AppendMenuItem_Click(object sender, EventArgs e) + { + if (_cdl == null) + { + MessageBox.Show(this, "Cannot append with no CDL loaded!", "Alert"); + } + else + { + var file = ToolHelpers.OpenFileDialog( + _currentFilename, + PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null), + "Code Data Logger Files", + "cdl"); + + if (file != null) + { + using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) + { + var newCDL = new CodeDataLog(); + newCDL.Load(fs); + if (!_cdl.Check(newCDL)) + { + MessageBox.Show(this, "CDL file does not match emulator's current memory map!"); + return; + } + _cdl.LogicalOrFrom(newCDL); + UpdateDisplay(true); + } + } + } + } + + private void ClearMenuItem_Click(object sender, EventArgs e) + { + if (_cdl == null) + { + MessageBox.Show(this, "Cannot clear with no CDL loaded!", "Alert"); + } + else + { + var result = MessageBox.Show(this, "OK to clear CDL?", "Query", MessageBoxButtons.YesNo); + if (result == DialogResult.Yes) + { + _cdl.ClearData(); + UpdateDisplay(true); + } + } + } + + private void DisassembleMenuItem_Click(object sender, EventArgs e) + { + if (_cdl == null) + { + MessageBox.Show(this, "Cannot disassemble with no CDL loaded!", "Alert"); + return; + } + + var sfd = new SaveFileDialog(); + var result = sfd.ShowDialog(this); + if (result == DialogResult.OK) + { + using (var fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write)) + { + CodeDataLogger.DisassembleCDL(fs, _cdl); + } + } + } + + private void ExitMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + protected override void OnClosed(EventArgs e) + { + //deactivate logger + if (CodeDataLogger != null) //just in case... + CodeDataLogger.SetCDL(null); + } + + private void PCECDL_Load(object sender, EventArgs e) + { + } + + private void PCECDL_DragEnter(object sender, DragEventArgs e) + { + e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None; + } + + private void PCECDL_DragDrop(object sender, DragEventArgs e) + { + var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop); + if (Path.GetExtension(filePaths[0]) == ".cdl") + { + LoadFile(filePaths[0]); + } + } + + + + private void tsbViewStyle_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateDisplay(true); + } + + private void tsbLoggingActive_CheckedChanged(object sender, EventArgs e) + { + if (tsbLoggingActive.Checked && _cdl == null) + { + //implicitly create a new file + NewFileLogic(); + } + + if (_cdl != null && tsbLoggingActive.Checked) + CodeDataLogger.SetCDL(_cdl); + else + CodeDataLogger.SetCDL(null); + } + + private void lvCDL_QueryItemText(int item, int subItem, out string text) + { + text = listContents[item][subItem]; + } + + private void tsbExportText_Click(object sender, EventArgs e) + { + StringWriter sw = new StringWriter(); + foreach(var line in listContents) + { + foreach (var entry in line) + sw.Write("{0} |", entry); + sw.WriteLine(); + } + Clipboard.SetText(sw.ToString()); + } + } +} +>>>>>>> refs/remotes/TASVideos/master diff --git a/BizHawk.Client.EmuHawk/tools/CDL.resx b/BizHawk.Client.EmuHawk/tools/CDL.resx index abf0610feb..04180bb397 100644 --- a/BizHawk.Client.EmuHawk/tools/CDL.resx +++ b/BizHawk.Client.EmuHawk/tools/CDL.resx @@ -1,3 +1,4 @@ +<<<<<<< HEAD  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 126, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG + YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 + 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw + bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc + VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 + c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 + Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo + mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ + kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D + TgDQASA1MVpwzwAAAABJRU5ErkJggg== + + + + + AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAQAMAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACMWwCMWwCMWwCMWwCMWwCMWwCMWwCMWwCMWwCMWwCMWwCMWwAAAAAAAAAAAACMWxApOoZ + jN1ApOoCMWyj0/Wj0/Wj0/Wj0/Wj0/Wj0/Wj0/Wj0/UCMWwAAAACMWxApOpApOoCMWxApOoZjN0CMWyj + 0/UuKfAuKfCj0/XLPAPLPANApOpApOoCMWwCMWwZjN0CMWwQUHwCMWxApOoCMWxApOouKfCj0/Wj0/XL + PAOj0/XLPAOj0/UCMWwCMWxApOoCMWwQUHwCMWxApOoCMWyj0/UuKfCj0/Wj0/XLPAOj0/XLPAOj0/UC + MWwCMWxApOoCMWwQUHwCMWxApOoCMWyj0/UuKfCj0/Wj0/XLPAOj0/XLPAOj0/UCMWwCMWxApOoCMWwQ + UHwCMWwZjN0CMWyj0/UuKfAuKfCj0/XLPAPLPANApOpApOoCMWwCMWxApOoCMWwQUHwCMWwZjN0CMWyj + 0/Wj0/Wj0/VApOpApOpApOpApOpApOoCMWwCMWwZjN1ApOoCMWxApOpApOoCMWyj0/Wj0/Wj0/UCMWwC + MWyj0/Wj0/Wj0/UCMWwAAAACMWxApOpApOoZjN0CMWxApOpApOqj0/UCMWyj0/Wj0/Wj0/Wj0/UCMWwA + AAAAAAAAAAACMWwCMWwCMWwCMWwCMWwCMWwCMWyj0/VApOqj0/UCMWwCMWwAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAACMWyj0/VApOqj0/UOOwMOOwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAOOwMjpQUCMWyj0/UOOwMhhwkjpQUOOwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOOwMhhwkjpQUC + MWwOOwMjpQUhhwkOOwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMLAQOOwMOOwMAAAAOOwMhhwkjpQUO + OwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOOwMjpQUOOwMAAADAAwAAgAEAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAwAMAAP+BAAD/AAAA/wAAAP8QAAD/8QAA + + +>>>>>>> refs/remotes/TASVideos/master \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs b/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs index 729eb90a01..6a6517757c 100644 --- a/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs +++ b/BizHawk.Client.EmuHawk/tools/Cheats/CheatEdit.cs @@ -31,6 +31,11 @@ namespace BizHawk.Client.EmuHawk private Action _editCallback; private void CheatEdit_Load(object sender, EventArgs e) + { + Restart(); + } + + public void Restart() { if (MemoryDomains != null) // the designer needs this check { diff --git a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs index fcca55df1a..accf994cc6 100644 --- a/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs +++ b/BizHawk.Client.EmuHawk/tools/Cheats/Cheats.cs @@ -73,6 +73,7 @@ namespace BizHawk.Client.EmuHawk public void Restart() { CheatEditor.MemoryDomains = Core; + CheatEditor.Restart(); } /// diff --git a/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs b/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs index 5a870e5dd2..e61f3e09d2 100644 --- a/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs +++ b/BizHawk.Client.EmuHawk/tools/Watch/RamWatch.cs @@ -397,13 +397,17 @@ namespace BizHawk.Client.EmuHawk if (SelectedWatches.Any()) { + foreach (var sw in SelectedWatches) + if (sw.Domain != SelectedWatches.First().Domain) + throw new InvalidOperationException("Can't edit multiple watches on varying memorydomains"); + var we = new WatchEditor { InitialLocation = this.ChildPointToScreen(WatchListView), MemoryDomains = _memoryDomains }; - we.SetWatch(_watches.Domain, SelectedWatches, duplicate ? WatchEditor.Mode.Duplicate : WatchEditor.Mode.Edit); + we.SetWatch(SelectedWatches.First().Domain, SelectedWatches, duplicate ? WatchEditor.Mode.Duplicate : WatchEditor.Mode.Edit); var result = we.ShowHawkDialog(); if (result == DialogResult.OK) diff --git a/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs b/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs index 3e3ed84cea..53a8dd6a83 100644 --- a/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs +++ b/BizHawk.Client.EmuHawk/tools/Watch/WatchEditor.cs @@ -118,7 +118,7 @@ namespace BizHawk.Client.EmuHawk DomainDropDown.Items.AddRange(MemoryDomains .Select(d => d.ToString()) .ToArray()); - DomainDropDown.SelectedItem = MemoryDomains.MainMemory.ToString(); + DomainDropDown.SelectedItem = domain.ToString(); SetTitle(); } diff --git a/BizHawk.Common/BizHawk.Common.csproj b/BizHawk.Common/BizHawk.Common.csproj index 1a05d5b78c..825675481d 100644 --- a/BizHawk.Common/BizHawk.Common.csproj +++ b/BizHawk.Common/BizHawk.Common.csproj @@ -74,8 +74,10 @@ + + diff --git a/BizHawk.Common/HawkFile.cs b/BizHawk.Common/HawkFile.cs index e4a2286125..0cd336d2c5 100644 --- a/BizHawk.Common/HawkFile.cs +++ b/BizHawk.Common/HawkFile.cs @@ -105,6 +105,11 @@ namespace BizHawk.Common /// public bool IsArchive { get { return _isArchive; } } + /// + /// Indicates whether the file is an archive member (IsArchive && IsBound[to member]) + /// + public bool IsArchiveMember { get { return IsArchive && IsBound; } } + public IList ArchiveItems { get @@ -168,6 +173,19 @@ namespace BizHawk.Common } } + /// + /// attempts to read all the content from the file + /// + public byte[] ReadAllBytes() + { + using (Stream stream = GetStream()) + { + var ms = new MemoryStream((int)stream.Length); + stream.CopyTo(ms); + return ms.GetBuffer(); + } + } + /// /// these extensions won't even be tried as archives (removes spurious archive detects since some of the signatures are pretty damn weak) /// diff --git a/BizHawk.Common/InstanceDll.cs b/BizHawk.Common/InstanceDll.cs index 090f2323ab..9996f6402c 100644 --- a/BizHawk.Common/InstanceDll.cs +++ b/BizHawk.Common/InstanceDll.cs @@ -1,3 +1,4 @@ +<<<<<<< HEAD using System; using System.IO; using System.Runtime.InteropServices; @@ -45,3 +46,79 @@ namespace BizHawk.Common IntPtr _hModule; } } +======= +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace BizHawk.Common +{ + public class InstanceDll : IDisposable + { + public InstanceDll(string dllPath) + { + //copy the dll to a temp directory + var path = Path.Combine(Path.GetTempPath(), "instancedll-pid" + System.Diagnostics.Process.GetCurrentProcess().Id + "-" + Guid.NewGuid()) + "-" + Path.GetFileName(dllPath); + using (var stream = new FileStream(path, FileMode.Create, System.Security.AccessControl.FileSystemRights.FullControl, FileShare.ReadWrite | FileShare.Delete, 4 * 1024, FileOptions.None)) + using (var sdll = File.OpenRead(dllPath)) + sdll.CopyTo(stream); + + //try to locate dlls in the current directory (for libretro cores) + //this isnt foolproof but its a little better than nothing + //setting PWD temporarily doesnt work. that'd be ideal since it supposedly gets searched early on, + //but i guess not with SetDllDirectory in effect + var envpath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process); + try + { + string envpath_new = Path.GetDirectoryName(path) + ";" + envpath; + Environment.SetEnvironmentVariable("PATH", envpath_new, EnvironmentVariableTarget.Process); + _hModule = LoadLibrary(path); //consider using LoadLibraryEx instead of shenanigans? + var newfname = Path.GetFileName(path); + newfname = "bizhawk.bizdelete-" + newfname; + var newpath = Path.Combine(Path.GetDirectoryName(path), newfname); + File.Move(path, newpath); + } + finally + { + Environment.SetEnvironmentVariable("PATH", envpath, EnvironmentVariableTarget.Process); + } + } + + [Flags] + enum LoadLibraryFlags : uint + { + DONT_RESOLVE_DLL_REFERENCES = 0x00000001, + LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, + LOAD_LIBRARY_AS_DATAFILE = 0x00000002, + LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, + LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, + LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 + } + + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr LoadLibrary(string dllToLoad); + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); + [DllImport("kernel32.dll")] + static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); + [DllImport("kernel32.dll")] + static extern bool FreeLibrary(IntPtr hModule); + + public IntPtr GetProcAddress(string procName) + { + return GetProcAddress(_hModule, procName); + } + + public void Dispose() + { + if (_hModule != IntPtr.Zero) + { + FreeLibrary(_hModule); + _hModule = IntPtr.Zero; + } + } + + IntPtr _hModule; + } +} +>>>>>>> refs/remotes/TASVideos/master diff --git a/BizHawk.Common/Sprintf.cs b/BizHawk.Common/Sprintf.cs new file mode 100644 index 0000000000..faa3ef4699 --- /dev/null +++ b/BizHawk.Common/Sprintf.cs @@ -0,0 +1,668 @@ +//Richard Prinz, MIT license +//http://www.codeproject.com/Articles/19274/A-printf-implementation-in-C + +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Runtime.InteropServices; + +namespace BizHawk.Common +{ + public static unsafe class Sprintf + { + #region Public Methods + #region IsNumericType + /// + /// Determines whether the specified value is of numeric type. + /// + /// The object to check. + /// + /// true if o is a numeric type; otherwise, false. + /// + public static bool IsNumericType( object o ) + { + return ( o is byte || + o is sbyte || + o is short || + o is ushort || + o is int || + o is uint || + o is long || + o is ulong || + o is float || + o is double || + o is decimal ); + } + #endregion + #region IsPositive + /// + /// Determines whether the specified value is positive. + /// + /// The value. + /// if set to true treats 0 as positive. + /// + /// true if the specified value is positive; otherwise, false. + /// + public static bool IsPositive( object Value, bool ZeroIsPositive ) + { + switch ( Type.GetTypeCode( Value.GetType() ) ) + { + case TypeCode.SByte: + return ( ZeroIsPositive ? (sbyte)Value >= 0 : (sbyte)Value > 0 ); + case TypeCode.Int16: + return ( ZeroIsPositive ? (short)Value >= 0 : (short)Value > 0 ); + case TypeCode.Int32: + return ( ZeroIsPositive ? (int)Value >= 0 : (int)Value > 0 ); + case TypeCode.Int64: + return ( ZeroIsPositive ? (long)Value >= 0 : (long)Value > 0 ); + case TypeCode.Single: + return ( ZeroIsPositive ? (float)Value >= 0 : (float)Value > 0 ); + case TypeCode.Double: + return ( ZeroIsPositive ? (double)Value >= 0 : (double)Value > 0 ); + case TypeCode.Decimal: + return ( ZeroIsPositive ? (decimal)Value >= 0 : (decimal)Value > 0 ); + case TypeCode.Byte: + return ( ZeroIsPositive ? true : (byte)Value > 0 ); + case TypeCode.UInt16: + return ( ZeroIsPositive ? true : (ushort)Value > 0 ); + case TypeCode.UInt32: + return ( ZeroIsPositive ? true : (uint)Value > 0 ); + case TypeCode.UInt64: + return ( ZeroIsPositive ? true : (ulong)Value > 0 ); + case TypeCode.Char: + return ( ZeroIsPositive ? true : (char)Value != '\0' ); + default: + return false; + } + } + #endregion + #region ToUnsigned + /// + /// Converts the specified values boxed type to its correpsonding unsigned + /// type. + /// + /// The value. + /// A boxed numeric object whos type is unsigned. + public static object ToUnsigned( object Value ) + { + switch ( Type.GetTypeCode( Value.GetType() ) ) + { + case TypeCode.SByte: + return (byte)( (sbyte)Value ); + case TypeCode.Int16: + return (ushort)( (short)Value ); + case TypeCode.Int32: + return (uint)( (int)Value ); + case TypeCode.Int64: + return (ulong)( (long)Value ); + + case TypeCode.Byte: + return Value; + case TypeCode.UInt16: + return Value; + case TypeCode.UInt32: + return Value; + case TypeCode.UInt64: + return Value; + + case TypeCode.Single: + return (UInt32)( (float)Value ); + case TypeCode.Double: + return (ulong)( (double)Value ); + case TypeCode.Decimal: + return (ulong)( (decimal)Value ); + + default: + return null; + } + } + #endregion + #region ToInteger + /// + /// Converts the specified values boxed type to its correpsonding integer + /// type. + /// + /// The value. + /// A boxed numeric object whos type is an integer type. + public static object ToInteger( object Value, bool Round ) + { + switch ( Type.GetTypeCode( Value.GetType() ) ) + { + case TypeCode.SByte: + return Value; + case TypeCode.Int16: + return Value; + case TypeCode.Int32: + return Value; + case TypeCode.Int64: + return Value; + + case TypeCode.Byte: + return Value; + case TypeCode.UInt16: + return Value; + case TypeCode.UInt32: + return Value; + case TypeCode.UInt64: + return Value; + + case TypeCode.Single: + return ( Round ? (int)Math.Round( (float)Value ) : (int)( (float)Value ) ); + case TypeCode.Double: + return ( Round ? (long)Math.Round( (double)Value ) : (long)( (double)Value ) ); + case TypeCode.Decimal: + return ( Round ? Math.Round( (decimal)Value ) : (decimal)Value ); + + default: + return null; + } + } + #endregion + #region UnboxToLong + public static long UnboxToLong( object Value, bool Round ) + { + switch ( Type.GetTypeCode( Value.GetType() ) ) + { + case TypeCode.SByte: + return (long)( (sbyte)Value ); + case TypeCode.Int16: + return (long)( (short)Value ); + case TypeCode.Int32: + return (long)( (int)Value ); + case TypeCode.Int64: + return (long)Value; + + case TypeCode.Byte: + return (long)( (byte)Value ); + case TypeCode.UInt16: + return (long)( (ushort)Value ); + case TypeCode.UInt32: + return (long)( (uint)Value ); + case TypeCode.UInt64: + return (long)( (ulong)Value ); + + case TypeCode.Single: + return ( Round ? (long)Math.Round( (float)Value ) : (long)( (float)Value ) ); + case TypeCode.Double: + return ( Round ? (long)Math.Round( (double)Value ) : (long)( (double)Value ) ); + case TypeCode.Decimal: + return ( Round ? (long)Math.Round( (decimal)Value ) : (long)( (decimal)Value ) ); + + default: + return 0; + } + } + #endregion + #region ReplaceMetaChars + /// + /// Replaces the string representations of meta chars with their corresponding + /// character values. + /// + /// The input. + /// A string with all string meta chars are replaced + public static string ReplaceMetaChars( string input ) + { + return Regex.Replace( input, @"(\\)(\d{3}|[^\d])?", new MatchEvaluator( ReplaceMetaCharsMatch ) ); + } + private static string ReplaceMetaCharsMatch( Match m ) + { + // convert octal quotes (like \040) + if ( m.Groups[2].Length == 3 ) + return Convert.ToChar( Convert.ToByte( m.Groups[2].Value, 8 ) ).ToString(); + else + { + // convert all other special meta characters + //TODO: \xhhh hex and possible dec !! + switch ( m.Groups[2].Value ) + { + case "0": // null + return "\0"; + case "a": // alert (beep) + return "\a"; + case "b": // BS + return "\b"; + case "f": // FF + return "\f"; + case "v": // vertical tab + return "\v"; + case "r": // CR + return "\r"; + case "n": // LF + return "\n"; + case "t": // Tab + return "\t"; + default: + // if neither an octal quote nor a special meta character + // so just remove the backslash + return m.Groups[2].Value; + } + } + } + #endregion + #region sprintf + public static string sprintf( string Format, Func fetcher ) + { + #region Variables + StringBuilder f = new StringBuilder(); + Regex r = new Regex( @"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])" ); + //"%[parameter][flags][width][.precision][length]type" + Match m = null; + string w = String.Empty; + int defaultParamIx = 0; + int paramIx; + object o = null; + + bool flagLeft2Right = false; + bool flagAlternate = false; + bool flagPositiveSign = false; + bool flagPositiveSpace = false; + bool flagZeroPadding = false; + bool flagGroupThousands = false; + + int fieldLength = 0; + int fieldPrecision = 0; + char shortLongIndicator = '\0'; + char formatSpecifier = '\0'; + char paddingCharacter = ' '; + #endregion + + // find all format parameters in format string + f.Append( Format ); + m = r.Match( f.ToString() ); + while ( m.Success ) + { + #region parameter index + paramIx = defaultParamIx; + if ( m.Groups[1] != null && m.Groups[1].Value.Length > 0 ) + { + string val = m.Groups[1].Value.Substring( 0, m.Groups[1].Value.Length - 1 ); + paramIx = Convert.ToInt32( val ) - 1; + }; + #endregion + + #region format flags + // extract format flags + flagAlternate = false; + flagLeft2Right = false; + flagPositiveSign = false; + flagPositiveSpace = false; + flagZeroPadding = false; + flagGroupThousands = false; + if ( m.Groups[2] != null && m.Groups[2].Value.Length > 0 ) + { + string flags = m.Groups[2].Value; + + flagAlternate = ( flags.IndexOf( '#' ) >= 0 ); + flagLeft2Right = ( flags.IndexOf( '-' ) >= 0 ); + flagPositiveSign = ( flags.IndexOf( '+' ) >= 0 ); + flagPositiveSpace = ( flags.IndexOf( ' ' ) >= 0 ); + flagGroupThousands = ( flags.IndexOf( '\'' ) >= 0 ); + + // positive + indicator overrides a + // positive space character + if ( flagPositiveSign && flagPositiveSpace ) + flagPositiveSpace = false; + } + #endregion + + #region field length + // extract field length and + // pading character + paddingCharacter = ' '; + fieldLength = int.MinValue; + if ( m.Groups[3] != null && m.Groups[3].Value.Length > 0 ) + { + fieldLength = Convert.ToInt32( m.Groups[3].Value ); + flagZeroPadding = ( m.Groups[3].Value[0] == '0' ); + } + #endregion + + if ( flagZeroPadding ) + paddingCharacter = '0'; + + // left2right allignment overrides zero padding + if ( flagLeft2Right && flagZeroPadding ) + { + flagZeroPadding = false; + paddingCharacter = ' '; + } + + #region field precision + // extract field precision + fieldPrecision = int.MinValue; + if ( m.Groups[4] != null && m.Groups[4].Value.Length > 0 ) + fieldPrecision = Convert.ToInt32( m.Groups[4].Value ); + #endregion + + #region short / long indicator + // extract short / long indicator + shortLongIndicator = Char.MinValue; + if ( m.Groups[5] != null && m.Groups[5].Value.Length > 0 ) + shortLongIndicator = m.Groups[5].Value[0]; + #endregion + + #region format specifier + // extract format + formatSpecifier = Char.MinValue; + if ( m.Groups[6] != null && m.Groups[6].Value.Length > 0 ) + formatSpecifier = m.Groups[6].Value[0]; + #endregion + + // default precision is 6 digits if none is specified except + if ( fieldPrecision == int.MinValue && + formatSpecifier != 's' && + formatSpecifier != 'c' && + Char.ToUpper( formatSpecifier ) != 'X' && + formatSpecifier != 'o' ) + fieldPrecision = 6; + + #region get next value parameter + IntPtr n = fetcher(); + // get next value parameter and convert value parameter depending on short / long indicator + //if ( Parameters == null || paramIx >= Parameters.Length ) + // o = null; + //else + { + if (shortLongIndicator == 'h') + { + o = (short)(n.ToInt32()); + } + else if (shortLongIndicator == 'l') + { + //zero 08-nov-2015 - something like this for longs, but i dont think this is a long + //o = n.ToInt32() + (((long)(fetcher().ToInt32()) << 32)); + throw new InvalidOperationException("horn-rimmed astatine embryology"); + } + else o = n.ToInt32(); + } + #endregion + + // convert value parameters to a string depending on the formatSpecifier + w = String.Empty; + switch ( formatSpecifier ) + { + #region % - character + case '%': // % character + w = "%"; + break; + #endregion + #region d - integer + case 'd': // integer + w = FormatNumber( ( flagGroupThousands ? "n" : "d" ), flagAlternate, + fieldLength, int.MinValue, flagLeft2Right, + flagPositiveSign, flagPositiveSpace, + paddingCharacter, o ); + defaultParamIx++; + break; + #endregion + #region i - integer + case 'i': // integer + goto case 'd'; + #endregion + #region o - octal integer + case 'o': // octal integer - no leading zero + w = FormatOct( "o", flagAlternate, + fieldLength, int.MinValue, flagLeft2Right, + paddingCharacter, o ); + defaultParamIx++; + break; + #endregion + #region x - hex integer + case 'x': // hex integer - no leading zero + w = FormatHex( "x", flagAlternate, + fieldLength, fieldPrecision, flagLeft2Right, + paddingCharacter, o ); + defaultParamIx++; + break; + #endregion + #region X - hex integer + case 'X': // same as x but with capital hex characters + w = FormatHex( "X", flagAlternate, + fieldLength, fieldPrecision, flagLeft2Right, + paddingCharacter, o ); + defaultParamIx++; + break; + #endregion + #region u - unsigned integer + case 'u': // unsigned integer + w = FormatNumber( ( flagGroupThousands ? "n" : "d" ), flagAlternate, + fieldLength, int.MinValue, flagLeft2Right, + false, false, + paddingCharacter, ToUnsigned( o ) ); + defaultParamIx++; + break; + #endregion + #region c - character + case 'c': // character + w = ((char)(n.ToInt32())).ToString(); + defaultParamIx++; + break; + #endregion + #region s - string + case 's': // string + string t = "{0" + ( fieldLength != int.MinValue ? "," + ( flagLeft2Right ? "-" : String.Empty ) + fieldLength.ToString() : String.Empty ) + ":s}"; + w = Marshal.PtrToStringAnsi(n); + if ( fieldPrecision >= 0 ) + w = w.Substring( 0, fieldPrecision ); + + if ( fieldLength != int.MinValue ) + if ( flagLeft2Right ) + w = w.PadRight( fieldLength, paddingCharacter ); + else + w = w.PadLeft( fieldLength, paddingCharacter ); + defaultParamIx++; + break; + #endregion + #region f - double number + case 'f': // double + throw new InvalidOperationException("cataleptic kangaroo orchestra"); + //w = FormatNumber( ( flagGroupThousands ? "n" : "f" ), flagAlternate, + // fieldLength, fieldPrecision, flagLeft2Right, + // flagPositiveSign, flagPositiveSpace, + // paddingCharacter, o ); + //defaultParamIx++; + //break; + #endregion + #region e - exponent number + case 'e': // double / exponent + throw new InvalidOperationException("cataleptic kangaroo orchestra"); + //w = FormatNumber( "e", flagAlternate, + // fieldLength, fieldPrecision, flagLeft2Right, + // flagPositiveSign, flagPositiveSpace, + // paddingCharacter, o ); + //defaultParamIx++; + //break; + #endregion + #region E - exponent number + case 'E': // double / exponent + throw new InvalidOperationException("cataleptic kangaroo orchestra"); + //w = FormatNumber( "E", flagAlternate, + // fieldLength, fieldPrecision, flagLeft2Right, + // flagPositiveSign, flagPositiveSpace, + // paddingCharacter, o ); + //defaultParamIx++; + //break; + #endregion + #region g - general number + case 'g': // double / exponent + throw new InvalidOperationException("cataleptic kangaroo orchestra"); + //w = FormatNumber( "g", flagAlternate, + // fieldLength, fieldPrecision, flagLeft2Right, + // flagPositiveSign, flagPositiveSpace, + // paddingCharacter, o ); + //defaultParamIx++; + //break; + #endregion + #region G - general number + case 'G': // double / exponent + throw new InvalidOperationException("cataleptic kangaroo orchestra"); + //w = FormatNumber( "G", flagAlternate, + // fieldLength, fieldPrecision, flagLeft2Right, + // flagPositiveSign, flagPositiveSpace, + // paddingCharacter, o ); + //defaultParamIx++; + //break; + #endregion + #region p - pointer + case 'p': // pointer + if ( o is IntPtr ) + w = "0x" + n.ToString( "x" ); + defaultParamIx++; + break; + #endregion + #region n - number of processed chars so far + case 'n': // number of characters so far + w = FormatNumber( "d", flagAlternate, + fieldLength, int.MinValue, flagLeft2Right, + flagPositiveSign, flagPositiveSpace, + paddingCharacter, m.Index ); + break; + #endregion + default: + w = String.Empty; + defaultParamIx++; + break; + } + + // replace format parameter with parameter value + // and start searching for the next format parameter + // AFTER the position of the current inserted value + // to prohibit recursive matches if the value also + // includes a format specifier + f.Remove( m.Index, m.Length ); + f.Insert( m.Index, w ); + m = r.Match( f.ToString(), m.Index + w.Length ); + } + + return f.ToString(); + } + #endregion + #endregion + + #region Private Methods + #region FormatOCT + private static string FormatOct( string NativeFormat, bool Alternate, + int FieldLength, int FieldPrecision, + bool Left2Right, + char Padding, object Value ) + { + string w = String.Empty; + string lengthFormat = "{0" + ( FieldLength != int.MinValue ? + "," + ( Left2Right ? + "-" : + String.Empty ) + FieldLength.ToString() : + String.Empty ) + "}"; + + if ( IsNumericType( Value ) ) + { + w = Convert.ToString( UnboxToLong( Value, true ), 8 ); + + if ( Left2Right || Padding == ' ' ) + { + if ( Alternate && w != "0" ) + w = "0" + w; + w = String.Format( lengthFormat, w ); + } + else + { + if ( FieldLength != int.MinValue ) + w = w.PadLeft( FieldLength - ( Alternate && w != "0" ? 1 : 0 ), Padding ); + if ( Alternate && w != "0" ) + w = "0" + w; + } + } + + return w; + } + #endregion + #region FormatHEX + private static string FormatHex( string NativeFormat, bool Alternate, + int FieldLength, int FieldPrecision, + bool Left2Right, + char Padding, object Value ) + { + string w = String.Empty; + string lengthFormat = "{0" + ( FieldLength != int.MinValue ? + "," + ( Left2Right ? + "-" : + String.Empty ) + FieldLength.ToString() : + String.Empty ) + "}"; + string numberFormat = "{0:" + NativeFormat + ( FieldPrecision != int.MinValue ? + FieldPrecision.ToString() : + String.Empty ) + "}"; + + if ( IsNumericType( Value ) ) + { + w = String.Format( numberFormat, Value ); + + if ( Left2Right || Padding == ' ' ) + { + if ( Alternate ) + w = ( NativeFormat == "x" ? "0x" : "0X" ) + w; + w = String.Format( lengthFormat, w ); + } + else + { + if ( FieldLength != int.MinValue ) + w = w.PadLeft( FieldLength - ( Alternate ? 2 : 0 ), Padding ); + if ( Alternate ) + w = ( NativeFormat == "x" ? "0x" : "0X" ) + w; + } + } + + return w; + } + #endregion + #region FormatNumber + private static string FormatNumber( string NativeFormat, bool Alternate, + int FieldLength, int FieldPrecision, + bool Left2Right, + bool PositiveSign, bool PositiveSpace, + char Padding, object Value ) + { + string w = String.Empty; + string lengthFormat = "{0" + ( FieldLength != int.MinValue ? + "," + ( Left2Right ? + "-" : + String.Empty ) + FieldLength.ToString() : + String.Empty ) + "}"; + string numberFormat = "{0:" + NativeFormat + ( FieldPrecision != int.MinValue ? + FieldPrecision.ToString() : + "0" ) + "}"; + + if ( IsNumericType( Value ) ) + { + w = String.Format( numberFormat, Value ); + + if ( Left2Right || Padding == ' ' ) + { + if ( IsPositive( Value, true ) ) + w = ( PositiveSign ? + "+" : ( PositiveSpace ? " " : String.Empty ) ) + w; + w = String.Format( lengthFormat, w ); + } + else + { + if ( w.StartsWith( "-" ) ) + w = w.Substring( 1 ); + if ( FieldLength != int.MinValue ) + w = w.PadLeft( FieldLength - 1, Padding ); + if ( IsPositive( Value, true ) ) + w = ( PositiveSign ? + "+" : ( PositiveSpace ? + " " : ( FieldLength != int.MinValue ? + Padding.ToString() : String.Empty ) ) ) + w; + else + w = "-" + w; + } + } + + return w; + } + #endregion + #endregion + } +} + + diff --git a/BizHawk.Common/UnmanagedResourceHeap.cs b/BizHawk.Common/UnmanagedResourceHeap.cs new file mode 100644 index 0000000000..901587fba3 --- /dev/null +++ b/BizHawk.Common/UnmanagedResourceHeap.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace BizHawk.Common +{ + public class UnmanagedResourceHeap : IDisposable + { + public IntPtr StringToHGlobalAnsi(string str) + { + var ret = Marshal.StringToHGlobalAnsi(str); + HGlobals.Add(ret); + return ret; + } + + public List HGlobals = new List(); + + public void Dispose() + { + foreach (var h in HGlobals) + Marshal.FreeHGlobal(h); + HGlobals.Clear(); + } + } +} diff --git a/BizHawk.Common/Util.cs b/BizHawk.Common/Util.cs index 58be27a1d2..c145556987 100644 --- a/BizHawk.Common/Util.cs +++ b/BizHawk.Common/Util.cs @@ -8,7 +8,7 @@ using System.Reflection; namespace BizHawk.Common { - public static unsafe class Util + public static unsafe partial class Util { public static void CopyStream(Stream src, Stream dest, long len) { diff --git a/BizHawk.Common/Win32Hacks.cs b/BizHawk.Common/Win32Hacks.cs index 5405076205..88313cb295 100644 --- a/BizHawk.Common/Win32Hacks.cs +++ b/BizHawk.Common/Win32Hacks.cs @@ -4,6 +4,75 @@ using System.Runtime.InteropServices; namespace BizHawk.Common { + public static class Win32PInvokes + { + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsProcessorFeaturePresent(ProcessorFeature processorFeature); + + public enum ProcessorFeature : uint + { + /// + /// On a Pentium, a floating-point precision error can occur in rare circumstances + /// + FloatingPointPrecisionErrata = 0, + /// + /// Floating-point operations are emulated using a software emulator. + /// This function returns a nonzero value if floating-point operations are emulated; otherwise, it returns zero. + /// + FloatingPointEmulated = 1, + /// + /// The atomic compare and exchange operation (cmpxchg) is available + /// + CompareExchangeDouble = 2, + /// + /// The MMX instruction set is available + /// + InstructionsMMXAvailable = 3, + /// + /// The SSE instruction set is available + /// + InstructionsXMMIAvailable = 6, + /// + /// The 3D-Now instruction set is available. + /// + Instruction3DNowAvailable = 7, + /// + /// The RDTSC instruction is available + /// + InstructionRDTSCAvailable = 8, + /// + /// The processor is PAE-enabled + /// + PAEEnabled = 9, + /// + /// The SSE2 instruction set is available + /// + InstructionsXMMI64Available = 10, + /// + /// Data execution prevention is enabled. (This feature is not supported until Windows XP SP2 and Windows Server 2003 SP1) + /// + NXEnabled = 12, + /// + /// The SSE3 instruction set is available. (This feature is not supported until Windows Vista) + /// + InstructionsSSE3Available = 13, + /// + /// The atomic compare and exchange 128-bit operation (cmpxchg16b) is available. (This feature is not supported until Windows Vista) + /// + CompareExchange128 = 14, + /// + /// The atomic compare 64 and exchange 128-bit operation (cmp8xchg16) is available (This feature is not supported until Windows Vista.) + /// + Compare64Exchange128 = 15, + /// + /// TBD + /// + ChannelsEnabled = 16, + } + + } + //largely from https://raw.githubusercontent.com/noserati/tpl/master/ThreadAffinityTaskScheduler.cs (MIT license) public static class Win32ThreadHacks { diff --git a/BizHawk.Emulation.Common/CodeDataLog.cs b/BizHawk.Emulation.Common/CodeDataLog.cs index ff0f0d05f1..b5e3bbc8f3 100644 --- a/BizHawk.Emulation.Common/CodeDataLog.cs +++ b/BizHawk.Emulation.Common/CodeDataLog.cs @@ -1,3 +1,4 @@ +<<<<<<< HEAD using System; using System.Collections.Generic; using System.Linq; @@ -135,3 +136,182 @@ namespace BizHawk.Emulation.Common } } +======= +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Common +{ + public class CodeDataLog : Dictionary + { + public CodeDataLog() + { + } + + /// + /// Pins the managed arrays. Not that we expect them to be allocated, but in case we do, seeing thish ere will remind us to check for the pin condition and abort + /// + public void Pin() + { + if (Pins.Count != 0) + throw new InvalidOperationException("incremental astrological examination"); + foreach (var kvp in this) + Pins[kvp.Key] = GCHandle.Alloc(kvp.Value, GCHandleType.Pinned); + } + + /// + /// Unpins the managed arrays, to be paired with calls to Pin() + /// + public void Unpin() + { + foreach (var pin in Pins.Values) + pin.Free(); + Pins.Clear(); + } + + /// + /// Retrieves the pointer to a managed array + /// + public IntPtr GetPin(string key) + { + return Pins[key].AddrOfPinnedObject(); + } + + /// + /// Pinned managed arrays + /// + Dictionary Pins = new Dictionary(); + + /// + /// Whether the CDL is tracking a block with the given name + /// + public bool Has(string blockname) { return ContainsKey(blockname); } + + /// + /// This is just a hook, if needed, to readily suspend logging, without having to rewire the core + /// + public bool Active = true; + + public string SubType; + public int SubVer; + + /// + /// Tests whether the other CodeDataLog is structurally identical + /// + public bool Check(CodeDataLog other) + { + if (SubType != other.SubType) + return false; + if (SubVer != other.SubVer) + return false; + + if (this.Count != other.Count) + return false; + foreach (var kvp in this) + { + if (!other.ContainsKey(kvp.Key)) + return false; + var oval = other[kvp.Key]; + if (oval.Length != kvp.Value.Length) + return false; + } + + return true; + } + + public void LogicalOrFrom(CodeDataLog other) + { + if (this.Count != other.Count) + throw new InvalidDataException("Dictionaries must have the same number of keys!"); + + foreach (var kvp in other) + { + byte[] fromdata = kvp.Value; + byte[] todata = this[kvp.Key]; + + if (fromdata.Length != todata.Length) + throw new InvalidDataException("Memory regions must be the same size!"); + + for (int i = 0; i < todata.Length; i++) + todata[i] |= fromdata[i]; + } + } + + public void ClearData() + { + foreach (byte[] data in Values) + Array.Clear(data, 0, data.Length); + } + + public void Save(Stream s) + { + _Save(s, true); + } + + Dictionary _Save(Stream s, bool forReal) + { + var ret = new Dictionary(); + var w = new BinaryWriter(s); + w.Write("BIZHAWK-CDL-2"); + w.Write(SubType.PadRight(15)); + w.Write(Count); + w.Flush(); + long addr = s.Position; + if (forReal) + { + foreach (var kvp in this) + { + w.Write(kvp.Key); + w.Write(kvp.Value.Length); + w.Write(kvp.Value); + } + } + else + { + foreach (var kvp in this) + { + addr += kvp.Key.Length + 1; //assumes shortly-encoded key names + addr += 4; + ret[kvp.Key] = addr; + addr += kvp.Value.Length; + } + } + w.Flush(); + return ret; + } + + public Dictionary GetBlockMap() + { + return _Save(new MemoryStream(), false); + } + + public void Load(Stream s) + { + var br = new BinaryReader(s); + string id = br.ReadString(); + if (id == "BIZHAWK-CDL-1") + SubType = "PCE"; + else if (id == "BIZHAWK-CDL-2") + SubType = br.ReadString().TrimEnd(' '); + else + throw new InvalidDataException("File is not a Bizhawk CDL file!"); + + int count = br.ReadInt32(); + for (int i = 0; i < count; i++) + { + string key = br.ReadString(); + int len = br.ReadInt32(); + byte[] data = br.ReadBytes(len); + this[key] = data; + } + + } + + } +} +>>>>>>> refs/remotes/TASVideos/master diff --git a/BizHawk.Emulation.Common/CoreComms.cs b/BizHawk.Emulation.Common/CoreComms.cs index 557691c1a1..d963c81ec8 100644 --- a/BizHawk.Emulation.Common/CoreComms.cs +++ b/BizHawk.Emulation.Common/CoreComms.cs @@ -38,6 +38,9 @@ namespace BizHawk.Emulation.Common public bool LinkConnected = false; public bool UsesLinkCable = false; + //I know we want to get rid of CoreComm, but while it's still here, I'll use it for this + public string LaunchLibretroCore; + /// /// show a message. reasonably annoying (dialog box), shouldn't be used most of the time /// diff --git a/BizHawk.Emulation.Common/Interfaces/ICoreFileProvider.cs b/BizHawk.Emulation.Common/Interfaces/ICoreFileProvider.cs index b335f60d47..75f2c4074c 100644 --- a/BizHawk.Emulation.Common/Interfaces/ICoreFileProvider.cs +++ b/BizHawk.Emulation.Common/Interfaces/ICoreFileProvider.cs @@ -17,6 +17,14 @@ namespace BizHawk.Emulation.Common /// string DllPath(); + /// + /// produces a path that contains saveram... because libretro cores need it? not sure yet + /// + string GetSaveRAMPath(); + + string GetGameBasePath(); + + #region EmuLoadHelper api /// diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs index 0faf37d3dc..05136dcc62 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs @@ -151,6 +151,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public int MessageCounter; + void WritePipeInt(int n) + { + } + + void WritePipePointer(IntPtr ptr, bool flush = true) + { + bwPipe.Write(ptr.ToInt32()); + if(flush) bwPipe.Flush(); + } + void WritePipeMessage(eMessage msg) { if(!bufio) MessageCounter++; @@ -191,6 +201,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public Action ReadHook, ExecHook; public Action WriteHook; + public enum eCDLog_AddrType + { + CARTROM, CARTRAM, WRAM, APURAM, + NUM + }; + + public enum eCDLog_Flags + { + ExecFirst = 0x01, + ExecOperand = 0x02, + CPUData = 0x04, + DMAData = 0x08, //not supported yet + BRR = 0x80, + }; + Dictionary SharedMemoryBlocks = new Dictionary(); Dictionary DeallocatedMemoryBlocks = new Dictionary(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_Enums.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_Enums.cs index a1d30bef5c..affb989217 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_Enums.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_Enums.cs @@ -41,6 +41,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES eMessage_QUERY_set_backdropColor, eMessage_QUERY_peek_logical_register, eMessage_QUERY_peek_cpu_regs, + eMessage_QUERY_set_cdl, eMessage_CMD_FIRST, eMessage_CMD_init, diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs index 493a1afa05..93c514e285 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi_QUERY.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using BizHawk.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.SNES { @@ -180,7 +181,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES { public uint pc; public ushort a, x, y, z, s, d, vector; //7x - public byte p, nothing; + public byte p, nothing; public uint aa, rd; public byte sp, dp, db, mdr; public const int SIZEOF = 32; @@ -195,6 +196,39 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES fixed(CpuRegs* ptr = &ret) Marshal.Copy(temp, 0, new IntPtr(ptr), CpuRegs.SIZEOF); } + + public void QUERY_set_cdl(CodeDataLog cdl) + { + WritePipeMessage(eMessage.eMessage_QUERY_set_cdl); + if (cdl == null) + { + for(int i=0;i<4*2;i++) + WritePipePointer(IntPtr.Zero); + } + else + { + WritePipePointer(cdl.GetPin("CARTROM"),false); + bwPipe.Write(cdl["CARTROM"].Length); + + if (cdl.Has("CARTRAM")) + { + WritePipePointer(cdl.GetPin("CARTRAM"), false); + bwPipe.Write(cdl["CARTRAM"].Length); + } + else + { + WritePipePointer(IntPtr.Zero); + WritePipePointer(IntPtr.Zero); + } + + WritePipePointer(cdl.GetPin("WRAM")); + bwPipe.Write(cdl["WRAM"].Length); + + WritePipePointer(cdl.GetPin("APURAM"), false); + bwPipe.Write(cdl["APURAM"].Length); + bwPipe.Flush(); + } + } } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs index 0078b9c861..ad7b619b62 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesCore.cs @@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES portedUrl: "http://byuu.org/" )] [ServiceNotApplicable(typeof(IDriveLight))] - public unsafe class LibsnesCore : IEmulator, IVideoProvider, ISaveRam, IStatable, IInputPollable, IRegionable, + public unsafe class LibsnesCore : IEmulator, IVideoProvider, ISaveRam, IStatable, IInputPollable, IRegionable, ICodeDataLogger, IDebuggable, ISettable { public LibsnesCore(GameInfo game, byte[] romData, bool deterministicEmulation, byte[] xmlData, CoreComm comm, object Settings, object SyncSettings) @@ -56,7 +56,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES this.Settings = (SnesSettings)Settings ?? new SnesSettings(); this.SyncSettings = (SnesSyncSettings)SyncSettings ?? new SnesSyncSettings(); - api = new LibsnesApi(GetExePath()); + api = new LibsnesApi(GetDllPath()); api.ReadHook = ReadHook; api.ExecHook = ExecHook; api.WriteHook = WriteHook; @@ -170,6 +170,37 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES } } + CodeDataLog currCdl; + + public void SetCDL(CodeDataLog cdl) + { + if(currCdl != null) currCdl.Unpin(); + currCdl = cdl; + if(currCdl != null) currCdl.Pin(); + + //set it no matter what. if its null, the cdl will be unhooked from libsnes internally + api.QUERY_set_cdl(currCdl); + } + + public void NewCDL(CodeDataLog cdl) + { + cdl["CARTROM"] = new byte[MemoryDomains["CARTROM"].Size]; + + if (MemoryDomains.Has("CARTRAM")) + cdl["CARTRAM"] = new byte[MemoryDomains["CARTRAM"].Size]; + + cdl["WRAM"] = new byte[MemoryDomains["WRAM"].Size]; + cdl["APURAM"] = new byte[MemoryDomains["APURAM"].Size]; + + cdl.SubType = "SNES"; + cdl.SubVer = 0; + } + + public void DisassembleCDL(Stream s, CodeDataLog cdl) + { + //not supported yet + } + public IEmulatorServiceProvider ServiceProvider { get; private set; } private GameInfo _game; @@ -204,6 +235,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES resampler.Dispose(); api.Dispose(); + + if (currCdl != null) currCdl.Unpin(); } public IDictionary GetCpuFlagsAndRegisters() @@ -376,21 +409,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public LibsnesApi api; System.Xml.XmlDocument romxml; - string GetExePath() + string GetDllPath() { - const string bits = "32"; - // disabled til it works - // if (Win32.Is64BitOperatingSystem) - // bits = "64"; + var exename = "libsneshawk-32-" + CurrentProfile.ToLower() + ".dll"; - var exename = "libsneshawk-" + bits + "-" + CurrentProfile.ToLower() + ".dll"; + string dllPath = Path.Combine(CoreComm.CoreFileProvider.DllPath(), exename); - string exePath = Path.Combine(CoreComm.CoreFileProvider.DllPath(), exename); + if (!File.Exists(dllPath)) + throw new InvalidOperationException("Couldn't locate the DLL for SNES emulation for profile: " + CurrentProfile + ". Please make sure you're using a fresh dearchive of a BizHawk distribution."); - if (!File.Exists(exePath)) - throw new InvalidOperationException("Couldn't locate the executable for SNES emulation for profile: " + CurrentProfile + ". Please make sure you're using a fresh dearchive of a BizHawk distribution."); - - return exePath; + return dllPath; } void ReadHook(uint addr) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs index 537bfed059..1f3ac22c98 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/SNESGraphicsDecoder.cs @@ -5,6 +5,10 @@ //helpful detailed reg list //http://wiki.superfamicom.org/snes/show/Registers +//TODO +//SF2 title art doesnt seem to show up.. +//scanline control doesnt work? + using System; namespace BizHawk.Emulation.Cores.Nintendo.SNES diff --git a/BizHawk.Emulation.Cores/LibRetro.cs b/BizHawk.Emulation.Cores/LibRetro.cs index 1d0444788c..5bdcfca37a 100644 --- a/BizHawk.Emulation.Cores/LibRetro.cs +++ b/BizHawk.Emulation.Cores/LibRetro.cs @@ -5,6 +5,8 @@ using System.Text; using System.Runtime.InteropServices; using System.Reflection; +using BizHawk.Common; + namespace BizHawk.Emulation.Cores { /// @@ -46,6 +48,16 @@ namespace BizHawk.Emulation.Cores R3 = 15 }; + public enum RETRO_LOG_LEVEL : int //exact type size is unclear + { + DEBUG = 0, + INFO, + WARN, + ERROR, + + DUMMY = Int32.MaxValue + }; + public enum RETRO_DEVICE_ID_ANALOG { // LEFT / RIGHT? @@ -102,150 +114,150 @@ namespace BizHawk.Emulation.Cores public enum RETRO_KEY { - UNKNOWN = 0, - FIRST = 0, - BACKSPACE = 8, - TAB = 9, - CLEAR = 12, - RETURN = 13, - PAUSE = 19, - ESCAPE = 27, - SPACE = 32, - EXCLAIM = 33, - QUOTEDBL = 34, - HASH = 35, - DOLLAR = 36, - AMPERSAND = 38, - QUOTE = 39, - LEFTPAREN = 40, - RIGHTPAREN = 41, - ASTERISK = 42, - PLUS = 43, - COMMA = 44, - MINUS = 45, - PERIOD = 46, - SLASH = 47, - _0 = 48, - _1 = 49, - _2 = 50, - _3 = 51, - _4 = 52, - _5 = 53, - _6 = 54, - _7 = 55, - _8 = 56, - _9 = 57, - COLON = 58, - SEMICOLON = 59, - LESS = 60, - EQUALS = 61, - GREATER = 62, - QUESTION = 63, - AT = 64, - LEFTBRACKET = 91, - BACKSLASH = 92, - RIGHTBRACKET = 93, - CARET = 94, - UNDERSCORE = 95, - BACKQUOTE = 96, - a = 97, - b = 98, - c = 99, - d = 100, - e = 101, - f = 102, - g = 103, - h = 104, - i = 105, - j = 106, - k = 107, - l = 108, - m = 109, - n = 110, - o = 111, - p = 112, - q = 113, - r = 114, - s = 115, - t = 116, - u = 117, - v = 118, - w = 119, - x = 120, - y = 121, - z = 122, - DELETE = 127, + UNKNOWN = 0, + FIRST = 0, + BACKSPACE = 8, + TAB = 9, + CLEAR = 12, + RETURN = 13, + PAUSE = 19, + ESCAPE = 27, + SPACE = 32, + EXCLAIM = 33, + QUOTEDBL = 34, + HASH = 35, + DOLLAR = 36, + AMPERSAND = 38, + QUOTE = 39, + LEFTPAREN = 40, + RIGHTPAREN = 41, + ASTERISK = 42, + PLUS = 43, + COMMA = 44, + MINUS = 45, + PERIOD = 46, + SLASH = 47, + _0 = 48, + _1 = 49, + _2 = 50, + _3 = 51, + _4 = 52, + _5 = 53, + _6 = 54, + _7 = 55, + _8 = 56, + _9 = 57, + COLON = 58, + SEMICOLON = 59, + LESS = 60, + EQUALS = 61, + GREATER = 62, + QUESTION = 63, + AT = 64, + LEFTBRACKET = 91, + BACKSLASH = 92, + RIGHTBRACKET = 93, + CARET = 94, + UNDERSCORE = 95, + BACKQUOTE = 96, + a = 97, + b = 98, + c = 99, + d = 100, + e = 101, + f = 102, + g = 103, + h = 104, + i = 105, + j = 106, + k = 107, + l = 108, + m = 109, + n = 110, + o = 111, + p = 112, + q = 113, + r = 114, + s = 115, + t = 116, + u = 117, + v = 118, + w = 119, + x = 120, + y = 121, + z = 122, + DELETE = 127, - KP0 = 256, - KP1 = 257, - KP2 = 258, - KP3 = 259, - KP4 = 260, - KP5 = 261, - KP6 = 262, - KP7 = 263, - KP8 = 264, - KP9 = 265, - KP_PERIOD = 266, - KP_DIVIDE = 267, - KP_MULTIPLY = 268, - KP_MINUS = 269, - KP_PLUS = 270, - KP_ENTER = 271, - KP_EQUALS = 272, + KP0 = 256, + KP1 = 257, + KP2 = 258, + KP3 = 259, + KP4 = 260, + KP5 = 261, + KP6 = 262, + KP7 = 263, + KP8 = 264, + KP9 = 265, + KP_PERIOD = 266, + KP_DIVIDE = 267, + KP_MULTIPLY = 268, + KP_MINUS = 269, + KP_PLUS = 270, + KP_ENTER = 271, + KP_EQUALS = 272, - UP = 273, - DOWN = 274, - RIGHT = 275, - LEFT = 276, - INSERT = 277, - HOME = 278, - END = 279, - PAGEUP = 280, - PAGEDOWN = 281, + UP = 273, + DOWN = 274, + RIGHT = 275, + LEFT = 276, + INSERT = 277, + HOME = 278, + END = 279, + PAGEUP = 280, + PAGEDOWN = 281, - F1 = 282, - F2 = 283, - F3 = 284, - F4 = 285, - F5 = 286, - F6 = 287, - F7 = 288, - F8 = 289, - F9 = 290, - F10 = 291, - F11 = 292, - F12 = 293, - F13 = 294, - F14 = 295, - F15 = 296, + F1 = 282, + F2 = 283, + F3 = 284, + F4 = 285, + F5 = 286, + F6 = 287, + F7 = 288, + F8 = 289, + F9 = 290, + F10 = 291, + F11 = 292, + F12 = 293, + F13 = 294, + F14 = 295, + F15 = 296, - NUMLOCK = 300, - CAPSLOCK = 301, - SCROLLOCK = 302, - RSHIFT = 303, - LSHIFT = 304, - RCTRL = 305, - LCTRL = 306, - RALT = 307, - LALT = 308, - RMETA = 309, - LMETA = 310, - LSUPER = 311, - RSUPER = 312, - MODE = 313, - COMPOSE = 314, + NUMLOCK = 300, + CAPSLOCK = 301, + SCROLLOCK = 302, + RSHIFT = 303, + LSHIFT = 304, + RCTRL = 305, + LCTRL = 306, + RALT = 307, + LALT = 308, + RMETA = 309, + LMETA = 310, + LSUPER = 311, + RSUPER = 312, + MODE = 313, + COMPOSE = 314, - HELP = 315, - PRINT = 316, - SYSREQ = 317, - BREAK = 318, - MENU = 319, - POWER = 320, - EURO = 321, - UNDO = 322, + HELP = 315, + PRINT = 316, + SYSREQ = 317, + BREAK = 318, + MENU = 319, + POWER = 320, + EURO = 321, + UNDO = 322, - LAST + LAST }; [Flags] @@ -261,6 +273,29 @@ namespace BizHawk.Emulation.Cores SCROLLLOCK = 64 }; + [Flags] + public enum RETRO_SIMD + { + SSE = (1 << 0), + SSE2 = (1 << 1), + VMX = (1 << 2), + VMX128 = (1 << 3), + AVX = (1 << 4), + NEON = (1 << 5), + SSE3 = (1 << 6), + SSSE3 = (1 << 7), + MMX = (1 << 8), + MMXEXT = (1 << 9), + SSE4 = (1 << 10), + SSE42 = (1 << 11), + AVX2 = (1 << 12), + VFPU = (1 << 13), + PS = (1 << 14), + AES = (1 << 15), + VFPV3 = (1 << 16), + VFPV4 = (1 << 17), + } + public enum RETRO_ENVIRONMENT { SET_ROTATION = 1, @@ -284,6 +319,22 @@ namespace BizHawk.Emulation.Cores SET_FRAME_TIME_CALLBACK = 21, GET_RUMBLE_INTERFACE = 23, GET_INPUT_DEVICE_CAPABILITIES = 24, + //25,26 are experimental + GET_LOG_INTERFACE = 27, + GET_PERF_INTERFACE = 28, + GET_LOCATION_INTERFACE = 29, + GET_CORE_ASSETS_DIRECTORY = 30, + GET_SAVE_DIRECTORY = 31, + SET_SYSTEM_AV_INFO = 32, + SET_PROC_ADDRESS_CALLBACK = 33, + SET_SUBSYSTEM_INFO = 34, + SET_CONTROLLER_INFO = 35, + SET_MEMORY_MAPS = 36 | EXPERIMENTAL, + SET_GEOMETRY = 37, + GET_USERNAME = 38, + GET_LANGUAGE = 39, + + EXPERIMENTAL = 0x10000 }; public enum RETRO_PIXEL_FORMAT @@ -353,8 +404,50 @@ namespace BizHawk.Emulation.Cores public string meta; } + //untested + public struct retro_perf_counter + { + public string ident; + public ulong start; + public ulong total; + public ulong call_cnt; + + [MarshalAs(UnmanagedType.U1)] + public bool registered; + }; + + //perf callbacks + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long retro_perf_get_time_usec_t(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long retro_perf_get_counter_t(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate ulong retro_get_cpu_features_t(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void retro_perf_log_t(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void retro_perf_register_t(ref retro_perf_counter counter); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void retro_perf_start_t(ref retro_perf_counter counter); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void retro_perf_stop_t(ref retro_perf_counter counter); + + //for GET_PERF_INTERFACE + public struct retro_perf_callback + { + public retro_perf_get_time_usec_t get_time_usec; + public retro_get_cpu_features_t get_cpu_features; + public retro_perf_get_counter_t get_perf_counter; + public retro_perf_register_t perf_register; + public retro_perf_start_t perf_start; + public retro_perf_stop_t perf_stop; + public retro_perf_log_t perf_log; + } + #region callback prototypes [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public unsafe delegate void retro_log_printf_t(RETRO_LOG_LEVEL level, string fmt, IntPtr a0, IntPtr a1, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6, IntPtr a7, IntPtr a8, IntPtr a9, IntPtr a10, IntPtr a11, IntPtr a12, IntPtr a13, IntPtr a14, IntPtr a15); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return:MarshalAs(UnmanagedType.U1)] public delegate bool retro_environment_t(RETRO_ENVIRONMENT cmd, IntPtr data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -425,6 +518,7 @@ namespace BizHawk.Emulation.Cores [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate uint epretro_get_memory_size(RETRO_MEMORY id); #endregion + #region entry points // these are all hooked up by reflection on dll load public epretro_set_environment retro_set_environment; @@ -457,65 +551,22 @@ namespace BizHawk.Emulation.Cores public epretro_get_memory_size retro_get_memory_size; #endregion - private static Dictionary AttachedCores = new Dictionary(); - private IntPtr hModule = IntPtr.Zero; - public void Dispose() { - // like many other emu cores, libretros are in general single instance, so we track some things - lock (AttachedCores) - { - if (hModule != IntPtr.Zero) - { - retro_deinit(); - ClearAllEntryPoints(); - Win32.FreeLibrary(hModule); - AttachedCores.Remove(hModule); - hModule = IntPtr.Zero; - } - } + dll.Dispose(); } + InstanceDll dll; public LibRetro(string modulename) { - // like many other emu cores, libretros are in general single instance, so we track some things - lock (AttachedCores) + dll = new InstanceDll(modulename); + if (!ConnectAllEntryPoints()) { - IntPtr newmodule = Win32.LoadLibrary(modulename); - if (newmodule == IntPtr.Zero) - throw new Exception(string.Format("LoadLibrary(\"{0}\") returned NULL", modulename)); - - if (AttachedCores.ContainsKey(newmodule)) - { - // this core is already loaded, so we must detatch the old instance - LibRetro martyr = AttachedCores[newmodule]; - martyr.retro_deinit(); - martyr.ClearAllEntryPoints(); - martyr.hModule = IntPtr.Zero; - Win32.FreeLibrary(newmodule); // decrease ref count by 1 - } - AttachedCores[newmodule] = this; - hModule = newmodule; - if (!ConnectAllEntryPoints()) - { - ClearAllEntryPoints(); - Win32.FreeLibrary(hModule); - hModule = IntPtr.Zero; - throw new Exception("ConnectAllEntryPoints() failed. The console may contain more details."); - } + dll.Dispose(); + throw new Exception("ConnectAllEntryPoints() failed. The console may contain more details."); } } - private static class Win32 - { - [DllImport("kernel32.dll")] - public static extern IntPtr LoadLibrary(string dllToLoad); - [DllImport("kernel32.dll")] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); - [DllImport("kernel32.dll")] - public static extern bool FreeLibrary(IntPtr hModule); - } - private static IEnumerable GetAllEntryPoints() { return typeof(LibRetro).GetFields().Where((field) => field.FieldType.Name.StartsWith("epretro")); @@ -535,7 +586,7 @@ namespace BizHawk.Emulation.Cores foreach (var field in GetAllEntryPoints()) { string fieldname = field.Name; - IntPtr entry = Win32.GetProcAddress(hModule, fieldname); + IntPtr entry = dll.GetProcAddress(fieldname); if (entry != IntPtr.Zero) { field.SetValue(this, Marshal.GetDelegateForFunctionPointer(entry, field.FieldType)); diff --git a/BizHawk.Emulation.Cores/LibRetroEmulator.cs b/BizHawk.Emulation.Cores/LibRetroEmulator.cs index aa97549041..3946fdc706 100644 --- a/BizHawk.Emulation.Cores/LibRetroEmulator.cs +++ b/BizHawk.Emulation.Cores/LibRetroEmulator.cs @@ -1,20 +1,104 @@ using System; +using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; +using Newtonsoft.Json; +using BizHawk.Common; using BizHawk.Emulation.Common; +using BizHawk.Common.BufferExtensions; namespace BizHawk.Emulation.Cores { - [CoreAttributes("DEBUG ONLY DON'T USE", "natt")] - public unsafe class LibRetroEmulator : IEmulator, IVideoProvider + [CoreAttributes("Libretro", "natt&zeromus")] + public unsafe class LibRetroEmulator : IEmulator, ISettable, + ISaveRam, IStatable, IVideoProvider, IInputPollable { + #region Settings + + Settings _Settings = new Settings(); + SyncSettings _SyncSettings; + + public class SyncSettings + { + public SyncSettings Clone() + { + return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(this)); + } + + public SyncSettings() + { + } + } + + + public class Settings + { + public void Validate() + { + } + + public Settings() + { + SettingsUtil.SetDefaultValues(this); + } + + public Settings Clone() + { + return (Settings)MemberwiseClone(); + } + } + + public Settings GetSettings() + { + return _Settings.Clone(); + } + + public SyncSettings GetSyncSettings() + { + return _SyncSettings.Clone(); + } + + public bool PutSettings(Settings o) + { + _Settings.Validate(); + _Settings = o; + + //TODO - store settings into core? or we can just keep doing it before frameadvance + + return false; + } + + public bool PutSyncSettings(SyncSettings o) + { + bool reboot = false; + + //we could do it this way roughly if we need to + //if(JsonConvert.SerializeObject(o.FIOConfig) != JsonConvert.SerializeObject(_SyncSettings.FIOConfig) + + _SyncSettings = o; + + return reboot; + } + + #endregion + #region callbacks - bool retro_environment(LibRetro.RETRO_ENVIRONMENT cmd, IntPtr data) + unsafe void retro_log_printf(LibRetro.RETRO_LOG_LEVEL level, string fmt, IntPtr a0, IntPtr a1, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6, IntPtr a7, IntPtr a8, IntPtr a9, IntPtr a10, IntPtr a11, IntPtr a12, IntPtr a13, IntPtr a14, IntPtr a15) { + //avert your eyes, these things were not meant to be seen in c# + //I'm not sure this is a great idea. It would suck for silly logging to be unstable. But.. I dont think this is unstable. The sprintf might just print some garbledy stuff. + var args = new IntPtr[] { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 }; + int idx = 0; + Console.Write(Sprintf.sprintf(fmt, () => args[idx++])); + } + + unsafe bool retro_environment(LibRetro.RETRO_ENVIRONMENT cmd, IntPtr data) + { + Console.WriteLine(cmd); switch (cmd) { case LibRetro.RETRO_ENVIRONMENT.SET_ROTATION: @@ -36,6 +120,11 @@ namespace BizHawk.Emulation.Cores case LibRetro.RETRO_ENVIRONMENT.SET_PERFORMANCE_LEVEL: return false; case LibRetro.RETRO_ENVIRONMENT.GET_SYSTEM_DIRECTORY: + //please write an example of a core that crashes without this (fmsx malfunctions..) + //"this is optional, but many cores will silently malfunction without it as they can't load their firmware files" + //an alternative (alongside where the saverams and such will go?) + //*((IntPtr*)data.ToPointer()) = unmanagedResources.StringToHGlobalAnsi(CoreComm.CoreFileProvider.GetGameBasePath()); + *((IntPtr*)data.ToPointer()) = SystemDirectoryAtom; return false; case LibRetro.RETRO_ENVIRONMENT.SET_PIXEL_FORMAT: { @@ -66,12 +155,47 @@ namespace BizHawk.Emulation.Cores // this can be done in principle, but there's no reason to right now return false; case LibRetro.RETRO_ENVIRONMENT.GET_VARIABLE: - return false; + { + void** variables = (void**)data.ToPointer(); + IntPtr pKey = new IntPtr(*variables++); + string key = Marshal.PtrToStringAnsi(pKey); + Console.WriteLine("Requesting variable: {0}", key); + //always return default + //TODO: cache settings atoms + if(!Description.Variables.ContainsKey(key)) + return false; + //HACK: return pointer for desmume mouse, i want to implement that first + if (key == "desmume_pointer_type") + { + *variables = unmanagedResources.StringToHGlobalAnsi("touch").ToPointer(); + return true; + } + *variables = unmanagedResources.StringToHGlobalAnsi(Description.Variables[key].DefaultOption).ToPointer(); + return true; + } case LibRetro.RETRO_ENVIRONMENT.SET_VARIABLES: + { + void** variables = (void**)data.ToPointer(); + for (; ; ) + { + IntPtr pKey = new IntPtr(*variables++); + IntPtr pValue = new IntPtr(*variables++); + if(pKey == IntPtr.Zero) + break; + string key = Marshal.PtrToStringAnsi(pKey); + string value = Marshal.PtrToStringAnsi(pValue); + var vd = new VariableDescription() { Name = key}; + var parts = value.Split(';'); + vd.Description = parts[0]; + vd.Options = parts[1].TrimStart(' ').Split('|'); + Description.Variables[vd.Name] = vd; + } + } return false; case LibRetro.RETRO_ENVIRONMENT.GET_VARIABLE_UPDATE: return false; case LibRetro.RETRO_ENVIRONMENT.SET_SUPPORT_NO_GAME: + environmentInfo.SupportNoGame = true; return false; case LibRetro.RETRO_ENVIRONMENT.GET_LIBRETRO_PATH: return false; @@ -83,6 +207,25 @@ namespace BizHawk.Emulation.Cores return false; case LibRetro.RETRO_ENVIRONMENT.GET_INPUT_DEVICE_CAPABILITIES: return false; + case LibRetro.RETRO_ENVIRONMENT.GET_LOG_INTERFACE: + *(IntPtr*)data = Marshal.GetFunctionPointerForDelegate(retro_log_printf_cb); + return true; + case LibRetro.RETRO_ENVIRONMENT.GET_PERF_INTERFACE: + //some builds of fmsx core crash without this set + Marshal.StructureToPtr(retro_perf_callback, data, false); + return true; + case LibRetro.RETRO_ENVIRONMENT.GET_LOCATION_INTERFACE: + return false; + case LibRetro.RETRO_ENVIRONMENT.GET_CORE_ASSETS_DIRECTORY: + return false; + case LibRetro.RETRO_ENVIRONMENT.GET_SAVE_DIRECTORY: + //supposedly optional like everything else here, but without it ?? crashes (please write which case) + //this will suffice for now. if we find evidence later it's needed we can stash a string with + //unmanagedResources and CoreFileProvider + //*((IntPtr*)data.ToPointer()) = IntPtr.Zero; + return false; + case LibRetro.RETRO_ENVIRONMENT.SET_CONTROLLER_INFO: + return true; default: Console.WriteLine("Unknkown retro_environment command {0}", (int)cmd); return false; @@ -92,9 +235,68 @@ namespace BizHawk.Emulation.Cores { IsLagFrame = false; } + + private bool GetButton(uint pnum, string type, string button) + { + string key = string.Format("P{0} {1} {2}", pnum, type, button); + bool b = Controller[key]; + if (b == true) + { + return true; //debugging placeholder + } + else return false; + } + + //meanings (they are kind of hazy, but once we're done implementing this it will be completely defined by example) + //port = console physical port? + //device = logical device type + //index = sub device index? (multitap?) + //id = button id short retro_input_state(uint port, uint device, uint index, uint id) { - return 0; + //helpful debugging + //Console.WriteLine("{0} {1} {2} {3}", port, device, index, id); + + switch ((LibRetro.RETRO_DEVICE)device) + { + case LibRetro.RETRO_DEVICE.POINTER: + { + switch ((LibRetro.RETRO_DEVICE_ID_POINTER)id) + { + case LibRetro.RETRO_DEVICE_ID_POINTER.X: return (short)Controller.GetFloat("Pointer X"); + case LibRetro.RETRO_DEVICE_ID_POINTER.Y: return (short)Controller.GetFloat("Pointer Y"); + case LibRetro.RETRO_DEVICE_ID_POINTER.PRESSED: return (short)(Controller["Pointer Pressed"] ? 1 : 0); + } + return 0; + } + + case LibRetro.RETRO_DEVICE.JOYPAD: + { + //The JOYPAD is sometimes called RetroPad (and we'll call it that in user-facing stuff cos retroarch does) + //It is essentially a Super Nintendo controller, but with additional L2/R2/L3/R3 buttons, similar to a PS1 DualShock. + + string button = ""; + switch ((LibRetro.RETRO_DEVICE_ID_JOYPAD)id) + { + case LibRetro.RETRO_DEVICE_ID_JOYPAD.A: button = "A"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.B: button = "B"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.X: button = "X"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.Y: button = "Y"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.UP: button = "Up"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.DOWN: button = "Down"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.LEFT: button = "Left"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.RIGHT: button = "Right"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.L: button = "L"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.R: button = "R"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.SELECT: button = "Select"; break; + case LibRetro.RETRO_DEVICE_ID_JOYPAD.START: button = "Start"; break; + } + + return (short)(GetButton(port+1, "RetroPad", button) ? 1 : 0); + } + default: + return 0; + } } LibRetro.retro_environment_t retro_environment_cb; @@ -103,76 +305,161 @@ namespace BizHawk.Emulation.Cores LibRetro.retro_audio_sample_batch_t retro_audio_sample_batch_cb; LibRetro.retro_input_poll_t retro_input_poll_cb; LibRetro.retro_input_state_t retro_input_state_cb; + LibRetro.retro_log_printf_t retro_log_printf_cb; + + LibRetro.retro_perf_callback retro_perf_callback = new LibRetro.retro_perf_callback(); #endregion - private LibRetro retro; - - public static LibRetroEmulator CreateDebug(CoreComm nextComm, byte[] debugfile) + class RetroEnvironmentInfo { - System.IO.TextReader tr = new System.IO.StreamReader(new System.IO.MemoryStream(debugfile, false)); - string modulename = tr.ReadLine(); - string romname = tr.ReadLine(); - - byte[] romdata = System.IO.File.ReadAllBytes(romname); - - var emu = new LibRetroEmulator(nextComm, modulename); - try - { - if (!emu.Load(romdata)) - throw new Exception("LibRetroEmulator.Load() failed"); - // ... - } - catch - { - emu.Dispose(); - throw; - } - return emu; + public bool SupportNoGame; } + //disposable resources + private LibRetro retro; + private UnmanagedResourceHeap unmanagedResources = new UnmanagedResourceHeap(); + + /// + /// Cached information sent to the frontend by environment calls + /// + RetroEnvironmentInfo environmentInfo = new RetroEnvironmentInfo(); + + public class RetroDescription + { + /// + /// String containing a friendly display name for the core, but we probably shouldn't use this. I decided it's better to get the user used to using filenames as core 'codenames' instead. + /// + public string LibraryName; + + /// + /// String containing a friendly version number for the core library + /// + public string LibraryVersion; + + /// + /// List of extensions as "sfc|smc|fig" which this core accepts. + /// + public string ValidExtensions; + + /// + /// Whether the core needs roms to be specified as paths (can't take rom data buffersS) + /// + public bool NeedsRomAsPath; + + /// + /// Whether the core needs roms stored as archives (e.g. arcade roms). We probably shouldn't employ the dearchiver prompts when opening roms for these cores. + /// + public bool NeedsArchives; + + /// + /// Whether the core can be run without a game provided (e.g. stand-alone games, like 2048) + /// + public bool SupportsNoGame; + + /// + /// Variables defined by the core + /// + public Dictionary Variables = new Dictionary(); + } + + public class VariableDescription + { + public string Name; + public string Description; + public string[] Options; + public string DefaultOption { get { return Options[0]; } } + + public override string ToString() + { + return string.Format("{0} ({1}) = ({2})", Name, Description, string.Join("|", Options)); + } + } + + public readonly RetroDescription Description = new RetroDescription(); + + //path configuration + string CoresDirectory; + string SystemDirectory; + IntPtr SystemDirectoryAtom; + public LibRetroEmulator(CoreComm nextComm, string modulename) { + CoresDirectory = Path.GetDirectoryName(new FileInfo(modulename).FullName); + SystemDirectory = Path.Combine(CoresDirectory, "System"); + SystemDirectoryAtom = unmanagedResources.StringToHGlobalAnsi(SystemDirectory); + ServiceProvider = new BasicServiceProvider(this); + _SyncSettings = new SyncSettings(); + retro_environment_cb = new LibRetro.retro_environment_t(retro_environment); retro_video_refresh_cb = new LibRetro.retro_video_refresh_t(retro_video_refresh); retro_audio_sample_cb = new LibRetro.retro_audio_sample_t(retro_audio_sample); retro_audio_sample_batch_cb = new LibRetro.retro_audio_sample_batch_t(retro_audio_sample_batch); retro_input_poll_cb = new LibRetro.retro_input_poll_t(retro_input_poll); retro_input_state_cb = new LibRetro.retro_input_state_t(retro_input_state); + retro_log_printf_cb = new LibRetro.retro_log_printf_t(retro_log_printf); + + //no way (need new mechanism) to check for SSSE3, MMXEXT, SSE4, SSE42 + retro_perf_callback.get_cpu_features = new LibRetro.retro_get_cpu_features_t(() => (ulong)( + (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsXMMIAvailable) ? LibRetro.RETRO_SIMD.SSE : 0) | + (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsXMMI64Available) ? LibRetro.RETRO_SIMD.SSE2 : 0) | + (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsSSE3Available) ? LibRetro.RETRO_SIMD.SSE3 : 0) | + (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsMMXAvailable) ? LibRetro.RETRO_SIMD.MMX : 0) + ) ); + retro_perf_callback.get_perf_counter = new LibRetro.retro_perf_get_counter_t(() => System.Diagnostics.Stopwatch.GetTimestamp()); + retro_perf_callback.get_time_usec = new LibRetro.retro_perf_get_time_usec_t(() => DateTime.Now.Ticks / 10); + retro_perf_callback.perf_log = new LibRetro.retro_perf_log_t( () => {} ); + retro_perf_callback.perf_register = new LibRetro.retro_perf_register_t((ref LibRetro.retro_perf_counter counter) => { }); + retro_perf_callback.perf_start = new LibRetro.retro_perf_start_t((ref LibRetro.retro_perf_counter counter) => { }); + retro_perf_callback.perf_stop = new LibRetro.retro_perf_stop_t((ref LibRetro.retro_perf_counter counter) => { }); retro = new LibRetro(modulename); + try { CoreComm = nextComm; - LibRetro.retro_system_info sys = new LibRetro.retro_system_info(); - retro.retro_get_system_info(ref sys); - - if (sys.need_fullpath) - throw new ArgumentException("This libretro core needs filepaths"); - if (sys.block_extract) - throw new ArgumentException("This libretro needs non-blocked extract"); + //this series of steps may be mystical. + LibRetro.retro_system_info system_info = new LibRetro.retro_system_info(); + retro.retro_get_system_info(ref system_info); retro.retro_set_environment(retro_environment_cb); + retro.retro_init(); + retro.retro_set_video_refresh(retro_video_refresh_cb); retro.retro_set_audio_sample(retro_audio_sample_cb); retro.retro_set_audio_sample_batch(retro_audio_sample_batch_cb); retro.retro_set_input_poll(retro_input_poll_cb); retro.retro_set_input_state(retro_input_state_cb); + + //compile descriptive information + Description.NeedsArchives = system_info.block_extract; + Description.NeedsRomAsPath = system_info.need_fullpath; + Description.LibraryName = system_info.library_name; + Description.LibraryVersion = system_info.library_version; + Description.ValidExtensions = system_info.valid_extensions; + Description.SupportsNoGame = environmentInfo.SupportNoGame; + //variables need to be done ahead of time, when theyre set through the environment + //some retro_init (for example, desmume) will continue to use variables (and maybe other parts of the environment) from within retro_init } catch { retro.Dispose(); + retro = null; throw; } + + } public IEmulatorServiceProvider ServiceProvider { get; private set; } - public bool Load(byte[] data) + + + public bool LoadData(byte[] data) { LibRetro.retro_game_info gi = new LibRetro.retro_game_info(); fixed (byte* p = &data[0]) @@ -181,14 +468,34 @@ namespace BizHawk.Emulation.Cores gi.meta = ""; gi.path = ""; gi.size = (uint)data.Length; - if (!retro.retro_load_game(ref gi)) - { - Console.WriteLine("retro_load_game() failed"); - return false; - } - savebuff = new byte[retro.retro_serialize_size()]; - savebuff2 = new byte[savebuff.Length + 13]; + return LoadWork(ref gi); } + } + + public bool LoadPath(string path) + { + LibRetro.retro_game_info gi = new LibRetro.retro_game_info(); + gi.path = path; //is this the right encoding? seems to be ok + return LoadWork(ref gi); + } + + public bool LoadNoGame() + { + LibRetro.retro_game_info gi = new LibRetro.retro_game_info(); + return LoadWork(ref gi); + } + + bool LoadWork(ref LibRetro.retro_game_info gi) + { + if (!retro.retro_load_game(ref gi)) + { + Console.WriteLine("retro_load_game() failed"); + return false; + } + + //TODO - libretro cores can return a varying serialize size over time. I tried to get them to write it in the docs... + savebuff = new byte[retro.retro_serialize_size()]; + savebuff2 = new byte[savebuff.Length + 13]; LibRetro.retro_system_av_info av = new LibRetro.retro_system_av_info(); retro.retro_get_system_av_info(ref av); @@ -204,33 +511,49 @@ namespace BizHawk.Emulation.Cores SetupResampler(av.timing.fps, av.timing.sample_rate); + ControllerDefinition = CreateControllerDefinition(_SyncSettings); + return true; } - - public ControllerDefinition ControllerDefinition + public static ControllerDefinition CreateControllerDefinition(SyncSettings syncSettings) { - get { return NullEmulator.NullController; } + ControllerDefinition definition = new ControllerDefinition(); + definition.Name = "LibRetro Controls"; // <-- for compatibility + + foreach(var item in new[] { + "P1 {0} Up", "P1 {0} Down", "P1 {0} Left", "P1 {0} Right", "P1 {0} Select", "P1 {0} Start", "P1 {0} Y", "P1 {0} B", "P1 {0} X", "P1 {0} A", "P1 {0} L", "P1 {0} R", + "P2 {0} Up", "P2 {0} Down", "P2 {0} Left", "P2 {0} Right", "P2 {0} Select", "P2 {0} Start", "P2 {0} Y", "P2 {0} B", "P2 {0} X", "P2 {0} A", "P2 {0} L", "P2 {0} R", + }) + definition.BoolButtons.Add(string.Format(item,"RetroPad")); + + definition.BoolButtons.Add("Pointer Pressed"); + definition.FloatControls.Add("Pointer X"); + definition.FloatControls.Add("Pointer Y"); + definition.FloatRanges.Add(new ControllerDefinition.FloatRange(-32767, 0, 32767)); + definition.FloatRanges.Add(new ControllerDefinition.FloatRange(-32767, 0, 32767)); + + return definition; } + public ControllerDefinition ControllerDefinition { get; private set; } public IController Controller { get; set; } public void FrameAdvance(bool render, bool rendersound = true) { + //TODO - consider changing directory and using Libretro subdir of bizhawk as a kind of sandbox, for the duration of the run? IsLagFrame = true; Frame++; nsamprecv = 0; retro.retro_run(); - Console.WriteLine("[{0}]", nsamprecv); + //Console.WriteLine("[{0}]", nsamprecv); } public int Frame { get; private set; } - public int LagCount { get; set; } - public bool IsLagFrame { get; private set; } public string SystemId { - get { return "TEST"; } + get { return "Libretro"; } } public bool DeterministicEmulation @@ -244,7 +567,8 @@ namespace BizHawk.Emulation.Cores get { return null; } } - #region saveram + #region ISaveRam + //TODO - terrible things will happen if this changes at runtime byte[] saverambuff = new byte[0]; @@ -256,8 +580,8 @@ namespace BizHawk.Emulation.Cores IntPtr src = retro.retro_get_memory_data(LibRetro.RETRO_MEMORY.SAVE_RAM); if (src == IntPtr.Zero) - throw new Exception("retro_get_memory_data(RETRO_MEMORY_SAVE_RAM) returned NULL"); - + return null; + Marshal.Copy(src, saverambuff, 0, size); return (byte[])saverambuff.Clone(); } @@ -265,8 +589,9 @@ namespace BizHawk.Emulation.Cores public void StoreSaveRam(byte[] data) { int size = (int)retro.retro_get_memory_size(LibRetro.RETRO_MEMORY.SAVE_RAM); - if (data.Length != size) - throw new Exception("Passed saveram does not match retro_get_memory_size(RETRO_MEMORY_SAVE_RAM"); + + if (size == 0) + return; IntPtr dst = retro.retro_get_memory_data(LibRetro.RETRO_MEMORY.SAVE_RAM); if (dst == IntPtr.Zero) @@ -278,7 +603,14 @@ namespace BizHawk.Emulation.Cores public bool SaveRamModified { [FeatureNotImplemented] - get { return true; } + get + { + //if we dont have saveram, it isnt modified. otherwise, assume iti s + int size = (int)retro.retro_get_memory_size(LibRetro.RETRO_MEMORY.SAVE_RAM); + if (size == 0) + return false; + return true; + } [FeatureNotImplemented] set { throw new NotImplementedException(); } @@ -298,25 +630,32 @@ namespace BizHawk.Emulation.Cores private byte[] savebuff; private byte[] savebuff2; - [FeatureNotImplemented] public void SaveStateText(System.IO.TextWriter writer) { - throw new NotImplementedException(); + var temp = SaveStateBinary(); + temp.SaveAsHex(writer); } - [FeatureNotImplemented] public void LoadStateText(System.IO.TextReader reader) { - throw new NotImplementedException(); + string hex = reader.ReadLine(); + byte[] state = new byte[hex.Length / 2]; + state.ReadFromHex(hex); + LoadStateBinary(new BinaryReader(new MemoryStream(state))); } public void SaveStateBinary(System.IO.BinaryWriter writer) { - fixed (byte* ptr = &savebuff[0]) + //is this the only way we know of to detect unavailable savestates? + if (savebuff.Length > 0) { - if (!retro.retro_serialize((IntPtr)ptr, (uint)savebuff.Length)) - throw new Exception("retro_serialize() failed"); + fixed (byte* ptr = &savebuff[0]) + { + if (!retro.retro_serialize((IntPtr)ptr, (uint)savebuff.Length)) + throw new Exception("retro_serialize() failed"); + } } + writer.Write(savebuff.Length); writer.Write(savebuff); // other variables @@ -331,10 +670,13 @@ namespace BizHawk.Emulation.Cores if (newlen > savebuff.Length) throw new Exception("Unexpected buffer size"); reader.Read(savebuff, 0, newlen); - fixed (byte* ptr = &savebuff[0]) + if (savebuff.Length > 0) { - if (!retro.retro_unserialize((IntPtr)ptr, (uint)newlen)) - throw new Exception("retro_unserialize() failed"); + fixed (byte* ptr = &savebuff[0]) + { + if (!retro.retro_unserialize((IntPtr)ptr, (uint)newlen)) + throw new Exception("retro_unserialize() failed"); + } } // other variables Frame = reader.ReadInt32(); @@ -384,6 +726,8 @@ namespace BizHawk.Emulation.Cores retro.Dispose(); retro = null; } + unmanagedResources.Dispose(); + unmanagedResources = null; } #region ISoundProvider @@ -470,13 +814,13 @@ namespace BizHawk.Emulation.Cores { short ci = *row; int r = ci & 0x001f; - int g = ci & 0x07e0; - int b = ci & 0xf800; + int g = (ci & 0x07e0)>>5; + int b = (ci & 0xf800)>>11; r = (r << 3) | (r >> 2); - g = (g >> 3) | (g >> 9); - b = (b >> 8) | (b >> 13); - int co = r | g | b | unchecked((int)0xff000000); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + int co = (b<<16) | (g<<8) | r; *dst = co; dst++; @@ -533,8 +877,10 @@ namespace BizHawk.Emulation.Cores { get { - if (dar > 1.0f) - return (int)(BufferWidth * dar); + if(dar==0) + return BufferWidth; + else if (dar > 1.0f) + return (int)(BufferHeight * dar); else return BufferWidth; } @@ -543,8 +889,10 @@ namespace BizHawk.Emulation.Cores { get { + if(dar==0) + return BufferHeight; if (dar < 1.0f) - return (int)(BufferHeight / dar); + return (int)(BufferWidth / dar); else return BufferHeight; } @@ -555,5 +903,16 @@ namespace BizHawk.Emulation.Cores public int BackgroundColor { get { return unchecked((int)0xff000000); } } #endregion + + #region IInputPollable + public int LagCount { get; set; } + public bool IsLagFrame { get; private set; } + public IInputCallbackSystem InputCallbacks + { + [FeatureNotImplemented] + get + { throw new NotImplementedException(); } + } + #endregion } } diff --git a/Dist/changelog.txt b/Dist/changelog.txt index 1320bead7b..c9ddda8ddb 100644 --- a/Dist/changelog.txt +++ b/Dist/changelog.txt @@ -3,10 +3,46 @@ next ========================================= *EmuHawk +**Add custom exception display box, so exception info can be clipboarded out +**Support Code-Data Logger for GB/GBC, SMS/GG, and Genesis **Cheat Dialog: Fix flakiness in value-editing -**DispMethod D3D: Use FPU preserve to stop lua scripts using float math from malfunctioning +**Stop FP precision conflicts between lua scripts and D3D Display method **DispMethod D3D: More leniency in compilation of optional shaders (so it's able to run on more low spec systems) **Improvements to Retro shader compatibility +**Validate user shaders at selection time +**Support user custom AR selection +**Add --load-state commandline +**Fix #525 - Memorywatch hex textbox now remembers values across memdomain switches +**Fix #526 - Hex editor repainting fails and garbage rendering + +**Tastudio (TODO - editorialize this section) +***color stated frames on WasLag too. +***don't truncate LagLog if the branch's one is shorter, but input is the same. +***clean up garbage lua text and drawings. +***put branch states to a separate greenzone file. +***tsm never actually uses currentBranch, so why should it have it? +***last preparation before new tasproject entry. +***save/load TasSession variables in .tasproj. +***update RowCount before scrolling to frame. +***account for mouse speed when advancing/rewinding. + +**Basic Bot +***Monospaced input display +***Get smarter + +**Lua +**Fix gameExtraPadding coordinate translation +**Clarify script pause/stop state in UI and logic + +*PSX +**Fix #530 "AV Resizing shows black screen with PSX" + +*SNES +**Fix crashes in GFX debugger (including fix #529) +**Recommend proper SNES PAR + +*Genesis +**Fix missing scrollbars in VDP viewer ========================================= 1.11.3 @@ -58,7 +94,7 @@ next **Compatibility hack for Jabo vs some Intel GPUs on Windows8+ *SNES -**Handle interlarced modes differently +**Handle interlaced modes differently *mGBA **Fix #507 - Add "Combined WRAM" memory domain diff --git a/LuaInterface/Libs/7z.dll b/LuaInterface/Libs/7z.dll new file mode 100644 index 0000000000..95093da8a9 Binary files /dev/null and b/LuaInterface/Libs/7z.dll differ diff --git a/LuaInterface/Libs/7z.exe b/LuaInterface/Libs/7z.exe new file mode 100644 index 0000000000..789d089224 Binary files /dev/null and b/LuaInterface/Libs/7z.exe differ diff --git a/LuaInterface/Libs/luaperks.7z b/LuaInterface/Libs/luaperks.7z new file mode 100644 index 0000000000..e5911b9c76 Binary files /dev/null and b/LuaInterface/Libs/luaperks.7z differ diff --git a/LuaInterface/Libs/touch.exe b/LuaInterface/Libs/touch.exe new file mode 100644 index 0000000000..0666a1f629 Binary files /dev/null and b/LuaInterface/Libs/touch.exe differ diff --git a/LuaInterface/Libs/un7z_and_touch.bat b/LuaInterface/Libs/un7z_and_touch.bat new file mode 100644 index 0000000000..5e5648fb11 --- /dev/null +++ b/LuaInterface/Libs/un7z_and_touch.bat @@ -0,0 +1,3 @@ +cd %1 +7z x -bd -y -o%2.libs %3 +touch %4 %3 %4 %5 %6 %7 %8 %9 diff --git a/LuaInterface/Lua/src/LuaDLL.cpp b/LuaInterface/Lua/src/LuaDLL.cpp index 7093284948..db8bb12a13 100644 --- a/LuaInterface/Lua/src/LuaDLL.cpp +++ b/LuaInterface/Lua/src/LuaDLL.cpp @@ -27,6 +27,34 @@ extern "C" #include "lua.h" #include "lualib.h" #include "lauxlib.h" + + + +int iuplua_open(lua_State * L); +int iupcontrolslua_open(lua_State * L); +int luaopen_winapi(lua_State * L); + +//luasocket +int luaopen_socket_core(lua_State *L); +int luaopen_mime_core(lua_State *L); + +static void luaperks(lua_State *L) +{ + #ifdef LUAPERKS + iuplua_open(L); + iupcontrolslua_open(L); + luaopen_winapi(L); + + //luasocket - yeah, have to open this in a weird way + lua_pushcfunction(L,luaopen_socket_core); + lua_setglobal(L,"tmp"); + luaL_dostring(L, "package.preload[\"socket.core\"] = _G.tmp"); + lua_pushcfunction(L,luaopen_mime_core); + lua_setglobal(L,"tmp"); + luaL_dostring(L, "package.preload[\"mime.core\"] = _G.tmp"); + #endif +} + } // Not sure of the purpose of this, but I'm keeping it -kevinh @@ -209,6 +237,7 @@ namespace Lua511 static void luaL_openlibs(IntPtr luaState) { ::luaL_openlibs(toState); + ::luaperks(toState); } // Not yet wrapped diff --git a/LuaInterface/Lua/src/lua514.vcxproj b/LuaInterface/Lua/src/lua514.vcxproj index a7b4050031..57e51473af 100644 --- a/LuaInterface/Lua/src/lua514.vcxproj +++ b/LuaInterface/Lua/src/lua514.vcxproj @@ -5,6 +5,10 @@ Debug Win32 + + Release-LUAPERKS + Win32 + Release Win32 @@ -25,6 +29,13 @@ v100 true + + DynamicLibrary + Unicode + true + v100 + true + DynamicLibrary Unicode @@ -37,6 +48,9 @@ + + + @@ -49,18 +63,26 @@ $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\ $(Configuration)\ + $(Configuration)\ false + false + AllRules.ruleset AllRules.ruleset + AllRules.ruleset + + + @@ -75,8 +97,7 @@ 4996;%(DisableSpecificWarnings) - - + ..\..\luaperks.lib;gdi32.lib;opengl32.lib;shell32.lib;user32.lib;comctl32.lib;kernel32.lib;ws2_32.lib;psapi.lib;AdvAPI32.Lib;ole32.lib;mpr.lib;comdlg32.lib;WinSpool.Lib $(OutDir)$(TargetName).dll true true @@ -96,10 +117,51 @@ ProgramDatabase 4996;%(DisableSpecificWarnings) Cdecl + _WINDLL;%(PreprocessorDefinitions) - - + .libs\luaperks.lib;gdi32.lib;opengl32.lib;shell32.lib;user32.lib;comctl32.lib;kernel32.lib;ws2_32.lib;psapi.lib;AdvAPI32.Lib;ole32.lib;mpr.lib;comdlg32.lib;WinSpool.Lib + $(OutDir)lua51.dll + true + $(OutDir)$(TargetName).pdb + true + $(OutDir)$(TargetName).map + true + false + + + $(OutDir)lua51.lib + MachineX86 + + + + + + + + + + + + + + + + + + + + + %(AdditionalIncludeDirectories) + MultiThreadedDLL + Level3 + ProgramDatabase + 4996;%(DisableSpecificWarnings) + Cdecl + LUAPERKS;_WINDLL;%(PreprocessorDefinitions) + + + .libs\luaperks.lib;gdi32.lib;opengl32.lib;shell32.lib;user32.lib;comctl32.lib;kernel32.lib;ws2_32.lib;psapi.lib;AdvAPI32.Lib;ole32.lib;mpr.lib;comdlg32.lib;WinSpool.Lib $(OutDir)lua51.dll true $(OutDir)$(TargetName).pdb @@ -138,6 +200,7 @@ false + false @@ -165,6 +228,17 @@ + + + Document + call $(ProjectDir)..\..\libs\un7z_and_touch.bat $(ProjectDir)\..\..\libs\ $(ProjectDir) luaperks.7z $(ProjectDir).libs\luaperks.lib $(ProjectDir).libs\luaperks.tag + call $(ProjectDir)..\..\libs\un7z_and_touch.bat $(ProjectDir)\..\..\libs\ $(ProjectDir) luaperks.7z $(ProjectDir).libs\luaperks.lib $(ProjectDir).libs\luaperks.tag + .libs\luaperks.tag + .libs\luaperks.tag + ..\..\libs\7z.exe;..\..\libs\un7z_and_touch.bat + ..\..\libs\7z.exe;..\..\libs\un7z_and_touch.bat + + diff --git a/LuaInterface/Lua/src/lua514.vcxproj.filters b/LuaInterface/Lua/src/lua514.vcxproj.filters new file mode 100644 index 0000000000..775749f4b1 --- /dev/null +++ b/LuaInterface/Lua/src/lua514.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {2593862e-85ce-4cff-8e6a-339a263ee706} + + + + + libs + + + \ No newline at end of file diff --git a/LuaInterface/LuaInterface.sln b/LuaInterface/LuaInterface.sln index 9c5fdf8bb3..50776a5a8e 100644 --- a/LuaInterface/LuaInterface.sln +++ b/LuaInterface/LuaInterface.sln @@ -13,6 +13,9 @@ Global Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 + Release-LUAPERKS|Any CPU = Release-LUAPERKS|Any CPU + Release-LUAPERKS|Mixed Platforms = Release-LUAPERKS|Mixed Platforms + Release-LUAPERKS|Win32 = Release-LUAPERKS|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Debug|Any CPU.ActiveCfg = Debug|Win32 @@ -25,6 +28,11 @@ Global {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release|Mixed Platforms.Build.0 = Release|Win32 {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release|Win32.ActiveCfg = Release|Win32 {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release|Win32.Build.0 = Release|Win32 + {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release-LUAPERKS|Any CPU.ActiveCfg = Release-LUAPERKS|Win32 + {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release-LUAPERKS|Mixed Platforms.ActiveCfg = Release-LUAPERKS|Win32 + {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release-LUAPERKS|Mixed Platforms.Build.0 = Release-LUAPERKS|Win32 + {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release-LUAPERKS|Win32.ActiveCfg = Release-LUAPERKS|Win32 + {0A82CC4C-9A27-461C-8DB0-A65AC6393748}.Release-LUAPERKS|Win32.Build.0 = Release-LUAPERKS|Win32 {F55CABBB-4108-4A39-94E1-581FD46DC021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F55CABBB-4108-4A39-94E1-581FD46DC021}.Debug|Any CPU.Build.0 = Debug|Any CPU {F55CABBB-4108-4A39-94E1-581FD46DC021}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -35,6 +43,11 @@ Global {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release|Win32.ActiveCfg = Release|Any CPU + {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release-LUAPERKS|Any CPU.ActiveCfg = Release-LUAPERKS|Any CPU + {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release-LUAPERKS|Any CPU.Build.0 = Release-LUAPERKS|Any CPU + {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release-LUAPERKS|Mixed Platforms.ActiveCfg = Release-LUAPERKS|Any CPU + {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release-LUAPERKS|Mixed Platforms.Build.0 = Release-LUAPERKS|Any CPU + {F55CABBB-4108-4A39-94E1-581FD46DC021}.Release-LUAPERKS|Win32.ActiveCfg = Release-LUAPERKS|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/LuaInterface/LuaInterface/LuaInterface.csproj b/LuaInterface/LuaInterface/LuaInterface.csproj index e17de25f94..433b1dcdd9 100644 --- a/LuaInterface/LuaInterface/LuaInterface.csproj +++ b/LuaInterface/LuaInterface/LuaInterface.csproj @@ -69,6 +69,21 @@ AllRules.ruleset false + + ..\..\references\ + TRACE + true + pdbonly + x86 + ..\..\references\LuaInterface.dll.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + false + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + diff --git a/libsnes/bsnes/base/base.cpp b/libsnes/bsnes/base/base.cpp new file mode 100644 index 0000000000..f2ff271d74 --- /dev/null +++ b/libsnes/bsnes/base/base.cpp @@ -0,0 +1,3 @@ +#include "base.hpp" + +CDLInfo cdlInfo; diff --git a/libsnes/bsnes/base/base.hpp b/libsnes/bsnes/base/base.hpp index 7d8c181a8d..2eab46894a 100644 --- a/libsnes/bsnes/base/base.hpp +++ b/libsnes/bsnes/base/base.hpp @@ -55,6 +55,39 @@ template struct hook { #define privileged private #endif +enum eCDLog_AddrType +{ + eCDLog_AddrType_CARTROM, eCDLog_AddrType_CARTRAM, eCDLog_AddrType_WRAM, eCDLog_AddrType_APURAM, + eCDLog_AddrType_NUM +}; + +enum eCDLog_Flags +{ + eCDLog_Flags_None = 0x00, + eCDLog_Flags_ExecFirst = 0x01, + eCDLog_Flags_ExecOperand = 0x02, + eCDLog_Flags_CPUData = 0x04, + eCDLog_Flags_DMAData = 0x08, //not supported yet + eCDLog_Flags_BRR = 0x80 +}; + +struct CDLInfo +{ + eCDLog_Flags currFlags; + uint8_t* blocks[eCDLog_AddrType_NUM]; //[0]==nullptr -> disabled + uint32_t blockSizes[eCDLog_AddrType_NUM]; + void set(eCDLog_AddrType addrType, uint32_t addr) + { + if(!blocks[0]) return; + if(addr >= blockSizes[addrType]) + return; + blocks[addrType][addr] |= currFlags; + } +}; + +extern CDLInfo cdlInfo; +inline bool wantCDL() { return cdlInfo.blocks[0] != nullptr; } + typedef int1_t int1; typedef int2_t int2; typedef int3_t int3; diff --git a/libsnes/bsnes/snes/alt/cpu/cpu.cpp b/libsnes/bsnes/snes/alt/cpu/cpu.cpp index e86ca58e95..9b67166be0 100644 --- a/libsnes/bsnes/snes/alt/cpu/cpu.cpp +++ b/libsnes/bsnes/snes/alt/cpu/cpu.cpp @@ -77,7 +77,7 @@ void CPU::enter() { } alwaysinline void CPU::op_step() { - (this->*opcode_table[op_readpc()])(); + (this->*opcode_table[op_readpcfirst()])(); } void CPU::enable() { @@ -96,8 +96,8 @@ void CPU::enable() { bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write); bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write); - read = [](unsigned addr) { return cpu.wram[addr]; }; - write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; + read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; }; + write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); diff --git a/libsnes/bsnes/snes/alt/cpu/cpu.hpp b/libsnes/bsnes/snes/alt/cpu/cpu.hpp index f3105ad622..e03d2cc358 100644 --- a/libsnes/bsnes/snes/alt/cpu/cpu.hpp +++ b/libsnes/bsnes/snes/alt/cpu/cpu.hpp @@ -19,7 +19,7 @@ public: void mmio_write(unsigned addr, uint8 data); void op_io(); - uint8 op_read(unsigned addr); + uint8 op_read(unsigned addr, eCDLog_Flags = eCDLog_Flags_CPUData); void op_write(unsigned addr, uint8 data); void enter(); diff --git a/libsnes/bsnes/snes/alt/cpu/memory.cpp b/libsnes/bsnes/snes/alt/cpu/memory.cpp index fed9870af0..2e1a4a11a1 100644 --- a/libsnes/bsnes/snes/alt/cpu/memory.cpp +++ b/libsnes/bsnes/snes/alt/cpu/memory.cpp @@ -24,7 +24,8 @@ void CPU::op_io() { add_clocks(6); } -uint8 CPU::op_read(unsigned addr) { +uint8 CPU::op_read(unsigned addr, eCDLog_Flags flags) { + cdlInfo.currFlags = flags; regs.mdr = bus.read(addr); add_clocks(speed(addr)); return regs.mdr; diff --git a/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp b/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp index b012140782..12752a8431 100644 --- a/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp +++ b/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp @@ -526,6 +526,11 @@ VOICE_CLOCK( V4 ) m.t_looped = v->vbit; } v->brr_offset = 1; + + //assume we're going to access the whole block + cdlInfo.currFlags = eCDLog_Flags_BRR; + for(int i=0;i<9;i++) + cdlInfo.set(eCDLog_AddrType_APURAM, (v->brr_addr+i) & 0xFFFF); } } diff --git a/libsnes/bsnes/snes/alt/smp/core.cpp b/libsnes/bsnes/snes/alt/smp/core.cpp index 21bf5bf225..6a79e71d8e 100644 --- a/libsnes/bsnes/snes/alt/smp/core.cpp +++ b/libsnes/bsnes/snes/alt/smp/core.cpp @@ -14,12 +14,14 @@ void SMP::op_io() { #endif } -uint8 SMP::op_read(uint16 addr) { +uint8 SMP::op_read(uint16 addr, eCDLog_Flags flags) { #if defined(CYCLE_ACCURATE) tick(); #endif if((addr & 0xfff0) == 0x00f0) return mmio_read(addr); if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f]; + cdlInfo.currFlags = flags; + cdlInfo.set(eCDLog_AddrType_APURAM, addr); return apuram[addr]; } @@ -32,18 +34,19 @@ void SMP::op_write(uint16 addr, uint8 data) { } void SMP::op_step() { - #define op_readpc() op_read(regs.pc++) - #define op_readdp(addr) op_read((regs.p.p << 8) + addr) + #define op_readpcfirst() op_read(regs.pc++,eCDLog_Flags_ExecFirst) + #define op_readpc() op_read(regs.pc++,eCDLog_Flags_ExecOperand) + #define op_readdp(addr) op_read((regs.p.p << 8) + addr,eCDLog_Flags_CPUData) #define op_writedp(addr, data) op_write((regs.p.p << 8) + addr, data) - #define op_readaddr(addr) op_read(addr) + #define op_readaddr(addr) op_read(addr,eCDLog_Flags_CPUData) #define op_writeaddr(addr, data) op_write(addr, data) - #define op_readstack() op_read(0x0100 | ++regs.sp) + #define op_readstack() op_read(0x0100 | ++regs.sp,eCDLog_Flags_CPUData) #define op_writestack(data) op_write(0x0100 | regs.sp--, data) #if defined(CYCLE_ACCURATE) if(opcode_cycle == 0) { - opcode_number = op_readpc(); + opcode_number = op_readpcfirst(); opcode_cycle++; } else switch(opcode_number) { #include "core/opcycle_misc.cpp" @@ -55,7 +58,7 @@ void SMP::op_step() { #else - unsigned opcode = op_readpc(); + unsigned opcode = op_readpcfirst(); switch(opcode) { #include "core/op_misc.cpp" #include "core/op_mov.cpp" diff --git a/libsnes/bsnes/snes/alt/smp/smp.hpp b/libsnes/bsnes/snes/alt/smp/smp.hpp index 39b4562e61..f50184446c 100644 --- a/libsnes/bsnes/snes/alt/smp/smp.hpp +++ b/libsnes/bsnes/snes/alt/smp/smp.hpp @@ -90,7 +90,7 @@ public: void tick(); alwaysinline void op_io(); - alwaysinline uint8 op_read(uint16 addr); + alwaysinline uint8 op_read(uint16 addr, eCDLog_Flags flags); alwaysinline void op_write(uint16 addr, uint8 data); alwaysinline void op_step(); static const unsigned cycle_count_table[256]; diff --git a/libsnes/bsnes/snes/cartridge/cartridge.hpp b/libsnes/bsnes/snes/cartridge/cartridge.hpp index a108d8ba70..958aabd2c1 100644 --- a/libsnes/bsnes/snes/cartridge/cartridge.hpp +++ b/libsnes/bsnes/snes/cartridge/cartridge.hpp @@ -110,6 +110,11 @@ private: void parse_markup_obc1(XML::Node&); void parse_markup_msu1(XML::Node&); void parse_markup_link(XML::Node&); + + inline uint8 rom_read(unsigned addr); + inline void rom_write(unsigned addr, uint8 n); + inline uint8 ram_read(unsigned addr); + inline void ram_write(unsigned addr, uint8 n); }; extern Cartridge cartridge; diff --git a/libsnes/bsnes/snes/cartridge/markup.cpp b/libsnes/bsnes/snes/cartridge/markup.cpp index dd46cb2c13..a4ac63bb8c 100644 --- a/libsnes/bsnes/snes/cartridge/markup.cpp +++ b/libsnes/bsnes/snes/cartridge/markup.cpp @@ -62,13 +62,31 @@ void Cartridge::parse_markup_map(Mapping &m, XML::Node &map) { } } -// +uint8 Cartridge::rom_read(unsigned addr) +{ + cdlInfo.set(eCDLog_AddrType_CARTROM, addr); + return rom.read(addr); +} +void Cartridge::rom_write(unsigned addr, uint8 n) +{ + rom.write(addr,n); +} + +uint8 Cartridge::ram_read(unsigned addr) +{ + cdlInfo.set(eCDLog_AddrType_CARTRAM, addr); + return ram.read(addr); +} +void Cartridge::ram_write(unsigned addr, uint8 n) +{ + ram.write(addr, n); +} void Cartridge::parse_markup_rom(XML::Node &root) { if(root.exists() == false) return; for(auto &node : root) { if(node.name != "map") continue; - Mapping m(rom); + Mapping m({&Cartridge::rom_read, this}, {&Cartridge::rom_write, this}); parse_markup_map(m, node); if(m.size == 0) m.size = rom.size(); mapping.append(m); @@ -79,7 +97,7 @@ void Cartridge::parse_markup_ram(XML::Node &root) { if(root.exists() == false) return; ram_size = numeral(root["size"].data); for(auto &node : root) { - Mapping m(ram); + Mapping m({ &Cartridge::ram_read, this }, { &Cartridge::ram_write, this }); parse_markup_map(m, node); if(m.size == 0) m.size = ram_size; mapping.append(m); diff --git a/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp b/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp index d13ac92991..e7da7add13 100644 --- a/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp +++ b/libsnes/bsnes/snes/chip/sa1/memory/memory.cpp @@ -107,7 +107,8 @@ void SA1::op_io() { tick(); } -uint8 SA1::op_read(unsigned addr) { +uint8 SA1::op_read(unsigned addr, eCDLog_Flags flags) { + (void)flags; //this was needed for inheritance purposes, as SA-1 is derived from the main CPU class tick(); if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick(); return bus_read(addr); diff --git a/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp b/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp index ffb9e9f6ea..6e627057c0 100644 --- a/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp +++ b/libsnes/bsnes/snes/chip/sa1/memory/memory.hpp @@ -3,7 +3,7 @@ void bus_write(unsigned addr, uint8 data); uint8 vbr_read(unsigned addr); alwaysinline void op_io(); -alwaysinline uint8 op_read(unsigned addr); +alwaysinline uint8 op_read(unsigned addr, eCDLog_Flags = eCDLog_Flags_CPUData); alwaysinline void op_write(unsigned addr, uint8 data); uint8 mmc_read(unsigned addr); diff --git a/libsnes/bsnes/snes/cpu/core/core.hpp b/libsnes/bsnes/snes/cpu/core/core.hpp index 964bd12889..65c5fa9bc3 100644 --- a/libsnes/bsnes/snes/cpu/core/core.hpp +++ b/libsnes/bsnes/snes/cpu/core/core.hpp @@ -8,7 +8,7 @@ struct CPUcore { uint8_t sp, dp; virtual void op_io() = 0; - virtual uint8_t op_read(uint32_t addr) = 0; + virtual uint8_t op_read(uint32_t addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0; virtual void op_write(uint32_t addr, uint8_t data) = 0; virtual void last_cycle() = 0; virtual bool interrupt_pending() = 0; diff --git a/libsnes/bsnes/snes/cpu/core/memory.hpp b/libsnes/bsnes/snes/cpu/core/memory.hpp index 4992657869..c6347dc296 100644 --- a/libsnes/bsnes/snes/cpu/core/memory.hpp +++ b/libsnes/bsnes/snes/cpu/core/memory.hpp @@ -1,33 +1,44 @@ +alwaysinline uint8_t op_readpcfirst() { + return op_read((regs.pc.b << 16) + regs.pc.w++, eCDLog_Flags_ExecFirst); +} + alwaysinline uint8_t op_readpc() { - return op_read((regs.pc.b << 16) + regs.pc.w++); + return op_read((regs.pc.b << 16) + regs.pc.w++, eCDLog_Flags_ExecOperand); } alwaysinline uint8_t op_readstack() { + cdlInfo.currFlags = eCDLog_Flags_CPUData; regs.e ? regs.s.l++ : regs.s.w++; return op_read(regs.s.w); } alwaysinline uint8_t op_readstackn() { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read(++regs.s.w); } alwaysinline uint8_t op_readaddr(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read(addr & 0xffff); } alwaysinline uint8_t op_readlong(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read(addr & 0xffffff); } alwaysinline uint8_t op_readdbr(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read(((regs.db << 16) + addr) & 0xffffff); } alwaysinline uint8_t op_readpbr(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read((regs.pc.b << 16) + (addr & 0xffff)); } alwaysinline uint8_t op_readdp(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; if(regs.e && regs.d.l == 0x00) { return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff)); } else { @@ -36,6 +47,7 @@ alwaysinline uint8_t op_readdp(uint32_t addr) { } alwaysinline uint8_t op_readsp(uint32_t addr) { + cdlInfo.currFlags = eCDLog_Flags_CPUData; return op_read((regs.s + (addr & 0xffff)) & 0xffff); } diff --git a/libsnes/bsnes/snes/cpu/cpu.cpp b/libsnes/bsnes/snes/cpu/cpu.cpp index 8457b79740..8ecd3c9e7d 100644 --- a/libsnes/bsnes/snes/cpu/cpu.cpp +++ b/libsnes/bsnes/snes/cpu/cpu.cpp @@ -99,7 +99,7 @@ void CPU::op_step() { interface()->cpuTrace(tmp); } - (this->*opcode_table[op_readpc()])(); + (this->*opcode_table[op_readpcfirst()])(); } void CPU::enable() { @@ -118,7 +118,7 @@ void CPU::enable() { bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write); bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write); - read = [](unsigned addr) { return cpu.wram[addr]; }; + read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; }; write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; }; bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000); diff --git a/libsnes/bsnes/snes/cpu/cpu.hpp b/libsnes/bsnes/snes/cpu/cpu.hpp index 11c3620438..bb70ac78b4 100644 --- a/libsnes/bsnes/snes/cpu/cpu.hpp +++ b/libsnes/bsnes/snes/cpu/cpu.hpp @@ -1,5 +1,8 @@ struct CPU : public Processor, public CPUcore, public PPUcounter { uint8 *wram; //[128 * 1024]; + + function read_wram; + function write_wram; enum : bool { Threaded = true }; array coprocessors; diff --git a/libsnes/bsnes/snes/cpu/memory/memory.cpp b/libsnes/bsnes/snes/cpu/memory/memory.cpp index 7e5c0c691d..bc4ab661fe 100644 --- a/libsnes/bsnes/snes/cpu/memory/memory.cpp +++ b/libsnes/bsnes/snes/cpu/memory/memory.cpp @@ -10,12 +10,13 @@ void CPU::op_io() { alu_edge(); } -uint8 CPU::op_read(uint32 addr) { +uint8 CPU::op_read(uint32 addr, eCDLog_Flags flags) { debugger.op_read(addr); status.clock_count = speed(addr); dma_edge(); add_clocks(status.clock_count - 4); + cdlInfo.currFlags = flags; regs.mdr = bus.read(addr); add_clocks(4); alu_edge(); diff --git a/libsnes/bsnes/snes/cpu/memory/memory.hpp b/libsnes/bsnes/snes/cpu/memory/memory.hpp index c732969060..638e892231 100644 --- a/libsnes/bsnes/snes/cpu/memory/memory.hpp +++ b/libsnes/bsnes/snes/cpu/memory/memory.hpp @@ -1,4 +1,4 @@ void op_io(); -uint8 op_read(uint32 addr); +uint8 op_read(uint32 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData); void op_write(uint32 addr, uint8 data); alwaysinline unsigned speed(unsigned addr) const; diff --git a/libsnes/bsnes/snes/interface/interface.hpp b/libsnes/bsnes/snes/interface/interface.hpp index 85e413d1b6..9760893aae 100644 --- a/libsnes/bsnes/snes/interface/interface.hpp +++ b/libsnes/bsnes/snes/interface/interface.hpp @@ -1,3 +1,4 @@ + struct Interface { Interface(); virtual void videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan); diff --git a/libsnes/bsnes/snes/smp/core/core.hpp b/libsnes/bsnes/snes/smp/core/core.hpp index 2d47bfb132..0b3da3f330 100644 --- a/libsnes/bsnes/snes/smp/core/core.hpp +++ b/libsnes/bsnes/snes/smp/core/core.hpp @@ -1,6 +1,6 @@ struct SMPcore { virtual void op_io() = 0; - virtual uint8 op_read(uint16 addr) = 0; + virtual uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData) = 0; virtual void op_write(uint16 addr, uint8 data) = 0; void op_step(); diff --git a/libsnes/bsnes/snes/smp/core/memory.hpp b/libsnes/bsnes/snes/smp/core/memory.hpp index 4e40af4d8a..ac33f22232 100644 --- a/libsnes/bsnes/snes/smp/core/memory.hpp +++ b/libsnes/bsnes/snes/smp/core/memory.hpp @@ -1,5 +1,9 @@ +alwaysinline uint8 op_readpcfirst() { + return op_read(regs.pc++, eCDLog_Flags_ExecFirst); +} + alwaysinline uint8 op_readpc() { - return op_read(regs.pc++); + return op_read(regs.pc++, eCDLog_Flags_ExecOperand); } alwaysinline uint8 op_readsp() { @@ -19,7 +23,7 @@ alwaysinline void op_writedp(uint8 addr, uint8 data) { } alwaysinline void op_next() { - opcode = op_readpc(); + opcode = op_readpcfirst(); uindex = -1; } diff --git a/libsnes/bsnes/snes/smp/memory/memory.cpp b/libsnes/bsnes/snes/smp/memory/memory.cpp index 49c8895795..7a53df5df1 100644 --- a/libsnes/bsnes/snes/smp/memory/memory.cpp +++ b/libsnes/bsnes/snes/smp/memory/memory.cpp @@ -70,6 +70,7 @@ uint8 SMP::op_busread(uint16 addr) { return result; } + cdlInfo.set(eCDLog_AddrType_APURAM, addr); return ram_read(addr); } @@ -180,10 +181,11 @@ void SMP::op_io() { cycle_edge(); } -uint8 SMP::op_read(uint16 addr) { +uint8 SMP::op_read(uint16 addr, eCDLog_Flags flags) { debugger.op_read(addr); add_clocks(12); + cdlInfo.currFlags = flags; uint8 r = op_busread(addr); add_clocks(12); cycle_edge(); diff --git a/libsnes/bsnes/snes/smp/memory/memory.hpp b/libsnes/bsnes/snes/smp/memory/memory.hpp index 72691f0e4c..717947abef 100644 --- a/libsnes/bsnes/snes/smp/memory/memory.hpp +++ b/libsnes/bsnes/snes/smp/memory/memory.hpp @@ -5,5 +5,5 @@ uint8 op_busread(uint16 addr); void op_buswrite(uint16 addr, uint8 data); void op_io(); -uint8 op_read(uint16 addr); +uint8 op_read(uint16 addr, eCDLog_Flags flags = eCDLog_Flags_CPUData); void op_write(uint16 addr, uint8 data); diff --git a/libsnes/bsnes/target-libsnes/libsnes.cpp b/libsnes/bsnes/target-libsnes/libsnes.cpp index e83189f83e..72c3ad13b1 100644 --- a/libsnes/bsnes/target-libsnes/libsnes.cpp +++ b/libsnes/bsnes/target-libsnes/libsnes.cpp @@ -131,6 +131,7 @@ struct Interface : public SNES::Interface { { buffer = new uint32_t[512 * 480]; palette = new uint32_t[16 * 32768]; + memset(&cdlInfo,0,sizeof(cdlInfo)); } ~Interface() { @@ -140,7 +141,7 @@ struct Interface : public SNES::Interface { }; void pwrap_init(); -static Interface *iface = nullptr; +Interface *iface = nullptr; namespace SNES { SNES::Interface *interface() { diff --git a/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp b/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp index 41554e3625..9ff8c34e27 100644 --- a/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp +++ b/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp @@ -33,6 +33,8 @@ #include #include +extern SNES::Interface *iface; + typedef uint8 u8; typedef int32 s32; typedef uint32 u32; @@ -73,7 +75,8 @@ enum eMessage : int32 eMessage_QUERY_set_backdropColor, eMessage_QUERY_peek_logical_register, eMessage_QUERY_peek_cpu_regs, - + eMessage_QUERY_set_cdl, + eMessage_CMD_FIRST, eMessage_CMD_init, eMessage_CMD_power, @@ -883,6 +886,15 @@ bool Handle_QUERY(eMessage msg) case eMessage_QUERY_state_hook_irq: SNES::cpu.debugger.op_irq = ReadPipe() ? debug_op_irq : hook(); break; + + case eMessage_QUERY_set_cdl: + for (int i = 0; i(); + cdlInfo.blockSizes[i] = ReadPipe(); + } + break; + } return true; } diff --git a/libsnes/vs2015/libsnes.vcxproj b/libsnes/vs2015/libsnes.vcxproj index fc4d162fd9..668837a1fe 100644 --- a/libsnes/vs2015/libsnes.vcxproj +++ b/libsnes/vs2015/libsnes.vcxproj @@ -167,13 +167,147 @@ + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + @@ -188,7 +322,49 @@ true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true true @@ -197,11 +373,125 @@ true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + @@ -220,19 +510,133 @@ + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true false true false + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true true true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + @@ -241,18 +645,110 @@ true true + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + true false true false + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + diff --git a/libsnes/vs2015/libsnes.vcxproj.filters b/libsnes/vs2015/libsnes.vcxproj.filters index 6e53abe88f..b60aa69a48 100644 --- a/libsnes/vs2015/libsnes.vcxproj.filters +++ b/libsnes/vs2015/libsnes.vcxproj.filters @@ -151,6 +151,21 @@ {f06ef20e-c749-4f16-81d3-f88d96b659bc} + + {abb9e273-8335-47ae-b389-76395d57844c} + + + {b17bd430-7d56-4e93-b78c-d41b2c6f3d85} + + + {1e74e41b-9992-4e18-b2a9-91827d350402} + + + {f1711f3e-853c-4ec3-bd3d-2c21d85c65bd} + + + {a2db2d0e-68ec-4fa0-91fc-2bcc8ac33d32} + @@ -180,6 +195,75 @@ target-libsnes + + snes\interface + + + snes\cpu\core\disassembler + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu + + + snes\cartridge + + + snes\cpu\memory + + + snes\alt\cpu + + + snes\alt\smp + + + snes\smp\core + + + snes\smp\core + + + snes\smp\core + + + snes\smp\memory + + + snes\smp\timing + + + snes\smp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\dsp + @@ -320,5 +404,190 @@ snes\smp\core + + snes\cpu\core\disassembler + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu\core + + + snes\cpu + + + snes\cartridge + + + snes\cartridge + + + base + + + snes\cpu\memory + + + snes\alt\cpu + + + snes\alt\cpu + + + snes\alt\cpu + + + snes\alt\cpu + + + snes\alt\cpu + + + snes\alt\smp + + + snes\alt\smp + + + snes\alt\smp + + + snes\alt\smp + + + snes\alt\smp + + + snes\alt\smp + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\smp\core + + + snes\smp\core + + + snes\smp\core + + + snes\smp\core + + + snes\smp\core + + + snes\smp\memory + + + snes\smp\timing + + + snes\smp + + + snes\smp + + + snes\alt\dsp + + + snes\alt\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + snes\dsp + + + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + + + snes\alt\smp\core + \ No newline at end of file diff --git a/output/defctrl.json b/output/defctrl.json index 0a7b965818..f52ba215ab 100644 --- a/output/defctrl.json +++ b/output/defctrl.json @@ -1,5 +1,32 @@ { "AllTrollers": { + "LibRetro Controls": { + "P1 RetroPad Up": "UpArrow,J1 POV1U, X1 DpadUp, X1 LStickUp", + "P1 RetroPad Down": "DownArrow,J1 POV1D, X1 DpadDown, X1 LStickDown", + "P1 RetroPad Left": "LeftArrow,J1 POV1L, X1 DpadLeft, X1 LStickLeft", + "P1 RetroPad Right": "RightArrow,J1 POV1R, X1 DpadRight, X1 LStickRight", + "P1 RetroPad Select": "Space, J1 B9, X1 Back", + "P1 RetroPad Start": "Return, J1 B10, X1 Start", + "P1 RetroPad Y": "A, J1 B1, X1 X", + "P1 RetroPad B": "Z, J1 B2, X1 A", + "P1 RetroPad X": "S, J1 B4, X1 Y", + "P1 RetroPad A": "X, J1 B3, X1 B", + "P1 RetroPad L": "W, J1 B5, X1 LeftShoulder", + "P1 RetroPad R": "E, J1 B6, X1 RightShoulder", + "P2 RetroPad Up": "", + "P2 RetroPad Down": "", + "P2 RetroPad Left": "", + "P2 RetroPad Right": "", + "P2 RetroPad Select": "", + "P2 RetroPad Start": "", + "P2 RetroPad Y": "", + "P2 RetroPad B": "", + "P2 RetroPad X": "", + "P2 RetroPad A": "", + "P2 RetroPad L": "", + "P2 RetroPad R": "", + "Pointer Pressed": "WMouse L", + }, "NES Controller": { "P1 Up": "UpArrow, J1 POV1U, X1 DpadUp, X1 LStickUp", "P1 Down": "DownArrow, J1 POV1D, X1 DpadDown, X1 LStickDown", @@ -1116,6 +1143,28 @@ "Deadzone": 0.1 } }, - "Apple IIe Keyboard": {} + "Apple IIe Keyboard": {}, + "LibRetro Controls": { + "Pointer X": { + "Value": "WMouse X", + "Mult": 1.0, + "Deadzone": 0.1 + }, + "Pointer Y": { + "Value": "WMouse Y", + "Mult": 1.0, + "Deadzone": 0.1 + }, + "P1 Pointer X": { + "Value": "", + "Mult": 1.0, + "Deadzone": 0.1 + }, + "P1 Pointer Y": { + "Value": "", + "Mult": 1.0, + "Deadzone": 0.1 + } + } } } \ No newline at end of file diff --git a/output/dll/libsneshawk-32-compatibility.dll b/output/dll/libsneshawk-32-compatibility.dll index 7e91cbd937..2f41379eb2 100644 Binary files a/output/dll/libsneshawk-32-compatibility.dll and b/output/dll/libsneshawk-32-compatibility.dll differ diff --git a/output/dll/libsneshawk-32-performance.dll b/output/dll/libsneshawk-32-performance.dll index 29758965e9..4effa733ba 100644 Binary files a/output/dll/libsneshawk-32-performance.dll and b/output/dll/libsneshawk-32-performance.dll differ