diff --git a/Assets/Plugins/Essgee.Unity/AxiMemory.cs b/Assets/Plugins/Essgee.Unity/AxiMemory.cs new file mode 100644 index 0000000..25255e2 --- /dev/null +++ b/Assets/Plugins/Essgee.Unity/AxiMemory.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +namespace Essgee.Utilities +{ + internal unsafe static class AxiMemoryEx + { + static HashSet GCHandles = new HashSet(); + + public static void Init() + { + FreeAllGCHandle(); + set_TempBuffer = new byte[0x100000]; + } + + public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref uint* ptr) + { + GetObjectPtr(srcObj, ref handle, out IntPtr intptr); + ptr = (uint*)intptr; + } + + public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref short* ptr) + { + GetObjectPtr(srcObj, ref handle, out IntPtr intptr); + ptr = (short*)intptr; + } + public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref ushort* ptr) + { + GetObjectPtr(srcObj, ref handle, out IntPtr intptr); + ptr = (ushort*)intptr; + } + public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref int* ptr) + { + GetObjectPtr(srcObj, ref handle, out IntPtr intptr); + ptr = (int*)intptr; + } + public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref byte* ptr) + { + GetObjectPtr(srcObj, ref handle, out IntPtr intptr); + ptr = (byte*)intptr; + } + + static void GetObjectPtr(this object srcObj, ref GCHandle handle, out IntPtr intptr) + { + ReleaseGCHandle(ref handle); + handle = GCHandle.Alloc(srcObj, GCHandleType.Pinned); + GCHandles.Add(handle); + intptr = handle.AddrOfPinnedObject(); + } + + public static void ReleaseGCHandle(this ref GCHandle handle) + { + if (handle.IsAllocated) + handle.Free(); + GCHandles.Remove(handle); + } + + public static void FreeAllGCHandle() + { + foreach (var handle in GCHandles) + { + if (handle.IsAllocated) + handle.Free(); + } + GCHandles.Clear(); + } + + #region 指针化 TempBuffer + static byte[] TempBuffer_src; + static GCHandle TempBuffer_handle; + public static byte* TempBuffer; + public static byte[] set_TempBuffer + { + set + { + TempBuffer_handle.ReleaseGCHandle(); + if (value == null) + return; + TempBuffer_src = value; + TempBuffer_src.GetObjectPtr(ref TempBuffer_handle, ref TempBuffer); + } + } + #endregion + + public static void Write(this BinaryWriter bw, byte* bufferPtr, int offset, int count) + { + // 使用指针复制数据到临时数组 + Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count); + // 使用BinaryWriter写入临时数组 + bw.Write(TempBuffer_src, 0, count); + } + public static void Write(this FileStream fs, byte* bufferPtr, int offset, int count) + { + // 使用指针复制数据到临时数组 + Buffer.MemoryCopy(bufferPtr + offset, TempBuffer, 0, count); + // 使用BinaryWriter写入临时数组 + fs.Write(TempBuffer_src, 0, count); + } + public static int Read(this FileStream fs, byte* bufferPtr, int offset, int count) + { + // 使用BinaryWriter写入临时数组 + count = fs.Read(TempBuffer_src, offset, count); + // 使用指针复制数据到临时数组 + Buffer.MemoryCopy(TempBuffer, bufferPtr + offset, 0, count); + return count; + } + } + + internal unsafe static class AxiArray + { + + public static void Copy(byte* src, int srcindex, byte* target, int targetindex, int count) + { + int singlesize = sizeof(byte); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(&src[srcindex], &target[targetindex], totalBytesToCopy, totalBytesToCopy); + } + public static void Copy(short* src, int srcindex, short* target, int targetindex, int count) + { + int singlesize = sizeof(short); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(&src[srcindex], &target[targetindex], totalBytesToCopy, totalBytesToCopy); + } + public static void Copy(ushort* src, int srcindex, ushort* target, int targetindex, int count) + { + int singlesize = sizeof(ushort); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(&src[srcindex], &target[targetindex], totalBytesToCopy, totalBytesToCopy); + } + + public static void Copy(byte* src, byte* target, int index, int count) + { + int singlesize = sizeof(byte); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(&src[index], &target[index], totalBytesToCopy, totalBytesToCopy); + } + + public static void Copy(ushort* src, ushort* target, int index, int count) + { + int singlesize = sizeof(ushort); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(&src[index], &target[index], totalBytesToCopy, totalBytesToCopy); + } + public static void Copy(ushort* src, ushort* target, int count) + { + int singlesize = sizeof(ushort); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(src, target, totalBytesToCopy, totalBytesToCopy); + } + public static void Copy(byte* src, byte* target, int count) + { + int singlesize = sizeof(byte); + long totalBytesToCopy = count * singlesize; + Buffer.MemoryCopy(src, target, totalBytesToCopy, totalBytesToCopy); + } + public static void Clear(byte* data, int index, int lenght) + { + for (int i = index; i < lenght; i++, index++) + data[index] = 0; + } + public static void Clear(ushort* data, int index, int lenght) + { + for (int i = index; i < lenght; i++, index++) + data[index] = 0; + } + } +} diff --git a/Assets/Plugins/Essgee.Unity/AxiMemory.cs.meta b/Assets/Plugins/Essgee.Unity/AxiMemory.cs.meta new file mode 100644 index 0000000..98cca21 --- /dev/null +++ b/Assets/Plugins/Essgee.Unity/AxiMemory.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 922bbb45b85e7de4f8bce1c6f407009f \ No newline at end of file diff --git a/Assets/Plugins/Essgee.Unity/Emulation/EmulatorHandler.cs b/Assets/Plugins/Essgee.Unity/Emulation/EmulatorHandler.cs index 5ce4b66..33f0d19 100644 --- a/Assets/Plugins/Essgee.Unity/Emulation/EmulatorHandler.cs +++ b/Assets/Plugins/Essgee.Unity/Emulation/EmulatorHandler.cs @@ -2,6 +2,7 @@ using Essgee.Emulation.Machines; using Essgee.EventArguments; using Essgee.Metadata; +using Essgee.Utilities; using System; using System.Collections.Generic; using System.Diagnostics; @@ -129,8 +130,10 @@ namespace Essgee.Emulation emulator.Startup(); emulator.Reset(); - emulationThread = new Thread(ThreadMainLoop) { Name = "EssgeeEmulation", Priority = ThreadPriority.Normal }; - emulationThread.Start(); + //不再使用进程推帧 + + //emulationThread = new Thread(ThreadMainLoop) { Name = "EssgeeEmulation", Priority = ThreadPriority.Normal }; + //emulationThread.Start(); } public void Reset() @@ -171,6 +174,9 @@ namespace Essgee.Emulation public void LoadCartridge(byte[] romData, GameMetadata gameMetadata) { + //初始化AxiMem + AxiMemoryEx.Init(); + currentGameMetadata = gameMetadata; byte[] ramData = new byte[currentGameMetadata.RamSize]; @@ -225,6 +231,30 @@ namespace Essgee.Emulation public int FramesPerSecond { get; private set; } + public void Update_Frame() + { + if (!emulationThreadRunning) + return; + + while (pauseStateChangesRequested.Count > 0) + { + var newPauseState = pauseStateChangesRequested.Dequeue(); + emulationThreadPaused = newPauseState; + + PauseChanged?.Invoke(this, EventArgs.Empty); + } + + emulator.RunFrame(); + + + if (configChangeRequested) + { + emulator.SetConfiguration(newConfiguration); + configChangeRequested = false; + } + + } + private void ThreadMainLoop() { // TODO: rework fps limiter/counter - AGAIN - because the counter is inaccurate at sampleTimespan=0.25 and the limiter CAN cause sound crackling at sampleTimespan>0.25 diff --git a/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs b/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs index 1d29fac..b07a169 100644 --- a/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs +++ b/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs @@ -2,14 +2,22 @@ namespace Essgee.Emulation { - public static class Utilities + public unsafe static class Utilities { public static bool IsBitSet(byte value, int bit) { return ((value & (1 << bit)) != 0); } - public static void RGB222toBGRA8888(int color, ref byte[] buffer, int address) + //public static void RGB222toBGRA8888(int color, ref byte[] buffer, int address) + //{ + // byte r = (byte)((color >> 0) & 0x3), g = (byte)((color >> 2) & 0x3), b = (byte)((color >> 4) & 0x3); + // buffer[address + 0] = (byte)((b << 6) | (b << 4) | (b << 2) | b); + // buffer[address + 1] = (byte)((g << 6) | (g << 4) | (g << 2) | g); + // buffer[address + 2] = (byte)((r << 6) | (r << 4) | (r << 2) | r); + // buffer[address + 3] = 0xFF; + //} + public static void RGB222toBGRA8888(int color, ref byte* buffer, int address) { byte r = (byte)((color >> 0) & 0x3), g = (byte)((color >> 2) & 0x3), b = (byte)((color >> 4) & 0x3); buffer[address + 0] = (byte)((b << 6) | (b << 4) | (b << 2) | b); @@ -18,7 +26,16 @@ namespace Essgee.Emulation buffer[address + 3] = 0xFF; } - public static void RGB444toBGRA8888(int color, ref byte[] buffer, int address) + //public static void RGB444toBGRA8888(int color, ref byte[] buffer, int address) + //{ + // byte r = (byte)((color >> 0) & 0xF), g = (byte)((color >> 4) & 0xF), b = (byte)((color >> 8) & 0xF); + // buffer[address + 0] = (byte)((b << 4) | b); + // buffer[address + 1] = (byte)((g << 4) | g); + // buffer[address + 2] = (byte)((r << 4) | r); + // buffer[address + 3] = 0xFF; + //} + + public unsafe static void RGB444toBGRA8888(int color, ref byte* buffer, int address) { byte r = (byte)((color >> 0) & 0xF), g = (byte)((color >> 4) & 0xF), b = (byte)((color >> 8) & 0xF); buffer[address + 0] = (byte)((b << 4) | b); diff --git a/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaGGVDP.cs b/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaGGVDP.cs index 695c175..bea4985 100644 --- a/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaGGVDP.cs +++ b/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaGGVDP.cs @@ -7,7 +7,7 @@ using static Essgee.Emulation.Utilities; namespace Essgee.Emulation.Video { /* Sega 315-5378, Game Gear */ - public class SegaGGVDP : SegaSMSVDP + public unsafe class SegaGGVDP : SegaSMSVDP { protected override int numTotalScanlines => NumTotalScanlinesNtsc; @@ -18,7 +18,8 @@ namespace Essgee.Emulation.Video public SegaGGVDP() : base() { - cram = new byte[0x40]; + //cram = new byte[0x40]; + cram_set = new byte[0x40]; } public override void Reset() @@ -41,26 +42,27 @@ namespace Essgee.Emulation.Video /* Create arrays */ screenUsage = new byte[numVisiblePixels * numVisibleScanlines]; - outputFramebuffer = new byte[Viewport.Width * Viewport.Height * 4]; + //outputFramebuffer = new byte[Viewport.Width * Viewport.Height * 4]; + outputFramebuffer_set = new byte[Viewport.Width * Viewport.Height * 4]; /* Update resolution/display timing */ UpdateResolution(); } - GCHandle? lasyRenderHandle; + //GCHandle? lasyRenderHandle; protected override void PrepareRenderScreen() { - // 固定数组,防止垃圾回收器移动它 - var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); - // 获取数组的指针 - IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); + //// 固定数组,防止垃圾回收器移动它 + //var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); + //// 获取数组的指针 + //IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); - var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, mFrameDataPtr); + var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, outputFramebuffer_Ptr); OnRenderScreen(eventArgs); eventArgs.Release(); - if (lasyRenderHandle != null) - lasyRenderHandle.Value.Free(); - lasyRenderHandle = bitmapcolorRect_handle; + //if (lasyRenderHandle != null) + // lasyRenderHandle.Value.Free(); + //lasyRenderHandle = bitmapcolorRect_handle; //OnRenderScreen(new RenderScreenEventArgs(Viewport.Width, Viewport.Height, outputFramebuffer.Clone() as byte[])); } @@ -92,7 +94,7 @@ namespace Essgee.Emulation.Video WriteColorToFramebuffer((ushort)(cram[cramAddress + 1] << 8 | cram[cramAddress]), address); } - protected override void WriteColorToFramebuffer(ushort colorValue, int address) + protected unsafe override void WriteColorToFramebuffer(ushort colorValue, int address) { RGB444toBGRA8888(colorValue, ref outputFramebuffer, address); } diff --git a/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaSMSVDP.cs b/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaSMSVDP.cs index 8ae8d57..59af3b6 100644 --- a/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaSMSVDP.cs +++ b/Assets/Plugins/Essgee.Unity/Emulation/Video/SegaSMSVDP.cs @@ -8,7 +8,7 @@ using static Essgee.Emulation.Utilities; namespace Essgee.Emulation.Video { /* Sega 315-5124 (Mark III, SMS) and 315-5246 (SMS 2); differences see 'VDPDIFF' comments */ - public class SegaSMSVDP : TMS99xxA + public unsafe class SegaSMSVDP : TMS99xxA { /* VDPDIFF: switch for Mk3/SMS1 vs SMS2/GG behavior; configurable via SetRevision, maybe still split into separate classes instead? */ protected VDPTypes vdpType = VDPTypes.Mk3SMS1; @@ -23,8 +23,27 @@ namespace Essgee.Emulation.Video public const int PortVCounter = 0x40; // 0x7E canonically, but mirrored across bus public const int PortHCounter = 0x41; // 0x7F canonically, but mirrored across bus - [StateRequired] - protected byte[] cram; + //[StateRequired] + //protected byte[] cram; + + #region //指针化 cram + static byte[] cram_src; + static GCHandle cram_handle; + public static byte* cram; + public static int cramLength; + public static bool cram_IsNull => cram == null; + public static byte[] cram_set + { + set + { + cram_handle.ReleaseGCHandle(); + cram_src = value; + cramLength = value.Length; + cram_src.GetObjectPtr(ref cram_handle, ref cram); + } + } + #endregion + [StateRequired] protected int vCounter, hCounter; @@ -330,8 +349,10 @@ namespace Essgee.Emulation.Video public SegaSMSVDP() : base() { - registers = new byte[0x0B]; - cram = new byte[0x20]; + //registers = new byte[0x0B]; + //cram = new byte[0x20]; + registers_set = new byte[0x0B]; + cram_set = new byte[0x20]; spriteBuffer = new (int Number, int Y, int X, int Pattern, int Attribute)[NumActiveScanlinesHigh][]; for (int i = 0; i < spriteBuffer.Length; i++) spriteBuffer[i] = new (int Number, int Y, int X, int Pattern, int Attribute)[NumSpritesPerLineMode4]; @@ -353,7 +374,8 @@ namespace Essgee.Emulation.Video WriteRegister(0x09, 0x00); WriteRegister(0x0A, 0xFF); - for (int i = 0; i < cram.Length; i++) cram[i] = 0; + //for (int i = 0; i < cram.Length; i++) cram[i] = 0; + for (int i = 0; i < cramLength; i++) cram[i] = 0; vCounter = hCounter = 0; lineInterruptCounter = registers[0x0A]; @@ -379,7 +401,8 @@ namespace Essgee.Emulation.Video /* Create arrays */ screenUsage = new byte[numVisiblePixels * numVisibleScanlines]; - outputFramebuffer = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; + //outputFramebuffer = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; + outputFramebuffer_set = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; /* Update resolution/display timing */ UpdateResolution(); @@ -439,20 +462,21 @@ namespace Essgee.Emulation.Video } } - GCHandle? lasyRenderHandle; + //GCHandle? lasyRenderHandle; protected override void PrepareRenderScreen() { // 固定数组,防止垃圾回收器移动它 - var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); - // 获取数组的指针 - IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); + //var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); + //var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer, GCHandleType.Pinned); + //// 获取数组的指针 + //IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); - var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, mFrameDataPtr); + var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, outputFramebuffer_Ptr); OnRenderScreen(eventArgs); eventArgs.Release(); - if (lasyRenderHandle != null) - lasyRenderHandle.Value.Free(); - lasyRenderHandle = bitmapcolorRect_handle; + //if (lasyRenderHandle != null) + // lasyRenderHandle.Value.Free(); + //lasyRenderHandle = bitmapcolorRect_handle; //OnRenderScreen(new RenderScreenEventArgs(numVisiblePixels, numVisibleScanlines, outputFramebuffer.Clone() as byte[])); } @@ -868,7 +892,7 @@ namespace Essgee.Emulation.Video WriteColorToFramebuffer(cram[((palette * 16) + color)], address); } - protected override void WriteColorToFramebuffer(ushort colorValue, int address) + protected unsafe override void WriteColorToFramebuffer(ushort colorValue, int address) { /* If not in Master System video mode, color value is index into legacy colormap */ if (!isBitM4Set) @@ -925,7 +949,8 @@ namespace Essgee.Emulation.Video protected override void WriteRegister(byte register, byte value) { - if (register < registers.Length) + //if (register < registers.Length) + if (register < registersLength) registers[register] = value; if (register == 0x00 || register == 0x01) diff --git a/Assets/Plugins/Essgee.Unity/Emulation/Video/TMS99xxA.cs b/Assets/Plugins/Essgee.Unity/Emulation/Video/TMS99xxA.cs index ac9471e..372c421 100644 --- a/Assets/Plugins/Essgee.Unity/Emulation/Video/TMS99xxA.cs +++ b/Assets/Plugins/Essgee.Unity/Emulation/Video/TMS99xxA.cs @@ -8,7 +8,7 @@ using static Essgee.Emulation.Utilities; namespace Essgee.Emulation.Video { /* Texas Instruments TMS99xxA family */ - public class TMS99xxA : IVideo + public unsafe class TMS99xxA : IVideo { public const int NumTotalScanlinesPal = 313; public const int NumTotalScanlinesNtsc = 262; @@ -48,13 +48,52 @@ namespace Essgee.Emulation.Video protected double clockRate, refreshRate; protected bool isPalChip; - [StateRequired] - protected byte[] registers, vram; + //[StateRequired] + //protected byte[] registers, vram; + + #region //指针化 registers + static byte[] registers_src; + static GCHandle registers_handle; + public static byte* registers; + public static int registersLength; + public static bool registers_IsNull => registers == null; + public static byte[] registers_set + { + set + { + registers_handle.ReleaseGCHandle(); + registers_src = value; + registersLength = value.Length; + registers_src.GetObjectPtr(ref registers_handle, ref registers); + } + } + #endregion + + #region //指针化 vram + static byte[] vram_src; + static GCHandle vram_handle; + public static byte* vram; + public static int vramLength; + public static bool vram_IsNull => vram == null; + public static byte[] vram_set + { + set + { + vram_handle.ReleaseGCHandle(); + vram_src = value; + vramLength = value.Length; + vram_src.GetObjectPtr(ref vram_handle, ref vram); + } + } + #endregion + [StateRequired] protected (int Number, int Y, int X, int Pattern, int Attribute)[][] spriteBuffer; - protected ushort vramMask16k => 0x3FFF; - protected ushort vramMask4k => 0x0FFF; + //protected ushort vramMask16k => 0x3FFF; + //protected ushort vramMask4k => 0x0FFF; + protected const ushort vramMask16k = 0x3FFF; + protected const ushort vramMask4k = 0x0FFF; [StateRequired] protected bool isSecondControlWrite; @@ -64,6 +103,7 @@ namespace Essgee.Emulation.Video protected byte readBuffer; protected byte codeRegister => (byte)((controlWord >> 14) & 0x03); + protected ushort addressRegister { get { return (ushort)(controlWord & 0x3FFF); } @@ -156,7 +196,29 @@ namespace Essgee.Emulation.Video [StateRequired] protected int cycleCount; - protected byte[] outputFramebuffer; + //protected byte[] outputFramebuffer; + + #region //指针化 outputFramebuffer + static byte[] outputFramebuffer_src; + static GCHandle outputFramebuffer_handle; + public static IntPtr outputFramebuffer_Ptr; + public static byte* outputFramebuffer; + public static int outputFramebufferLength; + public static bool outputFramebuffer_IsNull => outputFramebuffer == null; + public static byte[] outputFramebuffer_set + { + set + { + + outputFramebuffer_handle.ReleaseGCHandle(); + outputFramebuffer_src = value; + outputFramebufferLength = value.Length; + outputFramebuffer_src.GetObjectPtr(ref outputFramebuffer_handle, ref outputFramebuffer); + outputFramebuffer_Ptr = outputFramebuffer_handle.AddrOfPinnedObject(); + } + } + #endregion + protected int clockCyclesPerLine; @@ -171,8 +233,10 @@ namespace Essgee.Emulation.Video public TMS99xxA() { - registers = new byte[0x08]; - vram = new byte[0x4000]; + //registers = new byte[0x08]; + //vram = new byte[0x4000]; + registers_set = new byte[0x08]; + vram_set = new byte[0x4000]; spriteBuffer = new (int Number, int Y, int X, int Pattern, int Attribute)[NumActiveScanlines][]; for (int i = 0; i < spriteBuffer.Length; i++) spriteBuffer[i] = new (int Number, int Y, int X, int Pattern, int Attribute)[NumSpritesPerLine]; @@ -218,8 +282,10 @@ namespace Essgee.Emulation.Video public virtual void Reset() { - for (int i = 0; i < registers.Length; i++) registers[i] = 0; - for (int i = 0; i < vram.Length; i++) vram[i] = 0; + //for (int i = 0; i < registers.Length; i++) registers[i] = 0; + //for (int i = 0; i < vram.Length; i++) vram[i] = 0; + for (int i = 0; i < registersLength; i++) registers[i] = 0; + for (int i = 0; i < vramLength; i++) vram[i] = 0; for (int i = 0; i < spriteBuffer.Length; i++) for (int j = 0; j < spriteBuffer[i].Length; j++) @@ -266,7 +332,8 @@ namespace Essgee.Emulation.Video /* Create arrays */ screenUsage = new byte[numVisiblePixels * numVisibleScanlines]; - outputFramebuffer = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; + //outputFramebuffer = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; + outputFramebuffer_set = new byte[(numVisiblePixels * numVisibleScanlines) * 4]; /* Scanline parameters */ if (!isPalChip) @@ -337,19 +404,19 @@ namespace Essgee.Emulation.Video } } - GCHandle? lasyRenderHandle; + //GCHandle? lasyRenderHandle; protected virtual void PrepareRenderScreen() { - // 固定数组,防止垃圾回收器移动它 - var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); - // 获取数组的指针 - IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); - var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, mFrameDataPtr); + //// 固定数组,防止垃圾回收器移动它 + //var bitmapcolorRect_handle = GCHandle.Alloc(outputFramebuffer.Clone() as byte[], GCHandleType.Pinned); + //// 获取数组的指针 + //IntPtr mFrameDataPtr = bitmapcolorRect_handle.AddrOfPinnedObject(); + var eventArgs = RenderScreenEventArgs.Create(numVisiblePixels, numVisibleScanlines, outputFramebuffer_Ptr); OnRenderScreen(eventArgs); eventArgs.Release(); - if (lasyRenderHandle != null) - lasyRenderHandle.Value.Free(); - lasyRenderHandle = bitmapcolorRect_handle; + //if (lasyRenderHandle != null) + // lasyRenderHandle.Value.Free(); + //lasyRenderHandle = bitmapcolorRect_handle; //OnRenderScreen(new RenderScreenEventArgs(numVisiblePixels, numVisibleScanlines, outputFramebuffer.Clone() as byte[])); } diff --git a/Assets/Scripts/UEssgee.cs b/Assets/Scripts/UEssgee.cs index 564e863..d0388c7 100644 --- a/Assets/Scripts/UEssgee.cs +++ b/Assets/Scripts/UEssgee.cs @@ -44,7 +44,8 @@ public class Essgeeinit : MonoBehaviour uegResources = new UEGResources(); uegLog = new UEGLog(); InitAll(uegResources, Application.persistentDataPath); - LoadAndRunCartridge("G:/Ninja_Gaiden_(UE)_type_A_[!].sms"); + LoadAndRunCartridge("G:/psjapa.sms"); + //LoadAndRunCartridge("G:/Ninja_Gaiden_(UE)_type_A_[!].sms"); //LoadAndRunCartridge("G:/SML2.gb"); } @@ -59,6 +60,8 @@ public class Essgeeinit : MonoBehaviour if (!emulatorHandler.IsRunning) return; mUniKeyboard.UpdateInputKey(); + + emulatorHandler.Update_Frame(); } void InitAll(IGameMetaReources metaresources,string CustonDataDir) @@ -343,6 +346,7 @@ public class Essgeeinit : MonoBehaviour private void LoadAndRunCartridge(string fileName) { + //Application.targetFrameRate = 60; try { var (machineType, romData) = CartridgeLoader.Load(fileName, "ROM image"); diff --git a/Assets/Scripts/UEssgeeInterface/UEGMouse.cs b/Assets/Scripts/UEssgeeInterface/UEGMouse.cs new file mode 100644 index 0000000..1c64b41 --- /dev/null +++ b/Assets/Scripts/UEssgeeInterface/UEGMouse.cs @@ -0,0 +1,23 @@ +//using MAME.Core; +//using UnityEngine; + +//public class UEGMouse : MonoBehaviour, IMouse +//{ +// static int mX, mY; +// public byte[] buttons = new byte[2]; +// void Update() +// { +// mX = (int)Input.mousePosition.x; +// mY = (int)Input.mousePosition.y; +// buttons[0] = Input.GetMouseButton(0) ? (byte)1 : (byte)0; +// buttons[1] = Input.GetMouseButton(1) ? (byte)1 : (byte)0; +// } + +// public void MouseXY(out int X, out int Y, out byte[] MouseButtons) +// { +// X = mX; +// Y = mY * -1; +// MouseButtons = buttons; +// } + +//} diff --git a/Assets/Scripts/UEssgeeInterface/UEGMouse.cs.meta b/Assets/Scripts/UEssgeeInterface/UEGMouse.cs.meta new file mode 100644 index 0000000..dfd24b9 --- /dev/null +++ b/Assets/Scripts/UEssgeeInterface/UEGMouse.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0e566345b50ca464fb8bd492a22c043b \ No newline at end of file diff --git a/Assets/Scripts/UEssgeeInterface/UEGSoundPlayer.cs b/Assets/Scripts/UEssgeeInterface/UEGSoundPlayer.cs index 53f0800..567c273 100644 --- a/Assets/Scripts/UEssgeeInterface/UEGSoundPlayer.cs +++ b/Assets/Scripts/UEssgeeInterface/UEGSoundPlayer.cs @@ -13,8 +13,8 @@ public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer void Awake() { - //AudioClip dummy = AudioClip.Create("dummy", 1, 2, AudioSettings.outputSampleRate, false); - AudioClip dummy = AudioClip.Create("dummy", 1, 2, 44100, false); + AudioClip dummy = AudioClip.Create("dummy", 1, 2, AudioSettings.outputSampleRate, false); + //AudioClip dummy = AudioClip.Create("dummy", 1, 2, 44100, false); dummy.SetData(new float[] { 1, 1 }, 0); m_as.clip = dummy; m_as.loop = true; @@ -74,7 +74,9 @@ public class UEGSoundPlayer : MonoBehaviour//, ISoundPlayer for (int i = 0; i < samples_a; i += 2) { - _buffer.Write(buffer[i] / 32767.0f); + //_buffer.Write(buffer[i] / 32767.0f); + float data = (uint)(buffer[i] + 32767); + _buffer.Write(data / ushort.MaxValue); //_buffer.Write(buffer[i] / 32767.0f); } } diff --git a/Assets/Scripts/UEssgeeInterface/UniMouse.cs.meta b/Assets/Scripts/UEssgeeInterface/UniMouse.cs.meta index dfd24b9..b9168f8 100644 --- a/Assets/Scripts/UEssgeeInterface/UniMouse.cs.meta +++ b/Assets/Scripts/UEssgeeInterface/UniMouse.cs.meta @@ -1,2 +1,2 @@ fileFormatVersion: 2 -guid: 0e566345b50ca464fb8bd492a22c043b \ No newline at end of file +guid: d5855fd9c3285e144b7db2b76cf55d77 \ No newline at end of file