bool Handle_SIG(eMessage msg) { switch (msg) { default: return(false); case eMessage.eMessage_SIG_video_refresh: { int width = brPipe.ReadInt32(); int height = brPipe.ReadInt32(); bwPipe.Write(0); //offset in mapped memory buffer bwPipe.Flush(); brPipe.ReadBoolean(); //dummy synchronization if (video_refresh != null) { video_refresh((int *)mmvaPtr, width, height); } break; } case eMessage.eMessage_SIG_input_poll: break; case eMessage.eMessage_SIG_input_state: { int port = brPipe.ReadInt32(); int device = brPipe.ReadInt32(); int index = brPipe.ReadInt32(); int id = brPipe.ReadInt32(); ushort ret = 0; if (input_state != null) { ret = input_state(port, device, index, id); } bwPipe.Write(ret); bwPipe.Flush(); break; } case eMessage.eMessage_SIG_input_notify: { int index = brPipe.ReadInt32(); if (input_notify != null) { input_notify(index); } break; } case eMessage.eMessage_SIG_audio_flush: { int nsamples = brPipe.ReadInt32(); bwPipe.Write(0); //location to store audio buffer in bwPipe.Flush(); brPipe.ReadInt32(); //dummy synchronization if (audio_sample != null) { ushort *audiobuffer = ((ushort *)mmvaPtr); for (int i = 0; i < nsamples;) { ushort left = audiobuffer[i++]; ushort right = audiobuffer[i++]; audio_sample(left, right); } } bwPipe.Write(0); //dummy synchronization bwPipe.Flush(); brPipe.ReadInt32(); //dummy synchronization break; } case eMessage.eMessage_SIG_path_request: { int slot = brPipe.ReadInt32(); string hint = ReadPipeString(); string ret = hint; if (pathRequest != null) { hint = pathRequest(slot, hint); } WritePipeString(hint); break; } case eMessage.eMessage_SIG_trace_callback: { var trace = ReadPipeString(); if (traceCallback != null) { traceCallback(trace); } break; } case eMessage.eMessage_SIG_allocSharedMemory: { var name = ReadPipeString(); var size = brPipe.ReadInt32(); if (SharedMemoryBlocks.ContainsKey(name)) { throw new InvalidOperationException("Re-defined a shared memory block. Check bsnes init/shutdown code. Block name: " + name); } //try reusing existing block; dispose it if it exists and if the size doesnt match SharedMemoryBlock smb = null; if (DeallocatedMemoryBlocks.ContainsKey(name)) { smb = DeallocatedMemoryBlocks[name]; DeallocatedMemoryBlocks.Remove(name); if (smb.Size != size) { smb.Dispose(); smb = null; } } //allocate a new block if we have to if (smb == null) { smb = new SharedMemoryBlock(); smb.Name = name; smb.Size = size; smb.BlockName = InstanceName + smb.Name; smb.Allocate(); } SharedMemoryBlocks[smb.Name] = smb; WritePipeString(smb.BlockName); break; } case eMessage.eMessage_SIG_freeSharedMemory: { string name = ReadPipeString(); var smb = SharedMemoryBlocks[name]; DeallocatedMemoryBlocks[name] = smb; SharedMemoryBlocks.Remove(name); break; } } //switch(msg) return(true); }
bool Handle_SIG(eMessage msg) { switch (msg) { default: return(false); case eMessage.eMessage_SIG_video_refresh: { int width = comm->width; int height = comm->height; if (video_refresh != null) { video_refresh((int *)comm->ptr, width, height); } break; } case eMessage.eMessage_SIG_input_poll: break; case eMessage.eMessage_SIG_input_state: { int port = comm->port; int device = comm->device; int index = comm->index; int id = (int)comm->id; if (input_state != null) { comm->value = (uint)input_state(port, device, index, id); } break; } case eMessage.eMessage_SIG_input_notify: { if (input_notify != null) { input_notify(comm->index); } break; } case eMessage.eMessage_SIG_audio_flush: { uint nsamples = comm->size; if (audio_sample != null) { ushort *audiobuffer = ((ushort *)comm->ptr); for (uint i = 0; i < nsamples;) { ushort left = audiobuffer[i++]; ushort right = audiobuffer[i++]; audio_sample(left, right); } } break; } case eMessage.eMessage_SIG_path_request: { int slot = comm->slot; string hint = comm->GetAscii(); string ret = hint; if (pathRequest != null) { hint = pathRequest(slot, hint); } SetAscii(hint); break; } case eMessage.eMessage_SIG_trace_callback: { if (traceCallback != null) { traceCallback(comm->GetAscii()); } break; } case eMessage.eMessage_SIG_allocSharedMemory: { var name = comm->GetAscii(); var size = comm->size; if (SharedMemoryBlocks.ContainsKey(name)) { throw new InvalidOperationException("Re-defined a shared memory block. Check bsnes init/shutdown code. Block name: " + name); } //try reusing existing block; dispose it if it exists and if the size doesnt match SharedMemoryBlock smb = null; if (DeallocatedMemoryBlocks.ContainsKey(name)) { smb = DeallocatedMemoryBlocks[name]; DeallocatedMemoryBlocks.Remove(name); if (smb.Size != size) { smb.Dispose(); smb = null; } } //allocate a new block if we have to if (smb == null) { smb = new SharedMemoryBlock(); smb.Name = name; smb.Size = (int)size; smb.BlockName = InstanceName + smb.Name; smb.Allocate(); } comm->ptr = smb.Ptr; SharedMemoryBlocks[smb.Name] = smb; CopyString(smb.BlockName); break; } case eMessage.eMessage_SIG_freeSharedMemory: { foreach (var block in SharedMemoryBlocks.Values) { if (block.Ptr == comm->ptr) { DeallocatedMemoryBlocks[block.Name] = block; SharedMemoryBlocks.Remove(block.Name); break; } } break; } } //switch(msg) Message(eMessage.eMessage_Resume); return(true); }
private static async void InstanceListLoop() { SharedMemoryBlock block; try { block = new SharedMemoryBlock("__" + nameof(MaintFace), 65536, true); } catch (Exception) { // could not create memory segment, possibly because of security. we don't know. #if DEBUG Trace.WriteLine(nameof(MaintFace) + " Warning: Cannot view local " + nameof(MaintFace) + " instances; Could not create/read shared memory segment."); #endif return; } Guid instanceGuid = Guid.NewGuid(); for (;;) { try { using (block.AcquireExclusiveAccess()) { List<Instance> newList; try { newList = block.ReadSerializable<List<Instance>>(); } catch (Exception) { // Corrupt or non-existent; Create a new list. newList = new List<Instance>(); } // Find and update the timestamp; recreate if necessary bool found = false; for (int i = 0; i < newList.Count; i++) { if (newList[i].Guid == instanceGuid) { newList[i].TimeStamp = DateTime.UtcNow; newList[i].IsThis = true; found = true; break; } } if (!found) { var newInstance = new Instance() { Name = Name, Guid = instanceGuid, Url = Url, TimeStamp = DateTime.UtcNow, IsThis = true, }; // Make sure the name is unique for (int ct = 0; ; ct++) { if (ct == 0) newInstance.Name = Name; else newInstance.Name = Name + $" ({ct})"; bool unique = true; for (int i = 0; i < newList.Count; i++) if (newList[i].Name == newInstance.Name) { unique = false; break; } if (unique) break; } newList.Add(newInstance); } // Check other timestamps for age; delete if necessary var now = DateTime.UtcNow; for (int i = 0; i < newList.Count; i++) if ((now - newList[i].TimeStamp) > TimeSpan.FromSeconds(3)) newList.RemoveAt(i--); block.WriteSerializable(newList); _instances = newList; } } catch (Exception ex) { Trace.WriteLine(nameof(MaintFace) + " Error: " + nameof(InstanceListLoop) + ": " + ex.Message); } await Task.Delay(_messageRate); } }