IEmuCore 推帧,跳帧抽象,不再需要IEmuCore依赖monobehaviour的update推帧
This commit is contained in:
parent
5ae970673a
commit
1090fb4da7
@ -1,3 +1,7 @@
|
|||||||
|
using AxibugEmuOnline.Client;
|
||||||
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
|
using AxibugEmuOnline.Client.Network;
|
||||||
|
using AxibugProtobuf;
|
||||||
using AxiReplay;
|
using AxiReplay;
|
||||||
using MAME.Core;
|
using MAME.Core;
|
||||||
using System;
|
using System;
|
||||||
@ -6,13 +10,6 @@ using System.IO;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using AxibugEmuOnline.Client;
|
|
||||||
using AxibugEmuOnline.Client.ClientCore;
|
|
||||||
using AxibugProtobuf;
|
|
||||||
using static AxibugEmuOnline.Client.NesControllerMapper;
|
|
||||||
using VirtualNes.Core;
|
|
||||||
using System.Linq;
|
|
||||||
using AxibugEmuOnline.Client.Event;
|
|
||||||
|
|
||||||
public class UMAME : MonoBehaviour, IEmuCore
|
public class UMAME : MonoBehaviour, IEmuCore
|
||||||
{
|
{
|
||||||
@ -49,9 +46,9 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//设为60帧
|
//设为60帧
|
||||||
Application.targetFrameRate = 60;
|
Application.targetFrameRate = 120;
|
||||||
// 强制横屏
|
// 强制横屏
|
||||||
Screen.orientation = ScreenOrientation.LandscapeLeft;
|
Screen.orientation = ScreenOrientation.LandscapeLeft;
|
||||||
instance = this;
|
instance = this;
|
||||||
mFPS = GameObject.Find("FPS").GetComponent<Text>();
|
mFPS = GameObject.Find("FPS").GetComponent<Text>();
|
||||||
@ -75,7 +72,7 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
{
|
{
|
||||||
StopGame();
|
StopGame();
|
||||||
}
|
}
|
||||||
#region 实现接口
|
#region 实现接口
|
||||||
public object GetState()
|
public object GetState()
|
||||||
{
|
{
|
||||||
return SaveState();
|
return SaveState();
|
||||||
@ -107,7 +104,7 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
if (LoadGame(romFile.FileName, false))
|
if (LoadGame(romFile.FileName, false))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return "Rom加载失败";
|
return "Rom加载失败";
|
||||||
}
|
}
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
@ -130,9 +127,9 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
mReplayWriter = new ReplayWriter(mChangeRomName, "fuck", ReplayData.ReplayFormat.FM32IP64, Encoding.UTF8);
|
mReplayWriter = new ReplayWriter(mChangeRomName, "fuck", ReplayData.ReplayFormat.FM32IP64, Encoding.UTF8);
|
||||||
mChangeRomName = loadRom;
|
mChangeRomName = loadRom;
|
||||||
StopGame();
|
StopGame();
|
||||||
//读取ROM
|
//读取ROM
|
||||||
emu.LoadRom(mChangeRomName);
|
emu.LoadRom(mChangeRomName);
|
||||||
//读取成功
|
//读取成功
|
||||||
if (emu.bRom)
|
if (emu.bRom)
|
||||||
{
|
{
|
||||||
if (bReplay)
|
if (bReplay)
|
||||||
@ -142,14 +139,14 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
mUniKeyboard.SetRePlay(true);
|
mUniKeyboard.SetRePlay(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//读取ROM之后获得宽高初始化画面
|
//读取ROM之后获得宽高初始化画面
|
||||||
int _width; int _height; IntPtr _framePtr;
|
int _width; int _height; IntPtr _framePtr;
|
||||||
emu.GetGameScreenSize(out _width, out _height, out _framePtr);
|
emu.GetGameScreenSize(out _width, out _height, out _framePtr);
|
||||||
App.log.Debug($"_width->{_width}, _height->{_height}, _framePtr->{_framePtr}");
|
App.log.Debug($"_width->{_width}, _height->{_height}, _framePtr->{_framePtr}");
|
||||||
mUniVideoPlayer.Initialize(_width, _height, _framePtr);
|
mUniVideoPlayer.Initialize(_width, _height, _framePtr);
|
||||||
//初始化音频
|
//初始化音频
|
||||||
mUniSoundPlayer.Initialize();
|
mUniSoundPlayer.Initialize();
|
||||||
//开始游戏
|
//开始游戏
|
||||||
emu.StartGame();
|
emu.StartGame();
|
||||||
bInGame = true;
|
bInGame = true;
|
||||||
bLogicUpdatePause = true;
|
bLogicUpdatePause = true;
|
||||||
@ -157,48 +154,29 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
App.log.Debug($"ROM加载失败");
|
App.log.Debug($"ROM加载失败");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
if (!bInGame)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (bLogicUpdatePause)
|
public bool PushEmulatorFrame()
|
||||||
{
|
{
|
||||||
PushEmulatorFrame();
|
if (!bInGame) return false;
|
||||||
if (InGameUI.Instance.IsNetPlay)
|
if (!bLogicUpdatePause) return false;
|
||||||
FixEmulatorFrame();
|
|
||||||
}
|
//采集本帧Input
|
||||||
mUniVideoPlayer.ApplyFilterEffect();
|
|
||||||
mUniVideoPlayer.ApplyScreenScaler();
|
|
||||||
|
|
||||||
mFPS.text = ($"fpsv {mUniVideoPlayer.videoFPS.ToString("F2")} fpsa {mUniSoundPlayer.audioFPS.ToString("F2")} ,Idx:{App.roomMgr.netReplay?.mCurrClientFrameIdx},RIdx:{App.roomMgr.netReplay?.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay?.mRemoteForwardCount} ,RD:{App.roomMgr.netReplay?.mRemoteForwardCount} ,D:{App.roomMgr.netReplay?.mDiffFrameCount} ,Q:{App.roomMgr.netReplay?.mNetReplayQueue.Count}");
|
|
||||||
}
|
|
||||||
|
|
||||||
//是否跳帧,单机无效
|
|
||||||
void FixEmulatorFrame()
|
|
||||||
{
|
|
||||||
var skipFrameCount = App.roomMgr.netReplay.GetSkipFrameCount();
|
|
||||||
if (skipFrameCount > 0) App.log.Debug($"SKIP FRAME : {skipFrameCount} ,CF:{App.roomMgr.netReplay.mCurrClientFrameIdx},RFIdx:{App.roomMgr.netReplay.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay.mRemoteForwardCount} ,queue:{App.roomMgr.netReplay.mNetReplayQueue.Count}");
|
|
||||||
for (var i = 0; i < skipFrameCount; i++)
|
|
||||||
if (!PushEmulatorFrame())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PushEmulatorFrame()
|
|
||||||
{
|
|
||||||
//采集本帧Input
|
|
||||||
bool bhadNext = mUniKeyboard.SampleInput();
|
bool bhadNext = mUniKeyboard.SampleInput();
|
||||||
//如果未收到Input数据,核心帧不推进
|
//如果未收到Input数据,核心帧不推进
|
||||||
if (!bhadNext) return false;
|
if (!bhadNext) return false;
|
||||||
//放行下一帧
|
//放行下一帧
|
||||||
//emu.UnlockNextFreme();
|
//emu.UnlockNextFreme();
|
||||||
//推帧
|
//推帧
|
||||||
emu.UpdateFrame();
|
emu.UpdateFrame();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
public void AfterPushFrame()
|
||||||
|
{
|
||||||
|
mFPS.text = ($"fpsv {mUniVideoPlayer.videoFPS.ToString("F2")} fpsa {mUniSoundPlayer.audioFPS.ToString("F2")} ,Idx:{App.roomMgr.netReplay?.mCurrClientFrameIdx},RIdx:{App.roomMgr.netReplay?.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay?.mRemoteForwardCount} ,RD:{App.roomMgr.netReplay?.mRemoteForwardCount} ,D:{App.roomMgr.netReplay?.mDiffFrameCount} ,Q:{App.roomMgr.netReplay?.mNetReplayQueue.Count}");
|
||||||
}
|
}
|
||||||
public void SaveReplay()
|
public void SaveReplay()
|
||||||
{
|
{
|
||||||
@ -245,5 +223,11 @@ public class UMAME : MonoBehaviour, IEmuCore
|
|||||||
emu.LoadState(br);
|
emu.LoadState(br);
|
||||||
br.Close();
|
br.Close();
|
||||||
fs.Close();
|
fs.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Texture OutputPixel => mUniVideoPlayer.rawBufferWarper;
|
||||||
|
|
||||||
|
public RawImage DrawCanvas => mUniVideoPlayer.DrawCanvas;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
using MAME.Core;
|
using MAME.Core;
|
||||||
using System;
|
using System;
|
||||||
@ -24,6 +24,9 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
|
|||||||
public ulong mFrame { get; private set; }
|
public ulong mFrame { get; private set; }
|
||||||
bool bInit = false;
|
bool bInit = false;
|
||||||
|
|
||||||
|
public Texture2D rawBufferWarper => m_rawBufferWarper;
|
||||||
|
public RawImage DrawCanvas => m_drawCanvas;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
mFrame = 0;
|
mFrame = 0;
|
||||||
@ -31,7 +34,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
|
|||||||
m_drawCanvasrect = m_drawCanvas.GetComponent<RectTransform>();
|
m_drawCanvasrect = m_drawCanvas.GetComponent<RectTransform>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(int width, int height,IntPtr framePtr)
|
public void Initialize(int width, int height, IntPtr framePtr)
|
||||||
{
|
{
|
||||||
m_drawCanvas.color = Color.white;
|
m_drawCanvas.color = Color.white;
|
||||||
|
|
||||||
@ -40,7 +43,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
|
|||||||
mScreenSize = new Vector2Int(width, height);
|
mScreenSize = new Vector2Int(width, height);
|
||||||
mDataLenght = width * height * 4;
|
mDataLenght = width * height * 4;
|
||||||
//mFrameData = new int[mWidth * mHeight];
|
//mFrameData = new int[mWidth * mHeight];
|
||||||
//MAME来的是BGRA32,好好好 BGRA->RGBA
|
//MAME来的是BGRA32,好好好 BGRA->RGBA
|
||||||
m_rawBufferWarper = new Texture2D(mScreenSize.x, mScreenSize.y, TextureFormat.RGBA32, false);
|
m_rawBufferWarper = new Texture2D(mScreenSize.x, mScreenSize.y, TextureFormat.RGBA32, false);
|
||||||
m_rawBufferWarper.filterMode = FilterMode.Point;
|
m_rawBufferWarper.filterMode = FilterMode.Point;
|
||||||
}
|
}
|
||||||
@ -56,7 +59,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
|
|||||||
public void StopVideo()
|
public void StopVideo()
|
||||||
{
|
{
|
||||||
bInit = false;
|
bInit = false;
|
||||||
m_drawCanvas.color = new Color(0,0,0,0);
|
m_drawCanvas.color = new Color(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//void Update()
|
//void Update()
|
||||||
|
@ -6,6 +6,7 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using VirtualNes.Core;
|
using VirtualNes.Core;
|
||||||
using VirtualNes.Core.Debug;
|
using VirtualNes.Core.Debug;
|
||||||
|
|
||||||
@ -38,25 +39,6 @@ namespace AxibugEmuOnline.Client
|
|||||||
AudioProvider.NesEmu = this;
|
AudioProvider.NesEmu = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unity的逐帧驱动
|
|
||||||
/// </summary>
|
|
||||||
private unsafe void Update()
|
|
||||||
{
|
|
||||||
if (NesCore != null && !IsPause)
|
|
||||||
{
|
|
||||||
PushEmulatorFrame();
|
|
||||||
if (InGameUI.Instance.IsNetPlay)
|
|
||||||
FixEmulatorFrame();
|
|
||||||
|
|
||||||
var screenBuffer = NesCore.ppu.GetScreenPtr();
|
|
||||||
VideoProvider.SetDrawData(screenBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoProvider.ApplyScreenScaler();
|
|
||||||
VideoProvider.ApplyFilterEffect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public RomPlatformType Platform => RomPlatformType.Nes;
|
public RomPlatformType Platform => RomPlatformType.Nes;
|
||||||
private CoreSupporter m_coreSupporter;
|
private CoreSupporter m_coreSupporter;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -148,20 +130,11 @@ namespace AxibugEmuOnline.Client
|
|||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
private ControllerState m_lastState;
|
private ControllerState m_lastState;
|
||||||
#endif
|
#endif
|
||||||
//是否跳帧,单机无效
|
|
||||||
private void FixEmulatorFrame()
|
|
||||||
{
|
|
||||||
var skipFrameCount = App.roomMgr.netReplay.GetSkipFrameCount();
|
|
||||||
|
|
||||||
if (skipFrameCount > 0) App.log.Debug($"SKIP FRAME : {skipFrameCount}");
|
|
||||||
for (var i = 0; i < skipFrameCount; i++)
|
|
||||||
if (!PushEmulatorFrame())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//推进帧
|
//推进帧
|
||||||
private bool PushEmulatorFrame()
|
public bool PushEmulatorFrame()
|
||||||
{
|
{
|
||||||
|
if (NesCore == null || IsPause) return false;
|
||||||
|
|
||||||
m_coreSupporter.SampleInput(NesCore.FrameCount);
|
m_coreSupporter.SampleInput(NesCore.FrameCount);
|
||||||
var controlState = m_coreSupporter.GetControllerState();
|
var controlState = m_coreSupporter.GetControllerState();
|
||||||
|
|
||||||
@ -178,9 +151,15 @@ namespace AxibugEmuOnline.Client
|
|||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public unsafe void AfterPushFrame()
|
||||||
|
{
|
||||||
|
var screenBuffer = NesCore.ppu.GetScreenPtr();
|
||||||
|
VideoProvider.SetDrawData(screenBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IControllerSetuper GetControllerSetuper()
|
public IControllerSetuper GetControllerSetuper()
|
||||||
{
|
{
|
||||||
return ControllerMapper;
|
return ControllerMapper;
|
||||||
@ -219,7 +198,11 @@ namespace AxibugEmuOnline.Client
|
|||||||
|
|
||||||
UnityEditor.EditorUtility.SetDirty(db);
|
UnityEditor.EditorUtility.SetDirty(db);
|
||||||
UnityEditor.AssetDatabase.SaveAssets();
|
UnityEditor.AssetDatabase.SaveAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Texture OutputPixel => VideoProvider.OutputPixel;
|
||||||
|
public RawImage DrawCanvas => VideoProvider.Drawer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,9 @@ namespace AxibugEmuOnline.Client
|
|||||||
{
|
{
|
||||||
public class VideoProvider : MonoBehaviour
|
public class VideoProvider : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
public RenderTexture OutputPixel => rt_gpu;
|
||||||
|
public RawImage Drawer => Image;
|
||||||
|
|
||||||
#region UI_REF
|
#region UI_REF
|
||||||
public NesEmulator NesEmu;
|
public NesEmulator NesEmu;
|
||||||
public Canvas DrawCanvas;
|
public Canvas DrawCanvas;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
@ -34,6 +35,12 @@ namespace AxibugEmuOnline.Client
|
|||||||
RomPlatformType Platform { get; }
|
RomPlatformType Platform { get; }
|
||||||
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
|
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
|
||||||
uint Frame { get; }
|
uint Frame { get; }
|
||||||
|
/// <summary> 模拟器核心推帧 </summary>
|
||||||
|
bool PushEmulatorFrame();
|
||||||
|
/// <summary> 模拟器核心推帧结束 </summary>
|
||||||
|
void AfterPushFrame();
|
||||||
|
Texture OutputPixel { get; }
|
||||||
|
RawImage DrawCanvas { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IEnumCoreTool
|
public static class IEnumCoreTool
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugEmuOnline.Client.Common;
|
using AxibugEmuOnline.Client.Common;
|
||||||
using AxibugEmuOnline.Client.Network;
|
using AxibugEmuOnline.Client.Network;
|
||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client.Network
|
namespace AxibugEmuOnline.Client.Network
|
||||||
{
|
{
|
||||||
@ -76,7 +77,6 @@ namespace AxibugEmuOnline.Client.Network
|
|||||||
{
|
{
|
||||||
while (queueNetMsg.Count > 0)
|
while (queueNetMsg.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
var msgData = queueNetMsg.Dequeue();
|
var msgData = queueNetMsg.Dequeue();
|
||||||
PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3);
|
PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugEmuOnline.Client.Event;
|
using AxibugEmuOnline.Client.Event;
|
||||||
|
using AxibugEmuOnline.Client.Network;
|
||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -51,6 +52,36 @@ namespace AxibugEmuOnline.Client
|
|||||||
base.Awake();
|
base.Awake();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
PushCoreFrame();
|
||||||
|
|
||||||
|
App.settings.Filter.ExecuteFilterRender(Core.OutputPixel, Core.DrawCanvas);
|
||||||
|
App.settings.ScreenScaler.CalcScale(Core.DrawCanvas, Core.Platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushCoreFrame()
|
||||||
|
{
|
||||||
|
if (Core.IsNull()) return;
|
||||||
|
//fluash netMsg
|
||||||
|
NetMsg.Instance.DequeueNesMsg();
|
||||||
|
|
||||||
|
if (!Core.PushEmulatorFrame()) return;
|
||||||
|
|
||||||
|
if (IsNetPlay) //skip frame handle
|
||||||
|
{
|
||||||
|
var skipFrameCount = App.roomMgr.netReplay.GetSkipFrameCount();
|
||||||
|
if (skipFrameCount > 0) App.log.Debug($"SKIP FRAME : {skipFrameCount} ,CF:{App.roomMgr.netReplay.mCurrClientFrameIdx},RFIdx:{App.roomMgr.netReplay.mRemoteFrameIdx},RForward:{App.roomMgr.netReplay.mRemoteForwardCount} ,queue:{App.roomMgr.netReplay.mNetReplayQueue.Count}");
|
||||||
|
for (var i = 0; i < skipFrameCount; i++)
|
||||||
|
if (!Core.PushEmulatorFrame())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core.AfterPushFrame();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnDestroy()
|
protected override void OnDestroy()
|
||||||
{
|
{
|
||||||
Instance = null;
|
Instance = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user