diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Audio/DMGAudio.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Audio/DMGAudio.cs index 5ff4e81d..cba87ca7 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Audio/DMGAudio.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Audio/DMGAudio.cs @@ -296,6 +296,8 @@ namespace Essgee.Emulation.Audio sampleCycleCount = frameCycleCount = 0; } + //独立声明,不在函数内部 + private bool[] channelEnableFlags = new bool[4]; public void Step(int clockCyclesInStep) { if (!isSoundHwEnabled) return; @@ -385,10 +387,25 @@ namespace Essgee.Emulation.Audio // new bool[] { !channel1ForceEnable, !channel2ForceEnable, !channel3ForceEnable, !channel4ForceEnable }, // mixedSampleBuffer.ToArray()); + //有GC + //EnqueueSamplesEventArgs eventArgs = EnqueueSamplesEventArgs.Create( + // numChannels, + // channelSampleBuffer, + // new bool[] { !channel1ForceEnable, !channel2ForceEnable, !channel3ForceEnable, !channel4ForceEnable }, + // mixedSampleBuffer, + // mixedSampleBuffer_writePos); + + + // 在函数中使用 + channelEnableFlags[0] = !channel1ForceEnable; + channelEnableFlags[1] = !channel2ForceEnable; + channelEnableFlags[2] = !channel3ForceEnable; + channelEnableFlags[3] = !channel4ForceEnable; + EnqueueSamplesEventArgs eventArgs = EnqueueSamplesEventArgs.Create( numChannels, channelSampleBuffer, - new bool[] { !channel1ForceEnable, !channel2ForceEnable, !channel3ForceEnable, !channel4ForceEnable }, + channelEnableFlags, mixedSampleBuffer, mixedSampleBuffer_writePos); diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs index b07a169f..1727d4e8 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs @@ -44,7 +44,16 @@ namespace Essgee.Emulation buffer[address + 3] = 0xFF; } - public static void RGBCGBtoBGRA8888(int color, ref byte[] buffer, int address) + //public static void RGBCGBtoBGRA8888(int color, ref byte[] buffer, int address) + //{ + // /* https://byuu.net/video/color-emulation -- "LCD emulation: Game Boy Color" */ + // byte r = (byte)((color >> 0) & 0x1F), g = (byte)((color >> 5) & 0x1F), b = (byte)((color >> 10) & 0x1F); + // buffer[address + 0] = (byte)(Math.Min(960, (r * 6) + (g * 4) + (b * 22)) >> 2); + // buffer[address + 1] = (byte)(Math.Min(960, (g * 24) + (b * 8)) >> 2); + // buffer[address + 2] = (byte)(Math.Min(960, (r * 26) + (g * 4) + (b * 2)) >> 2); + // buffer[address + 3] = 0xFF; + //} + public static void RGBCGBtoBGRA8888(int color, ref byte* buffer, int address) { /* https://byuu.net/video/color-emulation -- "LCD emulation: Game Boy Color" */ byte r = (byte)((color >> 0) & 0x1F), g = (byte)((color >> 5) & 0x1F), b = (byte)((color >> 10) & 0x1F); diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs index 51fda27c..adbcfe87 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs @@ -346,7 +346,7 @@ namespace Essgee.Emulation.Video.Nintendo WriteColorToFramebuffer(c, ((y * displayActiveWidth) + (x % displayActiveWidth)) * 4); } - private void WriteColorToFramebuffer(ushort c, int address) + private unsafe void WriteColorToFramebuffer(ushort c, int address) { RGBCGBtoBGRA8888(c, ref outputFramebuffer, address); } diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/DMGVideo.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/DMGVideo.cs index f75d4e47..6e307eb2 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/DMGVideo.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/DMGVideo.cs @@ -8,7 +8,7 @@ using static Essgee.Emulation.CPU.SM83; namespace Essgee.Emulation.Video.Nintendo { - public class DMGVideo : IVideo + public unsafe class DMGVideo : IVideo { protected const int displayActiveWidth = 160; protected const int displayActiveHeight = 144; @@ -109,7 +109,48 @@ namespace Essgee.Emulation.Video.Nintendo protected byte[,] screenUsageFlags, screenUsageSpriteXCoords, screenUsageSpriteSlots; protected int cycleCount, cycleDotPause, currentScanline; - protected byte[] outputFramebuffer; + //protected byte[] outputFramebuffer; + + #region //指针化 outputFramebuffer + byte[] outputFramebuffer_src; + protected GCHandle outputFramebuffer_handle; + public byte* outputFramebuffer; + public int outputFramebufferLength; + public bool outputFramebuffer_IsNull => outputFramebuffer == null; + public byte[] outputFramebuffer_set + { + set + { + outputFramebuffer_handle.ReleaseGCHandle(); + outputFramebuffer_src = value; + outputFramebufferLength = value.Length; + outputFramebuffer_src.GetObjectPtr(ref outputFramebuffer_handle, ref outputFramebuffer); + } + } + #endregion + + + #region //指针化 outputFramebufferCopy + byte[] outputFramebufferCopy_src; + GCHandle outputFramebufferCopy_handle; + public byte* outputFramebufferCopy; + public int outputFramebufferCopyLength; + public bool outputFramebufferCopy_IsNull => outputFramebufferCopy == null; + private IntPtr outputFramebufferCopy_IntPtr; + public byte[] outputFramebufferCopy_set + { + set + { + outputFramebufferCopy_handle.ReleaseGCHandle(); + outputFramebufferCopy_src = value; + outputFramebufferCopyLength = value.Length; + outputFramebufferCopy_src.GetObjectPtr(ref outputFramebufferCopy_handle, ref outputFramebufferCopy); + outputFramebufferCopy_IntPtr = outputFramebufferCopy_handle.AddrOfPinnedObject(); + } + } + #endregion + + protected int clockCyclesPerLine; @@ -247,7 +288,10 @@ namespace Essgee.Emulation.Video.Nintendo screenUsageFlags = new byte[displayActiveWidth, displayActiveHeight]; screenUsageSpriteXCoords = new byte[displayActiveWidth, displayActiveHeight]; screenUsageSpriteSlots = new byte[displayActiveWidth, displayActiveHeight]; - outputFramebuffer = new byte[numDisplayPixels * 4]; + //outputFramebuffer = new byte[numDisplayPixels * 4]; + outputFramebuffer_set = new byte[numDisplayPixels * 4]; + + outputFramebufferCopy_set = new byte[numDisplayPixels * 4]; for (var y = 0; y < displayActiveHeight; y++) SetLine(y, 0xFF, 0xFF, 0xFF); @@ -398,7 +442,8 @@ namespace Essgee.Emulation.Video.Nintendo } - GCHandle? lasyRenderHandle; + GCHandle? lastRenderHandle; + protected virtual void EndHBlank() { /* End of scanline reached */ @@ -423,16 +468,25 @@ namespace Essgee.Emulation.Video.Nintendo /* Submit screen for rendering */ - // 固定数组,防止垃圾回收器移动它 - var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); - // 获取数组的指针 - IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); + //// 固定数组,防止垃圾回收器移动它 + //var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer_src.Clone() as byte[], GCHandleType.Pinned); + //// 获取数组的指针 + //IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); + + + for (int i = 0; i < outputFramebufferLength; i++) + { + outputFramebufferCopy[i] = outputFramebuffer[i]; + } + IntPtr mFrameDataPtr = outputFramebufferCopy_IntPtr; + var eventArgs = RenderScreenEventArgs.Create(displayActiveWidth, displayActiveHeight, mFrameDataPtr); OnRenderScreen(eventArgs); eventArgs.Release(); - if (lasyRenderHandle != null) - lasyRenderHandle.Value.Free(); - lasyRenderHandle = bitmapcolorRect_handle; + + //if (lastRenderHandle.HasValue) + // lastRenderHandle.Value.Free(); + //lastRenderHandle = bitmapcolorRect_handle; //OnRenderScreen(new RenderScreenEventArgs(displayActiveWidth, displayActiveHeight, outputFramebuffer.Clone() as byte[])); }