fix rebooting of libretro cores, add CPU detection win32 hacks, add retro perf interface
This commit is contained in:
parent
cbdf6a2acc
commit
70b7098cb8
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// On a Pentium, a floating-point precision error can occur in rare circumstances
|
||||
/// </summary>
|
||||
FloatingPointPrecisionErrata = 0,
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
FloatingPointEmulated = 1,
|
||||
/// <summary>
|
||||
/// The atomic compare and exchange operation (cmpxchg) is available
|
||||
/// </summary>
|
||||
CompareExchangeDouble = 2,
|
||||
/// <summary>
|
||||
/// The MMX instruction set is available
|
||||
/// </summary>
|
||||
InstructionsMMXAvailable = 3,
|
||||
/// <summary>
|
||||
/// The SSE instruction set is available
|
||||
/// </summary>
|
||||
InstructionsXMMIAvailable = 6,
|
||||
/// <summary>
|
||||
/// The 3D-Now instruction set is available.
|
||||
/// </summary>
|
||||
Instruction3DNowAvailable = 7,
|
||||
/// <summary>
|
||||
/// The RDTSC instruction is available
|
||||
/// </summary>
|
||||
InstructionRDTSCAvailable = 8,
|
||||
/// <summary>
|
||||
/// The processor is PAE-enabled
|
||||
/// </summary>
|
||||
PAEEnabled = 9,
|
||||
/// <summary>
|
||||
/// The SSE2 instruction set is available
|
||||
/// </summary>
|
||||
InstructionsXMMI64Available = 10,
|
||||
/// <summary>
|
||||
/// Data execution prevention is enabled. (This feature is not supported until Windows XP SP2 and Windows Server 2003 SP1)
|
||||
/// </summary>
|
||||
NXEnabled = 12,
|
||||
/// <summary>
|
||||
/// The SSE3 instruction set is available. (This feature is not supported until Windows Vista)
|
||||
/// </summary>
|
||||
InstructionsSSE3Available = 13,
|
||||
/// <summary>
|
||||
/// The atomic compare and exchange 128-bit operation (cmpxchg16b) is available. (This feature is not supported until Windows Vista)
|
||||
/// </summary>
|
||||
CompareExchange128 = 14,
|
||||
/// <summary>
|
||||
/// The atomic compare 64 and exchange 128-bit operation (cmp8xchg16) is available (This feature is not supported until Windows Vista.)
|
||||
/// </summary>
|
||||
Compare64Exchange128 = 15,
|
||||
/// <summary>
|
||||
/// TBD
|
||||
/// </summary>
|
||||
ChannelsEnabled = 16,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//largely from https://raw.githubusercontent.com/noserati/tpl/master/ThreadAffinityTaskScheduler.cs (MIT license)
|
||||
public static class Win32ThreadHacks
|
||||
{
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue