diff --git a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs
index f7656a0e..ce7a74b7 100644
--- a/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs
+++ b/AxibugEmuOnline.Client/Assets/Plugins/AxiReplay/NetReplay.cs
@@ -65,7 +65,7 @@ namespace AxiReplay
frameProfiler.InputHead(inputData.FrameStartID);
}
- public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff)
+ public bool TryGetNextFrame(int targetFrame, bool indirectGet, out ReplayStep data, out int frameDiff, out bool inputDiff)
{
if (!bNetInit)
{
@@ -74,37 +74,27 @@ namespace AxiReplay
inputDiff = false;
return false;
}
- TakeFrame(1, out data, out frameDiff, out inputDiff);
- return frameDiff > 0;
+ return TakeFrameToTargetFrame(targetFrame, indirectGet, out data, out frameDiff, out inputDiff);
}
- public bool TryGetNextFrame(int targetFrame, out ReplayStep data, out int frameDiff, out bool inputDiff)
- {
- if (!bNetInit)
- {
- data = default(ReplayStep);
- frameDiff = default(int);
- inputDiff = false;
- return false;
- }
- return TakeFrameToTargetFrame(targetFrame, out data, out frameDiff, out inputDiff);
+ bool checkCanGetFrame(int targetFrame, bool indirectGet)
+ {
+ if (indirectGet)
+ {
+ return targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx;
+ }
+ else
+ {
+ return targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= frameProfiler.TempFrameCount(mRemoteForwardCount);
+ }
}
- void TakeFrame(int addFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
- {
- int targetFrame = mCurrClientFrameIdx + addFrame;
- TakeFrameToTargetFrame(targetFrame, out data, out bFrameDiff, out inputDiff);
- }
-
- bool TakeFrameToTargetFrame(int targetFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
+ bool TakeFrameToTargetFrame(int targetFrame, bool indirectGet, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
{
bool result;
inputDiff = false;
-
- //if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0)
- //if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= mRemoteForwardCount)
- if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count >= frameProfiler.TempFrameCount(mRemoteForwardCount))
+ if (checkCanGetFrame(targetFrame, indirectGet))
{
//当前帧追加
mCurrClientFrameIdx = targetFrame;
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/IEmuCore.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs
similarity index 56%
rename from AxibugEmuOnline.Client/Assets/Script/AppMain/IEmuCore.cs
rename to AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs
index 1be8dfe4..ef893e45 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/IEmuCore.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs
@@ -1,19 +1,14 @@
-#pragma warning disable CS0618 // 类型或成员已过时
-
-using AxibugEmuOnline.Client.ClientCore;
+using AxibugEmuOnline.Client.ClientCore;
using AxibugProtobuf;
using AxiReplay;
using System;
using UnityEngine;
+using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;
namespace AxibugEmuOnline.Client
-{
- ///
- /// use instead
- ///
- [Obsolete("不可直接继承,需要继承EmuCore类型")]
- public abstract class IEmuCore : MonoBehaviour
+{
+ public abstract class EmuCore : MonoBehaviour
{
/// 获得模拟器核心中的状态快照对象
public abstract object GetState();
@@ -43,62 +38,101 @@ namespace AxibugEmuOnline.Client
/// 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0
public abstract uint Frame { get; }
- public abstract bool PushEmulatorFrame();
+ public abstract void PushEmulatorFrame();
/// 模拟器核心推帧结束
- public abstract void AfterPushFrame();
+ protected abstract void AfterPushFrame();
public abstract void GetAudioParams(out int frequency, out int channels);
public abstract Texture OutputPixel { get; }
- public abstract RawImage DrawCanvas { get; }
+ public abstract RawImage DrawCanvas { get; }
+
+
+ /// 指示该游戏实例是否处于联机模式
+ public bool IsNetPlay
+ {
+ get
+ {
+ if (!App.user.IsLoggedIn) return false;
+ if (App.roomMgr.mineRoomMiniInfo == null) return false;
+ if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false;
+
+ return true;
+ }
+ }
}
- public abstract class EmuCore : IEmuCore
+ /// 输入数据类型
+ public abstract class EmuCore : EmuCore
{
- public sealed override bool PushEmulatorFrame()
+ protected virtual bool EnableRollbackNetCode => false;
+
+ public sealed override void PushEmulatorFrame()
+ {
+ if (!TryPushEmulatorFrame()) 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 (!TryPushEmulatorFrame()) break;
+ }
+ }
+
+ AfterPushFrame();
+ }
+
+ bool TryPushEmulatorFrame()
{
if (SampleInputData(out var inputData))
{
+ if (IsNetPlay) SendLocalInput();
+
return OnPushEmulatorFrame(inputData);
}
return false;
}
+ private void SendLocalInput()
+ {
+ var localState = GetLocalInput();
+ var rawData = InputDataToNet(localState);
+ App.roomMgr.SendRoomSingelPlayerInput(Frame, rawData);
+
+ if (m_lastTestInput != rawData)
+ {
+ m_lastTestInput = rawData;
+ App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
+ }
+ }
+
ulong m_lastTestInput;
+ ReplayStep m_replayData;
+ int m_frameDiff;
+ bool m_inputDiff;
protected bool SampleInputData(out INPUTDATA inputData)
{
bool result = false;
inputData = default(INPUTDATA);
- if (InGameUI.Instance.IsNetPlay)
+ if (IsNetPlay)
{
- ReplayStep replayData;
- int frameDiff;
- bool inputDiff;
-
- if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, out replayData, out frameDiff, out inputDiff))
- {
- if (inputDiff)
- {
- App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{frameDiff} " +
- $"frame=>{replayData.FrameStartID} InPut=>{replayData.InPut}");
+ if (App.roomMgr.netReplay.TryGetNextFrame((int)Frame, EnableRollbackNetCode ? true : false, out m_replayData, out m_frameDiff, out m_inputDiff))
+ {
+ if (m_inputDiff)
+ {
+ App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} TryGetNextFrame remoteFrame->{App.roomMgr.netReplay.mRemoteFrameIdx} diff->{m_frameDiff} " +
+ $"frame=>{m_replayData.FrameStartID} InPut=>{m_replayData.InPut}");
}
- inputData = ConvertInputDataFromNet(replayData);
+ inputData = ConvertInputDataFromNet(m_replayData);
result = true;
}
else
{
result = false;
}
-
- var localState = GetLocalInput();
- var rawData = InputDataToNet(localState);
- if (m_lastTestInput != rawData)
- {
- m_lastTestInput = rawData;
- App.log.Debug($"{DateTime.Now.ToString("hh:mm:ss.fff")} Input F:{App.roomMgr.netReplay.mCurrClientFrameIdx} | I:{rawData}");
- }
- App.roomMgr.SendRoomSingelPlayerInput(Frame, rawData);
}
else//单机模式
{
@@ -116,4 +150,3 @@ namespace AxibugEmuOnline.Client
protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData);
}
}
-#pragma warning restore CS0618 // 类型或成员已过时
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/IEmuCore.cs.meta b/AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs.meta
similarity index 100%
rename from AxibugEmuOnline.Client/Assets/Script/AppMain/IEmuCore.cs.meta
rename to AxibugEmuOnline.Client/Assets/Script/AppMain/EmuCore.cs.meta
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs
index 69ef9530..4945f129 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/EssgeeEmulator/UEssgee.cs
@@ -167,7 +167,7 @@ public class UEssgee : EmuCore
return mUniKeyboard.DoLocalPressedKeys();
}
- public override void AfterPushFrame()
+ protected override void AfterPushFrame()
{
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs
index 253836be..13e0eb28 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UMAME.cs
@@ -179,7 +179,7 @@ public class UMAME : EmuCore
return mUniKeyboard.DoLocalPressedKeys();
}
- public override void AfterPushFrame()
+ protected override 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}");
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
index 92b63622..924701bb 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/MameEmulator/UniInterface/UniKeyboard.cs
@@ -65,7 +65,7 @@ public class UniKeyboard : MonoBehaviour, IKeyboard
public ulong GetPressedKeys()
{
- if (InGameUI.Instance.IsNetPlay)
+ if (InGameUI.Instance.Core.IsNetPlay)
return CurrRemoteInpuAllData;
else
return CurrLocalInpuAllData;
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs
index 69cf14d7..e5f8062b 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/NesEmulator/NesEmulator.cs
@@ -149,7 +149,7 @@ namespace AxibugEmuOnline.Client
}
- public override unsafe void AfterPushFrame()
+ protected override unsafe void AfterPushFrame()
{
var screenBuffer = NesCore.ppu.GetScreenPtr();
VideoProvider.SetDrawData(screenBuffer);
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs
index 7ec435cb..5d1705e3 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Emulator/StoicGooseEmulator/UStoicGoose.cs
@@ -145,7 +145,7 @@ public class UStoicGoose : EmuCore
throw new NotImplementedException();
}
- public override void AfterPushFrame()
+ protected override void AfterPushFrame()
{
throw new NotImplementedException();
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs
index d53608f6..52332280 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/Manager/AppEmu.cs
@@ -11,7 +11,7 @@ namespace AxibugEmuOnline.Client.Manager
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
///
- private IEmuCore m_emuCore;
+ private EmuCore m_emuCore;
private IControllerSetuper m_controllerSetuper;
@@ -19,7 +19,7 @@ namespace AxibugEmuOnline.Client.Manager
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
/// 但是Equals方法可以,所以,这个接口判断为空请使用Equals
///
- public IEmuCore Core => m_emuCore;
+ public EmuCore Core => m_emuCore;
public AppEmu()
{
@@ -53,14 +53,14 @@ namespace AxibugEmuOnline.Client.Manager
switch (romFile.Platform)
{
case RomPlatformType.Nes:
- m_emuCore = GameObject.Instantiate(Resources.Load("NES/NesEmulator")).GetComponent();
+ m_emuCore = GameObject.Instantiate(Resources.Load("NES/NesEmulator")).GetComponent();
break;
case RomPlatformType.Cps1:
case RomPlatformType.Cps2:
case RomPlatformType.Igs:
case RomPlatformType.Neogeo:
case RomPlatformType.ArcadeOld:
- m_emuCore = GameObject.Instantiate(Resources.Load("MAME/UMAME")).GetComponent();
+ m_emuCore = GameObject.Instantiate(Resources.Load("MAME/UMAME")).GetComponent();
break;
case RomPlatformType.MasterSystem:
case RomPlatformType.GameGear:
@@ -69,11 +69,11 @@ namespace AxibugEmuOnline.Client.Manager
case RomPlatformType.ColecoVision:
case RomPlatformType.Sc3000:
case RomPlatformType.Sg1000:
- m_emuCore = GameObject.Instantiate(Resources.Load("EssgeeUnity/EssgeeUnity")).GetComponent();
+ m_emuCore = GameObject.Instantiate(Resources.Load("EssgeeUnity/EssgeeUnity")).GetComponent();
break;
case RomPlatformType.WonderSwan:
case RomPlatformType.WonderSwanColor:
- m_emuCore = GameObject.Instantiate(Resources.Load("StoicGooseUnity/StoicGooseUnity")).GetComponent();
+ m_emuCore = GameObject.Instantiate(Resources.Load("StoicGooseUnity/StoicGooseUnity")).GetComponent();
break;
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs
index 6a8b0dea..3ed9dd31 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI.cs
@@ -20,20 +20,7 @@ namespace AxibugEmuOnline.Client
public override bool Enable => gameObject.activeInHierarchy;
- /// 指示该游戏实例是否处于联机模式
- public bool IsNetPlay
- {
- get
- {
- if (!App.user.IsLoggedIn) return false;
- if (App.roomMgr.mineRoomMiniInfo == null) return false;
- if (App.roomMgr.RoomState <= RoomGameState.OnlyHost) return false;
-
- return true;
- }
- }
-
- public IEmuCore Core { get; private set; }
+ public EmuCore Core { get; private set; }
protected override void Awake()
{
@@ -69,18 +56,7 @@ namespace AxibugEmuOnline.Client
//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();
+ Core.PushEmulatorFrame();
}
protected override void OnDestroy()
@@ -103,7 +79,7 @@ namespace AxibugEmuOnline.Client
return m_state;
}
- public void Show(RomFile currentRom, IEmuCore core)
+ public void Show(RomFile currentRom, EmuCore core)
{
m_delayCreateRoom = false;
m_state = null; //清空游戏快照
@@ -186,14 +162,14 @@ namespace AxibugEmuOnline.Client
{
OverlayManager.PopSideBar(menus, 0, PopMenu_OnHide);
- if (!IsNetPlay) //单人模式暂停模拟器
+ if (!Core.IsNetPlay) //单人模式暂停模拟器
Core.Pause();
}
//菜单关闭时候
private void PopMenu_OnHide()
{
- if (!IsNetPlay) //单人模式恢复模拟器的暂停
+ if (!Core.IsNetPlay) //单人模式恢复模拟器的暂停
Core.Resume();
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs
index b4b39e24..0fa39a39 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_LoadStateQuick.cs
@@ -3,7 +3,7 @@
public class InGameUI_LoadStateQuick : ExecuteMenu
{
private InGameUI m_gameUI;
- public override bool Visible => !m_gameUI.IsNetPlay && m_gameUI.GetQuickState() != null;
+ public override bool Visible => !m_gameUI.Core.IsNetPlay && m_gameUI.GetQuickState() != null;
public override string Name => "快速读取";
public InGameUI_LoadStateQuick(InGameUI gameUI)
@@ -13,7 +13,7 @@
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
{
- if (m_gameUI.IsNetPlay) return;
+ if (m_gameUI.Core.IsNetPlay) return;
object state = m_gameUI.GetQuickState();
if (state != null)
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs
index a804dd66..32db8a89 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_Reset.cs
@@ -6,7 +6,7 @@ namespace AxibugEmuOnline.Client
{
private InGameUI m_gameUI;
public override string Name => "复位";
- public override bool Visible => !m_gameUI.IsNetPlay || App.roomMgr.IsHost;
+ public override bool Visible => !m_gameUI.Core.IsNetPlay || App.roomMgr.IsHost;
public InGameUI_Reset(InGameUI gameUI)
{
@@ -15,7 +15,7 @@ namespace AxibugEmuOnline.Client
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
{
- if (!m_gameUI.IsNetPlay)
+ if (!m_gameUI.Core.IsNetPlay)
{
App.emu.ResetGame();
}
diff --git a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateQuick.cs b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateQuick.cs
index f8a51a1b..c8e5c506 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateQuick.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/AppMain/UI/InGameUI/InGameUI_SaveStateQuick.cs
@@ -7,7 +7,7 @@ namespace AxibugEmuOnline.Client
{
private InGameUI m_gameUI;
- public override bool Visible => !m_gameUI.IsNetPlay;
+ public override bool Visible => !m_gameUI.Core.IsNetPlay;
public override string Name => "快速保存";
public InGameUI_SaveStateQuick(InGameUI gameUI)
@@ -17,7 +17,7 @@ namespace AxibugEmuOnline.Client
public override void OnExcute(OptionUI optionUI, ref bool cancelHide)
{
- if (m_gameUI.IsNetPlay) return;
+ if (m_gameUI.Core.IsNetPlay) return;
Stopwatch sw = Stopwatch.StartNew();
object state = m_gameUI.Core.GetState();