using Essgee; using Essgee.Emulation; using Essgee.Emulation.Configuration; using Essgee.EventArguments; using Essgee.Exceptions; using Essgee.Extensions; using Essgee.Metadata; using Essgee.Utilities; using Essgee.Utilities.XInput; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using UnityEngine; public class Essgeeinit : MonoBehaviour { static Essgeeinit instance; public static System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); public static bool bInGame => instance?.emulatorHandler?.IsRunning == true ? true : false; #region UEGVideoPlayer graphicsHandler; UEGSoundPlayer soundHandler; GameMetadataHandler gameMetadataHandler; GameMetadata lastGameMetadata; EmulatorHandler emulatorHandler; bool lastUserPauseState; (int x, int y, int width, int height) currentViewport; double currentPixelAspectRatio; byte[] lastFramebufferData; (int width, int height) lastFramebufferSize; private UniKeyboard mUniKeyboard; #endregion void Awake() { instance = this; InitAll(Application.streamingAssetsPath, Application.persistentDataPath); //LoadAndRunCartridge("G:/Ninja_Gaiden_(UE)_type_A_[!].sms"); LoadAndRunCartridge("G:/SML2.gb"); } void OnDisable() { SaveConfiguration(); Dispose(false); } private void Update() { if (!emulatorHandler.IsRunning) return; mUniKeyboard.UpdateInputKey(); } void InitAll(string BaseDataDir, string CustonDataDir) { //初始化配置 InitAppEnvironment(BaseDataDir, CustonDataDir); InitEmu(); //细节初始化 InitializeHandlers(); } private void InitAppEnvironment(string BaseDataDir, string CustonDataDir) { EssgeeLogger.Init(new UEGLog()); EmuStandInfo.datDirectoryPath = Path.Combine(BaseDataDir, "EssgeeAssets", "No-Intro"); EmuStandInfo.metadataDatabaseFilePath = Path.Combine(BaseDataDir, "EssgeeAssets", "MetadataDatabase.json"); EmuStandInfo.jsonConfigFileName = "Config.json"; EmuStandInfo.saveDataDirectoryName = "Saves"; EmuStandInfo.screenshotDirectoryName = "Screenshots"; EmuStandInfo.saveStateDirectoryName = "Savestates"; EmuStandInfo.extraDataDirectoryName = "Extras"; EmuStandInfo.ProductName = "AxibugEmu"; EmuStandInfo.ProductVersion = ""; EmuStandInfo.programDataDirectory = Path.Combine(CustonDataDir, EmuStandInfo.ProductName); EmuStandInfo.programConfigPath = Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.jsonConfigFileName); EmuStandInfo.ShaderPath = Path.Combine(CustonDataDir, "Assets", "Shaders"); EmuStandInfo.SaveDataPath = Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveDataDirectoryName); EmuStandInfo.ScreenshotPath = Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.screenshotDirectoryName); EmuStandInfo.SaveStatePath = Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.saveStateDirectoryName); EmuStandInfo.ExtraDataPath = Path.Combine(EmuStandInfo.programDataDirectory, EmuStandInfo.extraDataDirectoryName); LoadConfiguration(); if (!Directory.Exists(EmuStandInfo.SaveDataPath)) Directory.CreateDirectory(EmuStandInfo.SaveDataPath); if (!Directory.Exists(EmuStandInfo.ScreenshotPath)) Directory.CreateDirectory(EmuStandInfo.ScreenshotPath); if (!Directory.Exists(EmuStandInfo.SaveStatePath)) Directory.CreateDirectory(EmuStandInfo.SaveStatePath); if (!Directory.Exists(EmuStandInfo.ExtraDataPath)) Directory.CreateDirectory(EmuStandInfo.ExtraDataPath); if (AppEnvironment.EnableLogger) { //TODO 关闭Debug //Logger.Flush(); //Logger.Close(); } } void InitEmu() { //keysDown = new List(); } #region 细节初始化 private void InitializeHandlers() { InitializeOSDHandler(); InitializeGraphicsHandler(); InitializeSoundHandler(); InitializeMetadataHandler(); mUniKeyboard = this.gameObject.AddComponent(); } private void InitializeOSDHandler() { //var osdFontText = Assembly.GetExecutingAssembly().ReadEmbeddedImageFile($"{Application.ProductName}.Assets.OsdFont.png"); //onScreenDisplayHandler = new OnScreenDisplayHandler(osdFontText); //onScreenDisplayHandler?.EnqueueMessageDebug($"Hello from {GetProductNameAndVersionString(true)}, this is a debug build!\nOSD handler initialized; font bitmap is {osdFontText.Width}x{osdFontText.Height}."); //if (onScreenDisplayHandler == null) throw new HandlerException("Failed to initialize OSD handler"); } private void InitializeGraphicsHandler() { graphicsHandler = this.gameObject.GetComponent(); //graphicsHandler = new GraphicsHandler(onScreenDisplayHandler); //graphicsHandler?.LoadShaderBundle(Program.Configuration.LastShader); } private void InitializeSoundHandler() { soundHandler = this.gameObject.GetComponent(); //soundHandler = new SoundHandler(onScreenDisplayHandler, Program.Configuration.SampleRate, 2, ExceptionHandler); //soundHandler.SetVolume(Program.Configuration.Volume); //soundHandler.SetMute(Program.Configuration.Mute); //soundHandler.SetLowPassFilter(Program.Configuration.LowPassFilter); //soundHandler.Startup(); } private void InitializeMetadataHandler() { //gameMetadataHandler = new GameMetadataHandler(onScreenDisplayHandler); gameMetadataHandler = new GameMetadataHandler(); } #endregion void Dispose(bool disposing) { //TODO 释放时 //if (disposing) //{ // if (components != null) components.Dispose(); // if (onScreenDisplayHandler != null) onScreenDisplayHandler.Dispose(); // if (graphicsHandler != null) graphicsHandler.Dispose(); // if (soundHandler != null) soundHandler.Dispose(); //} //base.Dispose(disposing); } #region 配置 private static void LoadConfiguration() { Directory.CreateDirectory(EmuStandInfo.programDataDirectory); if (!File.Exists(EmuStandInfo.programConfigPath) || (EmuStandInfo.Configuration = EmuStandInfo.programConfigPath.DeserializeFromFile()) == null) { EmuStandInfo.Configuration = new Configuration(); EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); } List machineType = new List(); machineType.Add(typeof(GameBoy)); machineType.Add(typeof(MasterSystem)); //foreach (var machineConfigType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IConfiguration).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) foreach (var machineConfigType in machineType) { if (!EmuStandInfo.Configuration.Machines.ContainsKey(machineConfigType.Name)) EmuStandInfo.Configuration.Machines.Add(machineConfigType.Name, (IConfiguration)Activator.CreateInstance(machineConfigType)); } //foreach (var debuggerFormType in Assembly.GetExecutingAssembly().GetTypes().Where(x => typeof(IDebuggerForm).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)) //{ // if (!StandInfo.Configuration.DebugWindows.ContainsKey(debuggerFormType.Name)) // StandInfo.Configuration.DebugWindows.Add(debuggerFormType.Name, Point.Empty); //} } private void ApplyConfigOverrides(Type machineType) { var forcePowerOnWithoutCart = false; var hasTVStandardOverride = false; var hasRegionOverride = false; var hasDisallowMemoryControlOverride = false; var overrideConfig = EmuStandInfo.Configuration.Machines[machineType.Name].CloneObject(); if (lastGameMetadata == null) { var property = overrideConfig.GetType().GetProperty("UseBootstrap"); if (property != null && (bool)property.GetValue(overrideConfig) != true) { property.SetValue(overrideConfig, true); forcePowerOnWithoutCart = true; } } if (lastGameMetadata != null && lastGameMetadata.PreferredTVStandard != TVStandard.Auto) { var property = overrideConfig.GetType().GetProperty("TVStandard"); if (property != null) { property.SetValue(overrideConfig, lastGameMetadata.PreferredTVStandard); hasTVStandardOverride = true; } } if (lastGameMetadata != null && lastGameMetadata.PreferredRegion != Essgee.Emulation.Region.Auto) { var property = overrideConfig.GetType().GetProperty("Region"); if (property != null) { property.SetValue(overrideConfig, lastGameMetadata.PreferredRegion); hasRegionOverride = true; } } if (lastGameMetadata != null && lastGameMetadata.AllowMemoryControl != true) { var propertyMem = overrideConfig.GetType().GetProperty("AllowMemoryControl"); if (propertyMem != null) { propertyMem.SetValue(overrideConfig, lastGameMetadata.AllowMemoryControl); hasDisallowMemoryControlOverride = true; var propertyBoot = overrideConfig.GetType().GetProperty("UseBootstrap"); if (propertyBoot != null) { propertyBoot.SetValue(overrideConfig, false); } } } if (forcePowerOnWithoutCart) EssgeeLogger.EnqueueMessageWarning("Bootstrap ROM is disabled in settings; enabling it for this startup."); if (hasTVStandardOverride) EssgeeLogger.EnqueueMessageWarning($"Overriding TV standard setting; running game as {lastGameMetadata?.PreferredTVStandard}."); if (hasRegionOverride) EssgeeLogger.EnqueueMessageWarning($"Overriding region setting; running game as {lastGameMetadata?.PreferredRegion}."); if (hasDisallowMemoryControlOverride) EssgeeLogger.EnqueueMessageWarning("Game-specific hack: Preventing software from reconfiguring memory control.\nBootstrap ROM has been disabled for this startup due to memory control hack."); if (forcePowerOnWithoutCart || hasTVStandardOverride || hasRegionOverride || hasDisallowMemoryControlOverride) emulatorHandler.SetConfiguration(overrideConfig); } public static void SaveConfiguration() { EmuStandInfo.Configuration.SerializeToFile(EmuStandInfo.programConfigPath); } #endregion #region 模拟器基本设置 public void SetEmuFpsLimit(bool bOpen) { emulatorHandler?.SetFpsLimiting(bOpen); } public void SetSoundMute(bool bOpen) { //soundHandler?.SetMute(Program.Configuration.Mute); } public void SetSoundLowPassFilter(bool bOpen) { //soundHandler?.SetLowPassFilter(Program.Configuration.LowPassFilter);; } public void SetTemporaryPause(bool newTemporaryPauseState) { if (emulatorHandler == null || !emulatorHandler.IsRunning || !EmuStandInfo.Configuration.AutoPause) return; if (newTemporaryPauseState) emulatorHandler.Pause(true); else if (!lastUserPauseState) emulatorHandler.Pause(false); } #endregion #region 模拟器生命周期 private void PowerOnWithoutCartridge(Type machineType) { //TODO IsRecording?? 可能需要实现 //if (soundHandler.IsRecording) // soundHandler.CancelRecording(); InitializeEmulation(machineType); lastGameMetadata = null; ApplyConfigOverrides(machineType); emulatorHandler.Startup(); EssgeeLogger.EnqueueMessageSuccess("Power on without cartridge."); } private void LoadAndRunCartridge(string fileName) { try { var (machineType, romData) = CartridgeLoader.Load(fileName, "ROM image"); //TODO IsRecording?? 可能需要实现 //if (soundHandler.IsRecording) // soundHandler.CancelRecording(); InitializeEmulation(machineType); lastGameMetadata = gameMetadataHandler.GetGameMetadata(emulatorHandler.Information.DatFileName, fileName, Crc32.Calculate(romData), romData.Length); ApplyConfigOverrides(machineType); emulatorHandler.LoadCartridge(romData, lastGameMetadata); //AddToRecentFiles(fileName); //CreateRecentFilesMenu(); //CreateLoadSaveStateMenus(); //CreateToggleGraphicsLayersMenu(); //CreateToggleSoundChannelsMenu(); //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = true; //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = true; //startRecordingToolStripMenuItem.Enabled = true; //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = true; //初始化不同平台的按钮 mUniKeyboard.Init(emulatorHandler.emulator); emulatorHandler.Startup(); //初始化音频 soundHandler.Initialize(); //SizeAndPositionWindow(); //SetWindowTitleAndStatus(); EssgeeLogger.EnqueueMessage($"Loaded '{lastGameMetadata?.KnownName ?? "unrecognized game"}'."); } catch (Exception ex) when (!AppEnvironment.DebugMode) { ExceptionHandler(ex); } } private void InitializeEmulation(Type machineType) { if (emulatorHandler != null) ShutdownEmulation(); emulatorHandler = new EmulatorHandler(machineType, ExceptionHandler); emulatorHandler.Initialize(); emulatorHandler.SendLogMessage += EmulatorHandler_SendLogMessage; emulatorHandler.EmulationReset += EmulatorHandler_EmulationReset; emulatorHandler.RenderScreen += EmulatorHandler_RenderScreen; emulatorHandler.SizeScreen += EmulatorHandler_SizeScreen; emulatorHandler.ChangeViewport += EmulatorHandler_ChangeViewport; emulatorHandler.PollInput += EmulatorHandler_PollInput; emulatorHandler.EnqueueSamples += EnqueueSoundSamples; emulatorHandler.SaveExtraData += EmulatorHandler_SaveExtraData; emulatorHandler.EnableRumble += EmulatorHandler_EnableRumble; emulatorHandler.PauseChanged += EmulatorHandler_PauseChanged; //emulatorHandler.EnqueueSamples += soundDebuggerForm.EnqueueSamples; emulatorHandler.SetFpsLimiting(EmuStandInfo.Configuration.LimitFps); emulatorHandler.SetConfiguration(EmuStandInfo.Configuration.Machines[machineType.Name]); currentPixelAspectRatio = emulatorHandler.Information.PixelAspectRatio; //pauseToolStripMenuItem.DataBindings.Clear(); //pauseToolStripMenuItem.CheckedChanged += (s, e) => //{ // var pauseState = (s as ToolStripMenuItem).Checked; // emulatorHandler.Pause(pauseState); // lastUserPauseState = pauseState; //}; EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Manufacturer} {emulatorHandler.Information.Model} emulation initialized."); } private void ExceptionHandler(Exception ex) { //this.CheckInvokeMethod(() => //{ if (!AppEnvironment.TemporaryDisableCustomExceptionForm) { //TODO debug窗口? //(_, ExceptionResult result, string prefix, string postfix) = ExceptionForm.GetExceptionInfo(ex); //if (result == ExceptionResult.Continue) //{ // //MessageBox.Show($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); // EssgeeLogger.Err($"{prefix}{ex.InnerException?.Message ?? ex.Message}\n\n{postfix}."); //} //else //{ // //var exceptionForm = new ExceptionForm(ex) { Owner = this }; // //exceptionForm.ShowDialog(); // switch (result) // { // case ExceptionResult.StopEmulation: // SignalStopEmulation(); // break; // case ExceptionResult.ExitApplication: // Environment.Exit(-1); // break; // } //} } else { var exceptionInfoBuilder = new StringBuilder(); exceptionInfoBuilder.AppendLine($"Thread: {ex.Data["Thread"] ?? ""}"); exceptionInfoBuilder.AppendLine($"Function: {ex.TargetSite.ReflectedType.FullName}.{ex.TargetSite.Name}"); exceptionInfoBuilder.AppendLine($"Exception: {ex.GetType().Name}"); exceptionInfoBuilder.Append($"Message: {ex.Message}"); var isUnhandled = Convert.ToBoolean(ex.Data["IsUnhandled"]); if (!isUnhandled && ex is CartridgeLoaderException) { //MessageBox.Show($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); EssgeeLogger.Err($"{ex.InnerException?.Message ?? ex.Message}\n\nFailed to load cartridge."); } else if (!isUnhandled && ex is EmulationException) { //MessageBox.Show($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated.", "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); EssgeeLogger.Err($"An emulation exception has occured!\n\n{exceptionInfoBuilder.ToString()}\n\nEmulation cannot continue and will be terminated."); SignalStopEmulation(); } else { var errorBuilder = new StringBuilder(); errorBuilder.AppendLine("An unhandled exception has occured!"); errorBuilder.AppendLine(); errorBuilder.AppendLine(exceptionInfoBuilder.ToString()); errorBuilder.AppendLine(); errorBuilder.AppendLine("Exception occured:"); errorBuilder.AppendLine($"{ex.StackTrace}"); errorBuilder.AppendLine(); errorBuilder.AppendLine("Execution cannot continue and the application will be terminated."); //EssgeeLogger.Err(errorBuilder.ToString(), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); EssgeeLogger.Err(errorBuilder.ToString()); Environment.Exit(-1); } } //}); } private void SignalStopEmulation() { ShutdownEmulation(); lastGameMetadata = null; //takeScreenshotToolStripMenuItem.Enabled = pauseToolStripMenuItem.Enabled = resetToolStripMenuItem.Enabled = stopToolStripMenuItem.Enabled = false; //loadStateToolStripMenuItem.Enabled = saveStateToolStripMenuItem.Enabled = false; //startRecordingToolStripMenuItem.Enabled = false; //toggleLayersToolStripMenuItem.Enabled = enableChannelsToolStripMenuItem.Enabled = false; //SetWindowTitleAndStatus(); } private void ShutdownEmulation() { if (emulatorHandler == null) return; emulatorHandler.SaveCartridge(); emulatorHandler.SendLogMessage -= EmulatorHandler_SendLogMessage; emulatorHandler.EmulationReset -= EmulatorHandler_EmulationReset; emulatorHandler.RenderScreen -= EmulatorHandler_RenderScreen; emulatorHandler.SizeScreen -= EmulatorHandler_SizeScreen; emulatorHandler.ChangeViewport -= EmulatorHandler_ChangeViewport; emulatorHandler.PollInput -= EmulatorHandler_PollInput; emulatorHandler.EnqueueSamples -= EnqueueSoundSamples; emulatorHandler.SaveExtraData -= EmulatorHandler_SaveExtraData; emulatorHandler.EnableRumble -= EmulatorHandler_EnableRumble; emulatorHandler.PauseChanged -= EmulatorHandler_PauseChanged; //emulatorHandler.EnqueueSamples -= soundDebuggerForm.EnqueueSamples; emulatorHandler.Shutdown(); while (emulatorHandler.IsRunning) { } emulatorHandler = null; GC.Collect(); //graphicsHandler?.FlushTextures(); EssgeeLogger.WriteLine("Emulation stopped."); } #endregion #region 模拟器内部事件 private void EmulatorHandler_SendLogMessage(object sender, SendLogMessageEventArgs e) { //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessageCore($"{emulatorHandler.Information.Model}: {e.Message}"); }); //TODO log EssgeeLogger.EnqueueMessageSuccess($"{emulatorHandler.Information.Model}: {e.Message}"); } private void EmulatorHandler_EmulationReset(object sender, EventArgs e) { //this.CheckInvokeMethod(delegate () { onScreenDisplayHandler.EnqueueMessage("Emulation reset."); }); EssgeeLogger.EnqueueMessageSuccess("Emulation reset."); } private void EmulatorHandler_RenderScreen(object sender, RenderScreenEventArgs e) { //this.CheckInvokeMethod(delegate () //{ //if (e.Width != lastFramebufferSize.width || e.Height != lastFramebufferSize.height) //{ // lastFramebufferSize = (e.Width, e.Height); // graphicsHandler?.SetTextureSize(e.Width, e.Height); //} //lastFramebufferData = e.FrameData; //graphicsHandler?.SetTextureData(e.FrameData); //graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameData, 0); graphicsHandler.SubmitVideo(e.Width, e.Height, e.FrameDataPtr, 0); // TODO: create emulation "EndOfFrame" event for this? ControllerManager.Update(); //}); } private void EmulatorHandler_SizeScreen(object sender, SizeScreenEventArgs e) { //TODO 待实现 屏幕大小 //this.CheckInvokeMethod(delegate () //{ // lastFramebufferSize = (e.Width, e.Height); // graphicsHandler?.SetTextureSize(e.Width, e.Height); //}); } private void EmulatorHandler_ChangeViewport(object sender, ChangeViewportEventArgs e) { //TODO 待实现 //this.CheckInvokeMethod(delegate () //{ // graphicsHandler?.SetScreenViewport(currentViewport = e.Viewport); // SizeAndPositionWindow(); //}); } private void EmulatorHandler_PollInput(object sender, PollInputEventArgs e) { //TODO Input实现 e.Keyboard = mUniKeyboard.mKeyCodeCore.GetPressedKeys(); e.MouseButtons = default; e.MousePosition = default; // TODO: rare, random, weird argument exceptions on e.Keyboard assignment; does this lock help?? //lock (uiLock) //{ // e.Keyboard = new List(keysDown); // e.MouseButtons = mouseButtonsDown; // var vx = (currentViewport.x - 50); // var dvx = renderControl.ClientSize.Width / (currentViewport.width - (double)vx); // var dvy = renderControl.ClientSize.Height / (currentViewport.height - (double)currentViewport.y); // e.MousePosition = ((int)(mousePosition.x / dvx) - vx, (int)(mousePosition.y / dvy) - currentViewport.y); // if (EmuStandInfo.Configuration.EnableXInput) // e.ControllerState = ControllerManager.GetController(0).GetControllerState(); //} } private void EmulatorHandler_SaveExtraData(object sender, SaveExtraDataEventArgs e) { /* Extract options etc. */ var includeDateTime = e.Options.HasFlag(ExtraDataOptions.IncludeDateTime); var allowOverwrite = e.Options.HasFlag(ExtraDataOptions.AllowOverwrite); var extension = string.Empty; switch (e.DataType) { case ExtraDataTypes.Image: extension = "png"; break; case ExtraDataTypes.Raw: extension = "bin"; break; default: throw new EmulationException($"Unknown extra data type {e.DataType}"); } /* Generate filename/path */ var filePrefix = $"{Path.GetFileNameWithoutExtension(lastGameMetadata.FileName)} ({e.Description}{(includeDateTime ? $" {DateTime.Now:yyyy-MM-dd HH-mm-ss})" : ")")}"; var filePath = Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix}.{extension}"); if (!allowOverwrite) { var existingFiles = Directory.EnumerateFiles(EmuStandInfo.ExtraDataPath, $"{filePrefix}*{extension}"); if (existingFiles.Contains(filePath)) for (int i = 2; existingFiles.Contains(filePath = Path.Combine(EmuStandInfo.ExtraDataPath, $"{filePrefix} ({i}).{extension}")); i++) { } } /* Handle data */ //if (e.Data is Bitmap image) if (e.DataType == ExtraDataTypes.Image) { /* Images, ex. GB Printer printouts */ //image.Save(filePath); //TODO 图像存储 } else if (e.Data is byte[] raw) { /* Raw bytes */ using (var file = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { file.Write(raw, 0, raw.Length); } } } private void EmulatorHandler_EnableRumble(object sender, EventArgs e) { if (EmuStandInfo.Configuration.EnableXInput && EmuStandInfo.Configuration.EnableRumble) ControllerManager.GetController(0).Vibrate(0.0f, 0.5f, TimeSpan.FromSeconds(0.1f)); } private void EmulatorHandler_PauseChanged(object sender, EventArgs e) { //SetWindowTitleAndStatus(); if (emulatorHandler.IsPaused) { //TODO 音频暂停? //soundHandler?.ClearSampleBuffer(); } } public void EnqueueSoundSamples(object sender, EnqueueSamplesEventArgs e) { //if (sampleQueue.Count > MaxQueueLength) //{ // var samplesToDrop = (sampleQueue.Count - MaxQueueLength); // onScreenDisplayHandler.EnqueueMessageDebug($"({GetType().Name}/{DateTime.Now.Second:D2}s) Sample queue overflow; dropping {samplesToDrop} of {sampleQueue.Count} samples."); // for (int i = 0; i < samplesToDrop; i++) // if (sampleQueue.Count != 0) // sampleQueue.Dequeue(); //} //sampleQueue.Enqueue(e.MixedSamples.ToArray()); //if (IsRecording) //{ // dataChunk.AddSampleData(e.MixedSamples); // waveHeader.FileLength += (uint)e.MixedSamples.Length; //} //TODO 音频处理 soundHandler.SubmitSamples(e.MixedSamples, e.ChannelSamples, e.MixedSamples.Length); } #endregion }