master #51
@ -7,7 +7,7 @@ namespace AxiReplay
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 客户端当前帧
|
/// 客户端当前帧
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int mCurrClientFrameIdx => mCurrReplay.FrameStartID;
|
public int mCurrClientFrameIdx = int.MinValue;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 服务器远端当前帧
|
/// 服务器远端当前帧
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,6 +28,8 @@ namespace AxiReplay
|
|||||||
/// 下一个数据数据
|
/// 下一个数据数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ReplayStep mNextReplay;
|
ReplayStep mNextReplay;
|
||||||
|
|
||||||
|
bool bNetInit = false;
|
||||||
public NetReplay()
|
public NetReplay()
|
||||||
{
|
{
|
||||||
ResetData();
|
ResetData();
|
||||||
@ -35,28 +37,43 @@ namespace AxiReplay
|
|||||||
public void ResetData()
|
public void ResetData()
|
||||||
{
|
{
|
||||||
mNetReplayQueue.Clear();
|
mNetReplayQueue.Clear();
|
||||||
mRemoteFrameIdx = 0;
|
|
||||||
mCurrReplay = default(ReplayStep);
|
mCurrReplay = default(ReplayStep);
|
||||||
mCurrReplay.FrameStartID = int.MinValue;
|
mCurrReplay.FrameStartID = int.MinValue;
|
||||||
mNextReplay = default(ReplayStep);
|
bNetInit = false;
|
||||||
mNextReplay.FrameStartID = 0;
|
|
||||||
mRemoteFrameIdx = 0;
|
|
||||||
}
|
}
|
||||||
public void InData(ReplayStep inputData, int ServerFrameIdx)
|
public void InData(ReplayStep inputData, int ServerFrameIdx)
|
||||||
{
|
{
|
||||||
mNetReplayQueue.Enqueue(inputData);
|
mNetReplayQueue.Enqueue(inputData);
|
||||||
mRemoteFrameIdx = inputData.FrameStartID;
|
mRemoteFrameIdx = inputData.FrameStartID;
|
||||||
|
if (!bNetInit)
|
||||||
|
{
|
||||||
|
bNetInit = true;
|
||||||
|
mNextReplay = mNetReplayQueue.Dequeue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff)
|
public bool TryGetNextFrame(out ReplayStep data, out int frameDiff, out bool inputDiff)
|
||||||
{
|
{
|
||||||
|
if (!bNetInit)
|
||||||
|
{
|
||||||
|
data = default(ReplayStep);
|
||||||
|
frameDiff = default;
|
||||||
|
inputDiff = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TakeFrame(1, out data, out frameDiff, out inputDiff);
|
TakeFrame(1, out data, out frameDiff, out inputDiff);
|
||||||
return frameDiff > 0;
|
return frameDiff > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetNextFrame(int targetFrame, out ReplayStep data, out int frameDiff, out bool inputDiff)
|
public bool TryGetNextFrame(int targetFrame, out ReplayStep data, out int frameDiff, out bool inputDiff)
|
||||||
{
|
{
|
||||||
TakeFrameToTargetFrame(targetFrame, out data, out frameDiff, out inputDiff);
|
if (!bNetInit)
|
||||||
return frameDiff > 0;
|
{
|
||||||
|
data = default(ReplayStep);
|
||||||
|
frameDiff = default;
|
||||||
|
inputDiff = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return TakeFrameToTargetFrame(targetFrame, out data, out frameDiff, out inputDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TakeFrame(int addFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
|
void TakeFrame(int addFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
|
||||||
@ -65,21 +82,28 @@ namespace AxiReplay
|
|||||||
TakeFrameToTargetFrame(targetFrame, out data, out bFrameDiff, out inputDiff);
|
TakeFrameToTargetFrame(targetFrame, out data, out bFrameDiff, out inputDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TakeFrameToTargetFrame(int targetFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
|
bool TakeFrameToTargetFrame(int targetFrame, out ReplayStep data, out int bFrameDiff, out bool inputDiff)
|
||||||
{
|
{
|
||||||
|
bool result;
|
||||||
inputDiff = false;
|
inputDiff = false;
|
||||||
if (targetFrame <= mNextReplay.FrameStartID + 1 && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0)
|
if (targetFrame == mNextReplay.FrameStartID && targetFrame <= mRemoteFrameIdx && mNetReplayQueue.Count > 0)
|
||||||
{
|
{
|
||||||
//当前帧追加
|
//当前帧追加
|
||||||
|
mCurrClientFrameIdx = targetFrame;
|
||||||
ulong oldInput = mCurrReplay.InPut;
|
ulong oldInput = mCurrReplay.InPut;
|
||||||
mCurrReplay = mNextReplay;
|
mCurrReplay = mNextReplay;
|
||||||
if (oldInput != mCurrReplay.InPut)
|
if (oldInput != mCurrReplay.InPut)
|
||||||
inputDiff = true;
|
inputDiff = true;
|
||||||
mNextReplay = mNetReplayQueue.Dequeue();
|
mNextReplay = mNetReplayQueue.Dequeue();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
result = false;
|
||||||
|
|
||||||
bFrameDiff = mRemoteFrameIdx - mCurrClientFrameIdx;
|
bFrameDiff = mRemoteFrameIdx - mCurrClientFrameIdx;
|
||||||
data = mCurrReplay;
|
data = mCurrReplay;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ MonoImporter:
|
|||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: -80
|
||||||
icon: {instanceID: 0}
|
icon: {instanceID: 0}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
|
@ -99,11 +99,11 @@ namespace AxibugEmuOnline.Client
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint LastTestInput = 0;
|
uint LastTestInput = 0;
|
||||||
public void SampleInput()
|
public void SampleInput(uint frameIndex)
|
||||||
{
|
{
|
||||||
if (InGameUI.Instance.IsNetPlay)
|
if (InGameUI.Instance.IsNetPlay)
|
||||||
{
|
{
|
||||||
if (App.roomMgr.netReplay.TryGetNextFrame(out var replayData, out int frameDiff, out bool inputDiff))
|
if (App.roomMgr.netReplay.TryGetNextFrame((int)frameIndex, out var replayData, out int frameDiff, out bool inputDiff))
|
||||||
{
|
{
|
||||||
if (inputDiff)
|
if (inputDiff)
|
||||||
{
|
{
|
||||||
|
@ -84,17 +84,27 @@ namespace AxibugEmuOnline.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControllerState lastState;
|
||||||
private bool PushEmulatorFrame()
|
private bool PushEmulatorFrame()
|
||||||
{
|
{
|
||||||
Supporter.SampleInput();
|
Supporter.SampleInput(NesCore.FrameCount);
|
||||||
var controlState = Supporter.GetControllerState();
|
var controlState = Supporter.GetControllerState();
|
||||||
|
|
||||||
//如果未收到Input数据,核心帧不推进
|
//如果未收到Input数据,核心帧不推进
|
||||||
if (!controlState.valid) return false;
|
if (!controlState.valid) return false;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (controlState != lastState)
|
||||||
|
{
|
||||||
|
App.log.Info($"[LOCALDEBUG]{NesCore.FrameCount}-->{controlState}");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NesCore.pad.Sync(controlState);
|
NesCore.pad.Sync(controlState);
|
||||||
NesCore.EmulateFrame(true);
|
NesCore.EmulateFrame(true);
|
||||||
|
|
||||||
|
lastState = controlState;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,11 +459,9 @@ namespace VirtualNes.Core
|
|||||||
m_CheatCode.Clear();
|
m_CheatCode.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FrameCount = 0;
|
public uint FrameCount { get; private set; }
|
||||||
public void EmulateFrame(bool bDraw)
|
public void EmulateFrame(bool bDraw)
|
||||||
{
|
{
|
||||||
FrameCount++;
|
|
||||||
|
|
||||||
int scanline = 0;
|
int scanline = 0;
|
||||||
if (rom.IsNSF())
|
if (rom.IsNSF())
|
||||||
{
|
{
|
||||||
@ -772,6 +770,8 @@ namespace VirtualNes.Core
|
|||||||
{
|
{
|
||||||
DrawPad();
|
DrawPad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPad()
|
private void DrawPad()
|
||||||
@ -1901,6 +1901,7 @@ namespace VirtualNes.Core
|
|||||||
|
|
||||||
public void LoadState(State state)
|
public void LoadState(State state)
|
||||||
{
|
{
|
||||||
|
FrameCount = 0;
|
||||||
//HEADER
|
//HEADER
|
||||||
{
|
{
|
||||||
state.HEADER.ID = "VirtuaNES ST";
|
state.HEADER.ID = "VirtuaNES ST";
|
||||||
|
@ -24,6 +24,25 @@ namespace VirtualNes.Core
|
|||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(ControllerState left, ControllerState right)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
left.raw0 == right.raw0 &&
|
||||||
|
left.raw1 == right.raw1 &&
|
||||||
|
left.raw2 == right.raw2 &&
|
||||||
|
left.raw3 == right.raw3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(ControllerState left, ControllerState right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{raw0}|{raw1}|{raw2}|{raw3}";
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasButton(int player, EnumButtonType button)
|
public bool HasButton(int player, EnumButtonType button)
|
||||||
{
|
{
|
||||||
uint raw = 0;
|
uint raw = 0;
|
||||||
|
@ -59,9 +59,9 @@ namespace VirtualNes.Core
|
|||||||
return s_support.GetControllerState();
|
return s_support.GetControllerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SampleInput()
|
public static void SampleInput(uint frameCount)
|
||||||
{
|
{
|
||||||
s_support.SampleInput();
|
s_support.SampleInput(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EmulatorConfig Config => s_support.Config;
|
public static EmulatorConfig Config => s_support.Config;
|
||||||
@ -81,6 +81,6 @@ namespace VirtualNes.Core
|
|||||||
Stream OpenFile(string directPath, string fileName);
|
Stream OpenFile(string directPath, string fileName);
|
||||||
bool TryGetMapperNo(ROM rom, out int mapperNo);
|
bool TryGetMapperNo(ROM rom, out int mapperNo);
|
||||||
ControllerState GetControllerState();
|
ControllerState GetControllerState();
|
||||||
void SampleInput();
|
void SampleInput(uint frameCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,21 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.2d.sprite": "1.0.0",
|
"com.unity.2d.sprite": "1.0.0",
|
||||||
|
"com.unity.2d.tilemap": "1.0.0",
|
||||||
|
"com.unity.ads": "3.7.5",
|
||||||
|
"com.unity.analytics": "3.6.12",
|
||||||
"com.unity.collab-proxy": "1.15.15",
|
"com.unity.collab-proxy": "1.15.15",
|
||||||
"com.unity.editorcoroutines": "1.0.0",
|
"com.unity.editorcoroutines": "1.0.0",
|
||||||
"com.unity.ide.rider": "3.0.13",
|
"com.unity.ide.rider": "3.0.13",
|
||||||
"com.unity.ide.visualstudio": "2.0.14",
|
"com.unity.ide.visualstudio": "2.0.14",
|
||||||
"com.unity.ide.vscode": "1.2.5",
|
"com.unity.ide.vscode": "1.2.5",
|
||||||
|
"com.unity.purchasing": "4.1.3",
|
||||||
"com.unity.test-framework": "1.1.31",
|
"com.unity.test-framework": "1.1.31",
|
||||||
"com.unity.textmeshpro": "3.0.6",
|
"com.unity.textmeshpro": "3.0.6",
|
||||||
"com.unity.timeline": "1.6.4",
|
"com.unity.timeline": "1.6.4",
|
||||||
"com.unity.ugui": "1.0.0",
|
"com.unity.ugui": "1.0.0",
|
||||||
"com.unity.visualscripting": "1.7.6",
|
"com.unity.visualscripting": "1.7.6",
|
||||||
|
"com.unity.xr.legacyinputhelpers": "2.1.9",
|
||||||
"com.unity.modules.ai": "1.0.0",
|
"com.unity.modules.ai": "1.0.0",
|
||||||
"com.unity.modules.androidjni": "1.0.0",
|
"com.unity.modules.androidjni": "1.0.0",
|
||||||
"com.unity.modules.animation": "1.0.0",
|
"com.unity.modules.animation": "1.0.0",
|
||||||
|
@ -6,6 +6,30 @@
|
|||||||
"source": "builtin",
|
"source": "builtin",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
},
|
},
|
||||||
|
"com.unity.2d.tilemap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.ads": {
|
||||||
|
"version": "3.7.5",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.cn"
|
||||||
|
},
|
||||||
|
"com.unity.analytics": {
|
||||||
|
"version": "3.6.12",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.cn"
|
||||||
|
},
|
||||||
"com.unity.collab-proxy": {
|
"com.unity.collab-proxy": {
|
||||||
"version": "1.15.15",
|
"version": "1.15.15",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
@ -54,6 +78,20 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"url": "https://packages.unity.cn"
|
"url": "https://packages.unity.cn"
|
||||||
},
|
},
|
||||||
|
"com.unity.purchasing": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0",
|
||||||
|
"com.unity.modules.unityanalytics": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0",
|
||||||
|
"com.unity.modules.androidjni": "1.0.0",
|
||||||
|
"com.unity.services.core": "1.0.1"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.cn"
|
||||||
|
},
|
||||||
"com.unity.services.core": {
|
"com.unity.services.core": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
@ -114,6 +152,16 @@
|
|||||||
},
|
},
|
||||||
"url": "https://packages.unity.cn"
|
"url": "https://packages.unity.cn"
|
||||||
},
|
},
|
||||||
|
"com.unity.xr.legacyinputhelpers": {
|
||||||
|
"version": "2.1.9",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.vr": "1.0.0",
|
||||||
|
"com.unity.modules.xr": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.cn"
|
||||||
|
},
|
||||||
"com.unity.modules.ai": {
|
"com.unity.modules.ai": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user