IEmuCore 推帧,跳帧抽象,不再需要IEmuCore依赖monobehaviour的update推帧

This commit is contained in:
ALIENJACK\alien 2025-01-26 10:51:06 +08:00
parent 5ae970673a
commit 1090fb4da7
8 changed files with 101 additions and 90 deletions

View File

@ -1,3 +1,7 @@
using AxibugEmuOnline.Client;
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Network;
using AxibugProtobuf;
using AxiReplay;
using MAME.Core;
using System;
@ -6,13 +10,6 @@ using System.IO;
using System.Text;
using UnityEngine;
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
{
@ -49,9 +46,9 @@ public class UMAME : MonoBehaviour, IEmuCore
{
//设为60帧
Application.targetFrameRate = 60;
// 强制横屏
//设为60帧
Application.targetFrameRate = 120;
// 强制横屏
Screen.orientation = ScreenOrientation.LandscapeLeft;
instance = this;
mFPS = GameObject.Find("FPS").GetComponent<Text>();
@ -75,7 +72,7 @@ public class UMAME : MonoBehaviour, IEmuCore
{
StopGame();
}
#region
#region
public object GetState()
{
return SaveState();
@ -107,7 +104,7 @@ public class UMAME : MonoBehaviour, IEmuCore
if (LoadGame(romFile.FileName, false))
return true;
else
return "Rom加载失败";
return "Rom加载失败";
}
public void Dispose()
{
@ -130,9 +127,9 @@ public class UMAME : MonoBehaviour, IEmuCore
mReplayWriter = new ReplayWriter(mChangeRomName, "fuck", ReplayData.ReplayFormat.FM32IP64, Encoding.UTF8);
mChangeRomName = loadRom;
StopGame();
//读取ROM
//读取ROM
emu.LoadRom(mChangeRomName);
//读取成功
//读取成功
if (emu.bRom)
{
if (bReplay)
@ -142,14 +139,14 @@ public class UMAME : MonoBehaviour, IEmuCore
mUniKeyboard.SetRePlay(true);
}
//读取ROM之后获得宽高初始化画面
//读取ROM之后获得宽高初始化画面
int _width; int _height; IntPtr _framePtr;
emu.GetGameScreenSize(out _width, out _height, out _framePtr);
App.log.Debug($"_width->{_width}, _height->{_height}, _framePtr->{_framePtr}");
mUniVideoPlayer.Initialize(_width, _height, _framePtr);
//初始化音频
//初始化音频
mUniSoundPlayer.Initialize();
//开始游戏
//开始游戏
emu.StartGame();
bInGame = true;
bLogicUpdatePause = true;
@ -157,49 +154,30 @@ public class UMAME : MonoBehaviour, IEmuCore
}
else
{
App.log.Debug($"ROM加载失败");
App.log.Debug($"ROM加载失败");
return false;
}
}
void Update()
public bool PushEmulatorFrame()
{
if (!bInGame)
return;
if (!bInGame) return false;
if (!bLogicUpdatePause) return false;
if (bLogicUpdatePause)
{
PushEmulatorFrame();
if (InGameUI.Instance.IsNetPlay)
FixEmulatorFrame();
}
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
//采集本帧Input
bool bhadNext = mUniKeyboard.SampleInput();
//如果未收到Input数据,核心帧不推进
//如果未收到Input数据,核心帧不推进
if (!bhadNext) return false;
//放行下一帧
//放行下一帧
//emu.UnlockNextFreme();
//推帧
//推帧
emu.UpdateFrame();
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()
{
string Path = SavePath + Machine.sName + ".rp";
@ -246,4 +224,10 @@ public class UMAME : MonoBehaviour, IEmuCore
br.Close();
fs.Close();
}
public Texture OutputPixel => mUniVideoPlayer.rawBufferWarper;
public RawImage DrawCanvas => mUniVideoPlayer.DrawCanvas;
}

View File

@ -1,4 +1,4 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.ClientCore;
using AxibugProtobuf;
using MAME.Core;
using System;
@ -24,6 +24,9 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
public ulong mFrame { get; private set; }
bool bInit = false;
public Texture2D rawBufferWarper => m_rawBufferWarper;
public RawImage DrawCanvas => m_drawCanvas;
private void Awake()
{
mFrame = 0;
@ -31,7 +34,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
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;
@ -40,7 +43,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
mScreenSize = new Vector2Int(width, height);
mDataLenght = width * height * 4;
//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.filterMode = FilterMode.Point;
}
@ -56,7 +59,7 @@ public class UniVideoPlayer : MonoBehaviour, IVideoPlayer
public void StopVideo()
{
bInit = false;
m_drawCanvas.color = new Color(0,0,0,0);
m_drawCanvas.color = new Color(0, 0, 0, 0);
}
//void Update()

View File

@ -6,6 +6,7 @@ using System.Globalization;
using System.IO;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.UI;
using VirtualNes.Core;
using VirtualNes.Core.Debug;
@ -38,25 +39,6 @@ namespace AxibugEmuOnline.Client
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;
private CoreSupporter m_coreSupporter;
/// <summary>
@ -148,20 +130,11 @@ namespace AxibugEmuOnline.Client
#if UNITY_EDITOR
private ControllerState m_lastState;
#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);
var controlState = m_coreSupporter.GetControllerState();
@ -181,6 +154,12 @@ namespace AxibugEmuOnline.Client
}
public unsafe void AfterPushFrame()
{
var screenBuffer = NesCore.ppu.GetScreenPtr();
VideoProvider.SetDrawData(screenBuffer);
}
public IControllerSetuper GetControllerSetuper()
{
return ControllerMapper;
@ -220,6 +199,10 @@ namespace AxibugEmuOnline.Client
UnityEditor.EditorUtility.SetDirty(db);
UnityEditor.AssetDatabase.SaveAssets();
}
public Texture OutputPixel => VideoProvider.OutputPixel;
public RawImage DrawCanvas => VideoProvider.Drawer;
#endif
}
}

View File

@ -10,6 +10,9 @@ namespace AxibugEmuOnline.Client
{
public class VideoProvider : MonoBehaviour
{
public RenderTexture OutputPixel => rt_gpu;
public RawImage Drawer => Image;
#region UI_REF
public NesEmulator NesEmu;
public Canvas DrawCanvas;

View File

@ -1,5 +1,6 @@
using AxibugProtobuf;
using UnityEngine;
using UnityEngine.UI;
namespace AxibugEmuOnline.Client
{
@ -34,6 +35,12 @@ namespace AxibugEmuOnline.Client
RomPlatformType Platform { get; }
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
uint Frame { get; }
/// <summary> 模拟器核心推帧 </summary>
bool PushEmulatorFrame();
/// <summary> 模拟器核心推帧结束 </summary>
void AfterPushFrame();
Texture OutputPixel { get; }
RawImage DrawCanvas { get; }
}
public static class IEnumCoreTool

View File

@ -1,4 +1,4 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Common;
using AxibugEmuOnline.Client.Network;
using AxibugProtobuf;

View File

@ -2,6 +2,7 @@
using AxibugProtobuf;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AxibugEmuOnline.Client.Network
{
@ -76,7 +77,6 @@ namespace AxibugEmuOnline.Client.Network
{
while (queueNetMsg.Count > 0)
{
var msgData = queueNetMsg.Dequeue();
PostNetMsgEvent(msgData.Item1, msgData.Item2, msgData.Item3);
}

View File

@ -1,5 +1,6 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Event;
using AxibugEmuOnline.Client.Network;
using AxibugProtobuf;
using System;
using System.Collections.Generic;
@ -51,6 +52,36 @@ namespace AxibugEmuOnline.Client
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()
{
Instance = null;