消灭Essgee中GameBoy/DMG的音视频GC

This commit is contained in:
sin365 2025-10-16 13:23:40 +08:00
parent 0b7a11291c
commit a6178e991c
4 changed files with 94 additions and 14 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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[]));
}