diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index f9ee25dd1e..5f425f7a1c 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -836,7 +836,7 @@ namespace BizHawk.Client.EmuHawk
public void RebootCore()
{
var ioa = OpenAdvancedSerializer.ParseWithLegacy(CurrentlyOpenRom);
- if (ioa is IOpenAdvancedLibretro)
+ if (ioa is OpenAdvanced_LibretroNoGame)
LoadRom("", CurrentlyOpenRomArgs);
else
LoadRom(ioa.SimplePath, CurrentlyOpenRomArgs);
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.Cores/LibRetro.cs b/BizHawk.Emulation.Cores/LibRetro.cs
index 124dc3cc5e..392a5d482a 100644
--- a/BizHawk.Emulation.Cores/LibRetro.cs
+++ b/BizHawk.Emulation.Cores/LibRetro.cs
@@ -263,6 +263,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,
@@ -371,6 +394,46 @@ 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)]
[return:MarshalAs(UnmanagedType.U1)]
diff --git a/BizHawk.Emulation.Cores/LibRetroEmulator.cs b/BizHawk.Emulation.Cores/LibRetroEmulator.cs
index 5e4e181787..c93e37827b 100644
--- a/BizHawk.Emulation.Cores/LibRetroEmulator.cs
+++ b/BizHawk.Emulation.Cores/LibRetroEmulator.cs
@@ -114,6 +114,8 @@ 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;
@@ -188,15 +190,18 @@ namespace BizHawk.Emulation.Cores
case LibRetro.RETRO_ENVIRONMENT.GET_LOG_INTERFACE:
return false;
case LibRetro.RETRO_ENVIRONMENT.GET_PERF_INTERFACE:
- return false;
+ //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;
+ //*((IntPtr*)data.ToPointer()) = IntPtr.Zero;
return false;
case LibRetro.RETRO_ENVIRONMENT.SET_CONTROLLER_INFO:
return true;
@@ -265,6 +270,8 @@ namespace BizHawk.Emulation.Cores
LibRetro.retro_input_poll_t retro_input_poll_cb;
LibRetro.retro_input_state_t retro_input_state_cb;
+ LibRetro.retro_perf_callback retro_perf_callback = new LibRetro.retro_perf_callback();
+
#endregion
private LibRetro retro;
@@ -292,7 +299,7 @@ namespace BizHawk.Emulation.Cores
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);
@@ -300,6 +307,21 @@ namespace BizHawk.Emulation.Cores
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);
+ //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
{