NesEmulator重构
This commit is contained in:
parent
c7a4f1467a
commit
1ffa708e71
@ -1,5 +1,6 @@
|
|||||||
using AxibugEmuOnline.Client.ClientCore;
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
using AxibugProtobuf;
|
using AxibugProtobuf;
|
||||||
|
using AxiReplay;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -11,7 +12,7 @@ using VirtualNes.Core.Debug;
|
|||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
public class NesEmulator : IEmuCore
|
public class NesEmulator : EmuCore<ControllerState>
|
||||||
{
|
{
|
||||||
public VideoProvider VideoProvider;
|
public VideoProvider VideoProvider;
|
||||||
public AudioProvider AudioProvider;
|
public AudioProvider AudioProvider;
|
||||||
@ -122,32 +123,31 @@ namespace AxibugEmuOnline.Client
|
|||||||
NesCore = null;
|
NesCore = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
private ControllerState m_lastState;
|
|
||||||
#endif
|
|
||||||
//推进帧
|
//推进帧
|
||||||
public override bool PushEmulatorFrame()
|
protected override bool OnPushEmulatorFrame(ControllerState inputData)
|
||||||
{
|
{
|
||||||
if (NesCore == null || IsPause) return false;
|
if (NesCore == null || IsPause) return false;
|
||||||
|
|
||||||
m_coreSupporter.SampleInput(NesCore.FrameCount);
|
NesCore.pad.Sync(inputData);
|
||||||
var controlState = m_coreSupporter.GetControllerState();
|
|
||||||
|
|
||||||
//如果未收到Input数据,核心帧不推进
|
|
||||||
if (!controlState.valid) return false;
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
if (controlState != m_lastState) App.log.Info($"[LOCALDEBUG]{NesCore.FrameCount}-->{controlState}");
|
|
||||||
m_lastState = controlState;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NesCore.pad.Sync(controlState);
|
|
||||||
NesCore.EmulateFrame(true);
|
NesCore.EmulateFrame(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override ControllerState ConvertInputDataFromNet(ReplayStep step)
|
||||||
|
{
|
||||||
|
return m_coreSupporter.FromNet(step);
|
||||||
|
}
|
||||||
|
protected override ulong InputDataToNet(ControllerState inputData)
|
||||||
|
{
|
||||||
|
return m_coreSupporter.ToNet(inputData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ControllerState GetLocalInput()
|
||||||
|
{
|
||||||
|
return m_coreSupporter.GetControllerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override unsafe void AfterPushFrame()
|
public override unsafe void AfterPushFrame()
|
||||||
{
|
{
|
||||||
@ -165,6 +165,13 @@ namespace AxibugEmuOnline.Client
|
|||||||
StopGame();
|
StopGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Texture OutputPixel => VideoProvider.OutputPixel;
|
||||||
|
public override RawImage DrawCanvas => VideoProvider.Drawer;
|
||||||
|
public override void GetAudioParams(out int frequency, out int channels)
|
||||||
|
{
|
||||||
|
AudioProvider.GetAudioParams(out frequency, out channels);
|
||||||
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 编辑器用
|
/// 编辑器用
|
||||||
@ -195,13 +202,5 @@ namespace AxibugEmuOnline.Client
|
|||||||
UnityEditor.AssetDatabase.SaveAssets();
|
UnityEditor.AssetDatabase.SaveAssets();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public override Texture OutputPixel => VideoProvider.OutputPixel;
|
|
||||||
public override RawImage DrawCanvas => VideoProvider.Drawer;
|
|
||||||
public override void GetAudioParams(out int frequency, out int channels)
|
|
||||||
{
|
|
||||||
AudioProvider.GetAudioParams(out frequency, out channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,9 +1,18 @@
|
|||||||
using AxibugProtobuf;
|
#pragma warning disable CS0618 // 类型或成员已过时
|
||||||
|
|
||||||
|
using AxibugEmuOnline.Client.ClientCore;
|
||||||
|
using AxibugProtobuf;
|
||||||
|
using AxiReplay;
|
||||||
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace AxibugEmuOnline.Client
|
namespace AxibugEmuOnline.Client
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// use <see cref="EmuCore{INPUTDATA}"/> instead
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("不可直接继承,需要继承EmuCore类型")]
|
||||||
public abstract class IEmuCore : MonoBehaviour
|
public abstract class IEmuCore : MonoBehaviour
|
||||||
{
|
{
|
||||||
/// <summary> 获得模拟器核心中的状态快照对象 </summary>
|
/// <summary> 获得模拟器核心中的状态快照对象 </summary>
|
||||||
@ -33,7 +42,7 @@ namespace AxibugEmuOnline.Client
|
|||||||
public abstract RomPlatformType Platform { get; }
|
public abstract RomPlatformType Platform { get; }
|
||||||
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
|
/// <summary> 获取当前模拟器帧序号,在加载快照和Reset后,应当重置为0 </summary>
|
||||||
public abstract uint Frame { get; }
|
public abstract uint Frame { get; }
|
||||||
/// <summary> 模拟器核心推帧 </summary>
|
|
||||||
public abstract bool PushEmulatorFrame();
|
public abstract bool PushEmulatorFrame();
|
||||||
/// <summary> 模拟器核心推帧结束 </summary>
|
/// <summary> 模拟器核心推帧结束 </summary>
|
||||||
public abstract void AfterPushFrame();
|
public abstract void AfterPushFrame();
|
||||||
@ -41,4 +50,71 @@ namespace AxibugEmuOnline.Client
|
|||||||
public abstract Texture OutputPixel { get; }
|
public abstract Texture OutputPixel { get; }
|
||||||
public abstract RawImage DrawCanvas { get; }
|
public abstract RawImage DrawCanvas { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class EmuCore<INPUTDATA> : IEmuCore
|
||||||
|
{
|
||||||
|
public sealed override bool PushEmulatorFrame()
|
||||||
|
{
|
||||||
|
if (SampleInputData(out var inputData))
|
||||||
|
{
|
||||||
|
return OnPushEmulatorFrame(inputData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong m_lastTestInput;
|
||||||
|
protected bool SampleInputData(out INPUTDATA inputData)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
inputData = default(INPUTDATA);
|
||||||
|
|
||||||
|
if (InGameUI.Instance.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}");
|
||||||
|
}
|
||||||
|
|
||||||
|
inputData = ConvertInputDataFromNet(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
|
||||||
|
{
|
||||||
|
inputData = GetLocalInput();
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract INPUTDATA GetLocalInput();
|
||||||
|
protected abstract INPUTDATA ConvertInputDataFromNet(ReplayStep step);
|
||||||
|
protected abstract ulong InputDataToNet(INPUTDATA inputData);
|
||||||
|
/// <summary> 模拟器核心推帧 </summary>
|
||||||
|
protected abstract bool OnPushEmulatorFrame(INPUTDATA InputData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#pragma warning restore CS0618 // 类型或成员已过时
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user