Update推帧,sms部分指针化
This commit is contained in:
parent
572aa7d732
commit
bf0acee294
169
Assets/Plugins/Essgee.Unity/AxiMemory.cs
Normal file
169
Assets/Plugins/Essgee.Unity/AxiMemory.cs
Normal file
@ -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<GCHandle> GCHandles = new HashSet<GCHandle>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
2
Assets/Plugins/Essgee.Unity/AxiMemory.cs.meta
Normal file
2
Assets/Plugins/Essgee.Unity/AxiMemory.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 922bbb45b85e7de4f8bce1c6f407009f
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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[]));
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
23
Assets/Scripts/UEssgeeInterface/UEGMouse.cs
Normal file
23
Assets/Scripts/UEssgeeInterface/UEGMouse.cs
Normal file
@ -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;
|
||||
// }
|
||||
|
||||
//}
|
2
Assets/Scripts/UEssgeeInterface/UEGMouse.cs.meta
Normal file
2
Assets/Scripts/UEssgeeInterface/UEGMouse.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e566345b50ca464fb8bd492a22c043b
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e566345b50ca464fb8bd492a22c043b
|
||||
guid: d5855fd9c3285e144b7db2b76cf55d77
|
Loading…
Reference in New Issue
Block a user