public LibretroApi(string dllPath, string corePath) { InstanceName = "libretro_" + Guid.NewGuid().ToString(); var pipeName = InstanceName; instanceDll = new InstanceDll(dllPath); instanceDllCore = new InstanceDll(corePath); var dllinit = (DllInit)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("DllInit"), typeof(DllInit)); Message = (MessageApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("Message"), typeof(MessageApi)); _copyBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("CopyBuffer"), typeof(BufferApi)); _setBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("SetBuffer"), typeof(BufferApi)); SetVariable = (SetVariableApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("SetVariable"), typeof(SetVariableApi)); comm = (CommStruct *)dllinit(instanceDllCore.HModule).ToPointer(); //TODO: (stash function pointers locally and thunk to IntPtr) //ALSO: this should be done by the core, I think, not the API. No smarts should be in here comm->env.retro_perf_callback.get_cpu_features = IntPtr.Zero; //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) => { }); }
public LibRetro(string modulename) { dll = new InstanceDll(modulename); if (!ConnectAllEntryPoints()) { dll.Dispose(); throw new Exception("ConnectAllEntryPoints() failed. The console may contain more details."); } }
BufferApi _setBuffer; //TODO: consider making private and wrapping public LibsnesApi(string dllPath) { InstanceName = "libsneshawk_" + Guid.NewGuid().ToString(); instanceDll = new InstanceDll(dllPath); var dllinit = (DllInit)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("DllInit"), typeof(DllInit)); Message = (MessageApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("Message"), typeof(MessageApi)); _copyBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("CopyBuffer"), typeof(BufferApi)); _setBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("SetBuffer"), typeof(BufferApi)); comm = (CommStruct *)dllinit().ToPointer(); }
public LibsnesApi(string dllPath) { InstanceName = "libsneshawk_" + Guid.NewGuid().ToString(); var pipeName = InstanceName; mmf = MemoryMappedFile.CreateNew(pipeName, 1024 * 1024); mmva = mmf.CreateViewAccessor(); mmva.SafeMemoryMappedViewHandle.AcquirePointer(ref mmvaPtr); pipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, 1024 * 1024, 1024); instanceDll = new InstanceDll(dllPath); var dllinit = (DllInit)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("DllInit"), typeof(DllInit)); dllinit(pipeName); //TODO - start a thread to wait for process to exit and gracefully handle errors? how about the pipe? pipe.WaitForConnection(); rbuf = new IPCRingBuffer(); wbuf = new IPCRingBuffer(); rbuf.Allocate(1024); wbuf.Allocate(1024); rbufstr = new IPCRingBufferStream(rbuf); wbufstr = new IPCRingBufferStream(wbuf); rstream = new SwitcherStream(); wstream = new SwitcherStream(); rstream.SetCurrStream(pipe); wstream.SetCurrStream(pipe); brPipe = new BinaryReader(rstream); bwPipe = new BinaryWriter(wstream); WritePipeMessage(eMessage.eMessage_SetBuffer); bwPipe.Write(1); WritePipeString(rbuf.Id); WritePipeMessage(eMessage.eMessage_SetBuffer); bwPipe.Write(0); WritePipeString(wbuf.Id); bwPipe.Flush(); }
public LibretroApi(string dllPath, string corePath) { T GetTypedDelegate <T>(string proc) where T : Delegate => (T)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddrOrThrow(proc), typeof(T)); InstanceName = "libretro_" + Guid.NewGuid(); var pipeName = InstanceName; instanceDll = new InstanceDll(dllPath); instanceDllCore = new InstanceDll(corePath); Message = GetTypedDelegate <MessageApi>("Message"); _copyBuffer = GetTypedDelegate <BufferApi>("CopyBuffer"); _setBuffer = GetTypedDelegate <BufferApi>("SetBuffer"); SetVariable = GetTypedDelegate <SetVariableApi>("SetVariable"); comm = (CommStruct *)(OSTailoredCode.IsUnixHost ? GetTypedDelegate <DllInitUnix>("DllInit")(corePath) : GetTypedDelegate <DllInit>("DllInit")(instanceDllCore.HModule)).ToPointer(); //TODO: (stash function pointers locally and thunk to IntPtr) //ALSO: this should be done by the core, I think, not the API. No smarts should be in here comm->env.retro_perf_callback.get_cpu_features = IntPtr.Zero; //retro_perf_callback.get_cpu_features = new LibRetro.retro_get_cpu_features_t(() => (ulong)( // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsXMMIAvailable) ? LibRetro.RETRO_SIMD.SSE : 0) | // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsXMMI64Available) ? LibRetro.RETRO_SIMD.SSE2 : 0) | // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsSSE3Available) ? LibRetro.RETRO_SIMD.SSE3 : 0) | // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.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) => { }); }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings) { ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally (autodetect romtype, etc) string romextension = "GEN"; // three or six button? // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds //hack, don't use if (rom != null && rom.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } try { Dll = new InstanceDll(Path.Combine(comm.CoreFileProvider.DllPath(), LibGPGX.DllName)); Core = BizInvoker.GetInvoker <LibGPGX>(Dll); _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings(); _settings = (GPGXSettings)Settings ?? new GPGXSettings(); CoreComm = comm; LoadCallback = new LibGPGX.load_archive_cb(load_archive); this.romfile = rom; this.CD = CD; this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (_syncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings())) { throw new Exception("gpgx_init() failed"); } { int fpsnum = 60; int fpsden = 1; Core.gpgx_get_fps(ref fpsnum, ref fpsden); CoreComm.VsyncNum = fpsnum; CoreComm.VsyncDen = fpsden; Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL; } // compute state size { byte[] tmp = new byte[Core.gpgx_state_max_size()]; int size = Core.gpgx_state_size(tmp, tmp.Length); if (size <= 0) { throw new Exception("Couldn't Determine GPGX internal state size!"); } _savebuff = new byte[size]; _savebuff2 = new byte[_savebuff.Length + 13]; Console.WriteLine("GPGX Internal State Size: {0}", size); } SetControllerDefinition(); // pull the default video size from the core UpdateVideoInitial(); SetMemoryDomains(); InputCallback = new LibGPGX.input_cb(input_callback); Core.gpgx_set_input_callback(InputCallback); if (CD != null) { DriveLightEnabled = true; } // process the non-init settings now PutSettings(_settings); //TODO - this hits performance, we need to make it controllable CDCallback = new LibGPGX.CDCallback(CDCallbackProc); InitMemCallbacks(); KillMemCallbacks(); Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer); } catch { Dispose(); throw; } }