tidy libretro core info and use recommended extensions

This commit is contained in:
zeromus 2015-11-07 19:59:10 -06:00
parent 70b7098cb8
commit b745d5776a
6 changed files with 151 additions and 29 deletions

View File

@ -263,7 +263,7 @@ namespace BizHawk.Client.Common
var retro = new LibRetroEmulator(nextComm, nextComm.LaunchLibretroCore);
nextEmulator = retro;
if (retro.EnvironmentInfo.SupportNoGame && string.IsNullOrEmpty(path))
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();
@ -283,7 +283,7 @@ namespace BizHawk.Client.Common
//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.system_info.block_extract)
if (retro.Description.NeedsArchives)
{
if (file.IsArchiveMember)
throw new InvalidOperationException("Should not have bound file member for libretro block_extract core");
@ -292,10 +292,10 @@ namespace BizHawk.Client.Common
else
{
//otherwise load the data or pass the filename, as requested. but..
if (retro.system_info.need_fullpath && file.IsArchiveMember)
if (retro.Description.NeedsRomAsPath && file.IsArchiveMember)
throw new InvalidOperationException("Cannot pass archive member to libretro needs_fullpath core");
if (retro.system_info.need_fullpath)
if (retro.Description.NeedsRomAsPath)
ret = retro.LoadPath(file.FullPathWithoutMember);
else
{
@ -314,7 +314,7 @@ namespace BizHawk.Client.Common
}
//game name == name of core + extensionless_game_filename
gameName = Path.Combine(codePathPart, Path.GetFileNameWithoutExtension(file.CanonicalName));
gameName = Path.Combine(codePathPart, Path.GetFileNameWithoutExtension(file.Name));
}
game = new GameInfo { Name = gameName, System = "Libretro" };

View File

@ -316,8 +316,13 @@ namespace BizHawk.Client.EmuHawk
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");
@ -328,7 +333,7 @@ namespace BizHawk.Client.EmuHawk
var ofd = new OpenFileDialog
{
InitialDirectory = PathManager.GetRomsPath(Global.Emulator.SystemId),
Filter = RomFilter,
Filter = filter,
RestoreDirectory = false,
FilterIndex = _lastOpenRomFilter,
Title = "Open Advanced"

View File

@ -1972,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)
@ -2002,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%",

View File

@ -26,6 +26,7 @@ namespace BizHawk.Client.EmuHawk
}
public Command Result;
public string SuggestedExtensionFilter;
public OpenAdvancedChooser(MainForm mainForm)
{
@ -33,7 +34,7 @@ namespace BizHawk.Client.EmuHawk
InitializeComponent();
RefreshLibretroCore();
RefreshLibretroCore(true);
}
private void btnOK_Click(object sender, EventArgs e)
@ -51,10 +52,11 @@ namespace BizHawk.Client.EmuHawk
private void btnSetLibretroCore_Click(object sender, EventArgs e)
{
mainForm.RunLibretroCoreChooser();
RefreshLibretroCore();
RefreshLibretroCore(false);
}
void RefreshLibretroCore()
LibRetroEmulator.RetroDescription CurrentDescription;
void RefreshLibretroCore(bool bootstrap)
{
txtLibretroCore.Text = "";
btnLibretroLaunchNoGame.Enabled = false;
@ -65,22 +67,60 @@ namespace BizHawk.Client.EmuHawk
return;
txtLibretroCore.Text = core;
btnLibretroLaunchGame.Enabled = true;
CurrentDescription = null;
//scan the current libretro core to see if it can be launched with NoGame
//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))
{
if (retro.EnvironmentInfo.SupportNoGame)
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 { }
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<string> args = new List<string>();
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();

View File

@ -506,6 +506,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;

View File

@ -73,16 +73,13 @@ namespace BizHawk.Emulation.Cores
public bool PutSyncSettings(SyncSettings o)
{
//currently LEC and pad settings changes both require reboot
bool reboot = true;
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;
}
@ -168,14 +165,14 @@ namespace BizHawk.Emulation.Cores
break;
string key = Marshal.PtrToStringAnsi(pKey);
string value = Marshal.PtrToStringAnsi(pValue);
Console.WriteLine("Defined variable: {0} = {1}", key, value);
environmentInfo.Variables.Add(Tuple.Create(key, value));
}
}
return false;
case LibRetro.RETRO_ENVIRONMENT.GET_VARIABLE_UPDATE:
return false;
case LibRetro.RETRO_ENVIRONMENT.SET_SUPPORT_NO_GAME:
EnvironmentInfo.SupportNoGame = true;
environmentInfo.SupportNoGame = true;
return false;
case LibRetro.RETRO_ENVIRONMENT.GET_LIBRETRO_PATH:
return false;
@ -274,18 +271,75 @@ namespace BizHawk.Emulation.Cores
#endregion
class RetroEnvironmentInfo
{
public bool SupportNoGame;
public List<Tuple<string, string>> Variables = new List<Tuple<string, string>>();
}
//disposable resources
private LibRetro retro;
private UnmanagedResourceHeap unmanagedResources = new UnmanagedResourceHeap();
//todo - make private
public LibRetro.retro_system_info system_info = new LibRetro.retro_system_info();
/// <summary>
/// Cached information sent to the frontend by environment calls
/// </summary>
RetroEnvironmentInfo environmentInfo = new RetroEnvironmentInfo();
public struct RetroEnvironmentInfo
public class RetroDescription
{
public bool SupportNoGame;
}
public RetroEnvironmentInfo EnvironmentInfo = new RetroEnvironmentInfo();
/// <summary>
/// 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.
/// </summary>
public string LibraryName;
/// <summary>
/// String containing a friendly version number for the core library
/// </summary>
public string LibraryVersion;
/// <summary>
/// List of extensions as "sfc|smc|fig" which this core accepts.
/// </summary>
public string ValidExtensions;
/// <summary>
/// Whether the core needs roms to be specified as paths (can't take rom data buffersS)
/// </summary>
public bool NeedsRomAsPath;
/// <summary>
/// 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.
/// </summary>
public bool NeedsArchives;
/// <summary>
/// Whether the core can be run without a game provided (e.g. stand-alone games, like 2048)
/// </summary>
public bool SupportsNoGame;
/// <summary>
/// Variables defined by the core
/// </summary>
public Dictionary<string, VariableDescription> Variables = new Dictionary<string, VariableDescription>();
}
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;
@ -321,21 +375,41 @@ namespace BizHawk.Emulation.Cores
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;
//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;
foreach (var vv in environmentInfo.Variables)
{
var vd = new VariableDescription() { Name = vv.Item1 };
var parts = vv.Item2.Split(';');
vd.Description = parts[0];
vd.Options = parts[1].TrimStart(' ').Split('|');
Description.Variables[vd.Name] = vd;
}
}
catch
{
@ -343,6 +417,8 @@ namespace BizHawk.Emulation.Cores
retro = null;
throw;
}
}
public IEmulatorServiceProvider ServiceProvider { get; private set; }