实现完美Replay

This commit is contained in:
sin365 2025-01-16 17:12:35 +08:00
parent c1f23ea66f
commit ea7e065b79
7 changed files with 230 additions and 209 deletions

View File

@ -82,6 +82,7 @@ namespace AxiReplay
void UpdateNextFrame(int targetFrame)
{
int LastNextFrameStartID = nextStep.FrameStartID;
//如果已经超过
while (targetFrame >= nextStep.FrameStartID)
{
@ -117,6 +118,12 @@ namespace AxiReplay
}
dbgList.Add($"{nextStep.FrameStartID} | {nextStep.InPut}");
//如果这次的NextStep1只推进了1帧则跳过交给下一帧判断
if (nextStep.FrameStartID - LastNextFrameStartID == 1)
{
break;
}
targetFrame++;
}
}
@ -159,10 +166,12 @@ namespace AxiReplay
/// </summary>
public bool NextFramebyFrameIdx(int FrameID, out ReplayStep data)
{
if (FrameID - lastTest != 1)
{
}
lastTest = FrameID;
if (FrameID == 3360)
{
}
bool res = TakeFrame(FrameID - byFrameIdx, out data);
byFrameIdx = FrameID;
return res;

View File

@ -20,7 +20,8 @@ namespace MAME.Core
}
public static PlayState playState;
public static bool is_foreground;
public static bool paused, exit_pending;
public static bool paused;
public static bool exit_pending;
public static EmuTimer.emu_timer soft_reset_timer;
public static BinaryReader brRecord = null;
public static BinaryWriter bwRecord = null;
@ -57,7 +58,8 @@ namespace MAME.Core
}
else
{
Video.video_frame_update();
//TODO 暂停时,不应该更新画面帧
//Video.video_frame_update();
}
/*if (bPP)
{

View File

@ -845,6 +845,7 @@ namespace MAME.Core
screenstate.vblank_start_time = EmuTimer.global_basetime;// Timer.get_current_time();
screenstate.vblank_end_time = Attotime.attotime_add_attoseconds(screenstate.vblank_start_time, screenstate.vblank_period);
Cpuexec.on_vblank();
//垂直同步
if ((video_attributes & VIDEO_UPDATE_AFTER_VBLANK) == 0)
{
video_frame_update();
@ -862,6 +863,7 @@ namespace MAME.Core
public static void vblank_end_callback()
{
int i;
//垂直同步
if ((video_attributes & VIDEO_UPDATE_AFTER_VBLANK) != 0)
{
video_frame_update();

View File

@ -75,7 +75,7 @@ public class UMAME : MonoBehaviour
mChangeRomName = UniMAMESetting.instance.LastGameRom;
mTimeSpan = new UniTimeSpan();
emu.Init(RomPath, mUniLog, mUniResources, mUniVideoPlayer, mUniSoundPlayer, mUniKeyboard.mKeyCodeCore, mUniMouse, mTimeSpan);
emu.Init(RomPath, mUniLog, mUniResources, mUniVideoPlayer, mUniSoundPlayer, mUniKeyboard, mUniMouse, mTimeSpan);
ALLGame = emu.GetGameList();
Debug.Log($"ALLGame:{ALLGame.Count}");
@ -125,7 +125,7 @@ public class UMAME : MonoBehaviour
{
string Path = SavePath + Machine.sName + ".rp";
mReplayReader = new ReplayReader(Path);
mUniKeyboard.mKeyCodeCore.SetRePlay(true);
mUniKeyboard.SetRePlay(true);
}
//读取ROM之后获得宽高初始化画面
@ -168,7 +168,7 @@ public class UMAME : MonoBehaviour
string Path = SavePath + Machine.sName + ".rp";
string dbgPath = SavePath + Machine.sName + ".rpread";
mReplayReader = new ReplayReader(Path, true, dbgPath);
mUniKeyboard.mKeyCodeCore.Init(mUniKeyboard, true);
mUniKeyboard.Init(true);
}
}

View File

@ -1,183 +0,0 @@
using MAME.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class KeyCodeCore : IKeyboard
{
public Dictionary<KeyCode, MotionKey> dictKeyCfgs = new Dictionary<KeyCode, MotionKey>();
public KeyCode[] CheckList;
public MotionKey[] mCurrKey = new MotionKey[0];
public ulong CurryInpuAllData = 0;
List<MotionKey> temp = new List<MotionKey>();
ulong tempInputAllData = 0;
UniKeyboard mUniKeyboard;
bool bReplayMode;
List<MotionKey> ReplayCheckKey = new List<MotionKey>();
ulong last_CurryInpuAllData_test = 0;
public MotionKey[] GetPressedKeys()
{
if (!bReplayMode)
{
//UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurryInpuAllData);
UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurryInpuAllData);
#if UNITY_EDITOR
if (last_CurryInpuAllData_test != CurryInpuAllData)
{
last_CurryInpuAllData_test = CurryInpuAllData;
string TempStr = "";
foreach (var item in mCurrKey)
{
TempStr += $"{item.ToString()}|";
}
if (!string.IsNullOrEmpty(TempStr))
Debug.Log($"{UMAME.instance.mUniVideoPlayer.mFrame} | Input-> {TempStr}");
else
Debug.Log($"{UMAME.instance.mUniVideoPlayer.mFrame} | Input-> 0");
}
#endif
return mCurrKey;
}
else
{
//有变化
//if (UMAME.instance.mReplayReader.NextFrame(out AxiReplay.ReplayStep stepData))
if (UMAME.instance.mReplayReader.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, out AxiReplay.ReplayStep stepData))
{
temp.Clear();
//有数据
for (int i = 0; i < ReplayCheckKey.Count; i++)
{
if ((stepData.InPut & (ulong)ReplayCheckKey[i]) > 0)
temp.Add(ReplayCheckKey[i]);
}
mCurrKey = temp.ToArray();
#if UNITY_EDITOR
string TempStr = "";
foreach (var item in mCurrKey)
{
TempStr += $"{item.ToString()}|";
}
if (!string.IsNullOrEmpty(TempStr))
Debug.Log($"{UMAME.instance.mUniVideoPlayer.mFrame} | Input-> {TempStr}");
else
Debug.Log($"{UMAME.instance.mUniVideoPlayer.mFrame} | Input-> 0");
#endif
}
return mCurrKey;
}
}
public void SetRePlay(bool IsReplay)
{
bReplayMode = IsReplay;
}
public void Init(UniKeyboard uniKeyboard, bool IsReplay)
{
bReplayMode = IsReplay;
mUniKeyboard = uniKeyboard;
foreach (MotionKey mkey in Enum.GetValues(typeof(MotionKey)))
{
ReplayCheckKey.Add(mkey);
}
dictKeyCfgs.Clear();
//dictKeyCfgs.Add(KeyCode.P, MotionKey.EMU_PAUSED);
dictKeyCfgs.Add(KeyCode.Alpha1, MotionKey.P1_GAMESTART);
dictKeyCfgs.Add(KeyCode.Alpha5, MotionKey.P1_INSERT_COIN);
dictKeyCfgs.Add(KeyCode.W, MotionKey.P1_UP);
dictKeyCfgs.Add(KeyCode.S, MotionKey.P1_DOWN);
dictKeyCfgs.Add(KeyCode.A, MotionKey.P1_LEFT);
dictKeyCfgs.Add(KeyCode.D, MotionKey.P1_RIGHT);
dictKeyCfgs.Add(KeyCode.J, MotionKey.P1_BTN_1);
dictKeyCfgs.Add(KeyCode.K, MotionKey.P1_BTN_2);
dictKeyCfgs.Add(KeyCode.L, MotionKey.P1_BTN_3);
dictKeyCfgs.Add(KeyCode.U, MotionKey.P1_BTN_4);
dictKeyCfgs.Add(KeyCode.KeypadDivide, MotionKey.P2_GAMESTART);
dictKeyCfgs.Add(KeyCode.KeypadMultiply, MotionKey.P2_INSERT_COIN);
dictKeyCfgs.Add(KeyCode.UpArrow, MotionKey.P2_UP);
dictKeyCfgs.Add(KeyCode.DownArrow, MotionKey.P2_DOWN);
dictKeyCfgs.Add(KeyCode.LeftArrow, MotionKey.P2_LEFT);
dictKeyCfgs.Add(KeyCode.RightArrow, MotionKey.P2_RIGHT);
dictKeyCfgs.Add(KeyCode.Keypad1, MotionKey.P2_BTN_1);
dictKeyCfgs.Add(KeyCode.Keypad2, MotionKey.P2_BTN_2);
dictKeyCfgs.Add(KeyCode.Keypad3, MotionKey.P2_BTN_3);
dictKeyCfgs.Add(KeyCode.Keypad4, MotionKey.P2_BTN_4);
CheckList = dictKeyCfgs.Keys.ToArray();
mUniKeyboard.btnP1.Key = new long[] { (long)MotionKey.P1_GAMESTART };
mUniKeyboard.btnCoin1.Key = new long[] { (long)MotionKey.P1_INSERT_COIN };
mUniKeyboard.btnA.Key = new long[] { (long)MotionKey.P1_BTN_1 };
mUniKeyboard.btnB.Key = new long[] { (long)MotionKey.P1_BTN_2 };
mUniKeyboard.btnC.Key = new long[] { (long)MotionKey.P1_BTN_3 };
mUniKeyboard.btnD.Key = new long[] { (long)MotionKey.P1_BTN_4 };
//mUniKeyboard.btnE.Key = new long[] { (long)MotionKey.P1_BTN_5 };
//mUniKeyboard.btnF.Key = new long[] { (long)MotionKey.P1_BTN_6 };
mUniKeyboard.btnAB.Key = new long[] { (long)MotionKey.P1_BTN_1, (long)MotionKey.P1_BTN_2 };
mUniKeyboard.btnCD.Key = new long[] { (long)MotionKey.P1_BTN_3, (long)MotionKey.P1_BTN_4 };
mUniKeyboard.btnABC.Key = new long[] { (long)MotionKey.P1_BTN_1, (long)MotionKey.P1_BTN_2, (long)MotionKey.P1_BTN_3 };
}
public void UpdateLogic()
{
if (bReplayMode) return;
tempInputAllData = 0;
temp.Clear();
for (int i = 0; i < CheckList.Length; i++)
{
if (Input.GetKey(CheckList[i]))
{
MotionKey mk = dictKeyCfgs[CheckList[i]];
temp.Add(mk);
tempInputAllData |= (ulong)mk;
}
}
for (int i = 0; i < mUniKeyboard.mUIBtns.Count; i++)
{
if (mUniKeyboard.mUIBtns[i].bHotKey)
{
for (int j = 0; j < mUniKeyboard.mUIBtns[i].Key.Length; j++)
{
MotionKey mk = (MotionKey)mUniKeyboard.mUIBtns[i].Key[j];
temp.Add(mk);
tempInputAllData |= (ulong)mk;
}
}
}
Vector2Int inputV2 = mUniKeyboard.mJoystick.RawInputV2;
//Debug.Log($"{inputV2.x},{inputV2.y}");
if (inputV2.x > 0)
{
temp.Add(MotionKey.P1_RIGHT);
tempInputAllData |= (ulong)MotionKey.P1_RIGHT;
}
else if (inputV2.x < 0)
{
temp.Add(MotionKey.P1_LEFT);
tempInputAllData |= (ulong)MotionKey.P1_LEFT;
}
if (inputV2.y > 0)
{
temp.Add(MotionKey.P1_UP);
tempInputAllData |= (ulong)MotionKey.P1_UP;
}
else if (inputV2.y < 0)
{
temp.Add(MotionKey.P1_DOWN);
tempInputAllData |= (ulong)MotionKey.P1_DOWN;
}
CurryInpuAllData = tempInputAllData;
mCurrKey = temp.ToArray();
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3054336185b15f84d9543bdafb49907f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,10 +1,11 @@
using MAME.Core;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class UniKeyboard : MonoBehaviour
public class UniKeyboard : MonoBehaviour, IKeyboard
{
public KeyCodeCore mKeyCodeCore = new KeyCodeCore();
#region
#region UIButton
public UILongClickButton btnP1;
public UILongClickButton btnCoin1;
public UILongClickButton btnA;
@ -18,9 +19,15 @@ public class UniKeyboard : MonoBehaviour
public UILongClickButton btnABC;
public Transform tfKeyPad;
public FloatingJoystick mJoystick;
public List<UILongClickButton> mUIBtns = new List<UILongClickButton>();
#endregion
public List<UILongClickButton> mUIBtns = new List<UILongClickButton>();
public static Dictionary<KeyCode, MotionKey> dictKeyCfgs = new Dictionary<KeyCode, MotionKey>();
public static KeyCode[] CheckList;
bool bReplayMode;
PlayMode mPlayMode;
ReplayMode mReplayMode;
ulong last_CurryInpuAllData_test = 0;
void Awake()
{
@ -59,16 +66,211 @@ public class UniKeyboard : MonoBehaviour
// btnF.gameObject.SetActive(false);
//}
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
tfKeyPad.gameObject.SetActive(false);
#endif
mKeyCodeCore.Init(this,false);
Init(false);
}
public MotionKey[] GetPressedKeys()
{
MotionKey[] currkey;
ulong InputData;
if (!bReplayMode)
currkey = mPlayMode.GetPressedKeys(out InputData);
else
currkey = mReplayMode.GetPressedKeys(out InputData);
#if UNITY_EDITOR
if (last_CurryInpuAllData_test != InputData)
{
string TempStr = "";
foreach (var item in currkey)
{
TempStr += $"{item.ToString()}|";
}
Debug.Log($"{UMAME.instance.mUniVideoPlayer.mFrame} | {EmuTimer.get_current_time().attoseconds} |{EmuTimer.get_current_time().seconds} | {InputData} | {TempStr}");
last_CurryInpuAllData_test = InputData;
}
#endif
return currkey;
}
public void UpdateInputKey()
{
mKeyCodeCore.UpdateLogic();
UpdateLogic();
}
#region
public void SetRePlay(bool IsReplay)
{
bReplayMode = IsReplay;
}
public void Init(bool IsReplay)
{
bReplayMode = IsReplay;
dictKeyCfgs.Clear();
//dictKeyCfgs.Add(KeyCode.P, MotionKey.EMU_PAUSED);
dictKeyCfgs.Add(KeyCode.Alpha1, MotionKey.P1_GAMESTART);
dictKeyCfgs.Add(KeyCode.Alpha5, MotionKey.P1_INSERT_COIN);
dictKeyCfgs.Add(KeyCode.W, MotionKey.P1_UP);
dictKeyCfgs.Add(KeyCode.S, MotionKey.P1_DOWN);
dictKeyCfgs.Add(KeyCode.A, MotionKey.P1_LEFT);
dictKeyCfgs.Add(KeyCode.D, MotionKey.P1_RIGHT);
dictKeyCfgs.Add(KeyCode.J, MotionKey.P1_BTN_1);
dictKeyCfgs.Add(KeyCode.K, MotionKey.P1_BTN_2);
dictKeyCfgs.Add(KeyCode.L, MotionKey.P1_BTN_3);
dictKeyCfgs.Add(KeyCode.U, MotionKey.P1_BTN_4);
dictKeyCfgs.Add(KeyCode.KeypadDivide, MotionKey.P2_GAMESTART);
dictKeyCfgs.Add(KeyCode.KeypadMultiply, MotionKey.P2_INSERT_COIN);
dictKeyCfgs.Add(KeyCode.UpArrow, MotionKey.P2_UP);
dictKeyCfgs.Add(KeyCode.DownArrow, MotionKey.P2_DOWN);
dictKeyCfgs.Add(KeyCode.LeftArrow, MotionKey.P2_LEFT);
dictKeyCfgs.Add(KeyCode.RightArrow, MotionKey.P2_RIGHT);
dictKeyCfgs.Add(KeyCode.Keypad1, MotionKey.P2_BTN_1);
dictKeyCfgs.Add(KeyCode.Keypad2, MotionKey.P2_BTN_2);
dictKeyCfgs.Add(KeyCode.Keypad3, MotionKey.P2_BTN_3);
dictKeyCfgs.Add(KeyCode.Keypad4, MotionKey.P2_BTN_4);
CheckList = dictKeyCfgs.Keys.ToArray();
btnP1.Key = new long[] { (long)MotionKey.P1_GAMESTART };
btnCoin1.Key = new long[] { (long)MotionKey.P1_INSERT_COIN };
btnA.Key = new long[] { (long)MotionKey.P1_BTN_1 };
btnB.Key = new long[] { (long)MotionKey.P1_BTN_2 };
btnC.Key = new long[] { (long)MotionKey.P1_BTN_3 };
btnD.Key = new long[] { (long)MotionKey.P1_BTN_4 };
//btnE.Key = new long[] { (long)MotionKey.P1_BTN_5 };
//btnF.Key = new long[] { (long)MotionKey.P1_BTN_6 };
btnAB.Key = new long[] { (long)MotionKey.P1_BTN_1, (long)MotionKey.P1_BTN_2 };
btnCD.Key = new long[] { (long)MotionKey.P1_BTN_3, (long)MotionKey.P1_BTN_4 };
btnABC.Key = new long[] { (long)MotionKey.P1_BTN_1, (long)MotionKey.P1_BTN_2, (long)MotionKey.P1_BTN_3 };
mPlayMode = new PlayMode(this);
mReplayMode = new ReplayMode();
}
public void UpdateLogic()
{
if (bReplayMode) return;
mPlayMode.UpdateLogic();
}
public class PlayMode
{
Dictionary<KeyCode, MotionKey> dictKeyCfgs => UniKeyboard.dictKeyCfgs;
UniKeyboard mUniKeyboard;
KeyCode[] CheckList => UniKeyboard.CheckList;
ulong tempInputAllData = 0;
List<MotionKey> temp = new List<MotionKey>();
public ulong CurryInpuAllData = 0;
public MotionKey[] mCurrKey = new MotionKey[0];
public PlayMode(UniKeyboard uniKeyboard)
{
this.mUniKeyboard = uniKeyboard;
}
public void UpdateLogic()
{
tempInputAllData = 0;
temp.Clear();
for (int i = 0; i < CheckList.Length; i++)
{
if (Input.GetKey(CheckList[i]))
{
MotionKey mk = dictKeyCfgs[CheckList[i]];
temp.Add(mk);
tempInputAllData |= (ulong)mk;
}
}
for (int i = 0; i < mUniKeyboard.mUIBtns.Count; i++)
{
if (mUniKeyboard.mUIBtns[i].bHotKey)
{
for (int j = 0; j < mUniKeyboard.mUIBtns[i].Key.Length; j++)
{
MotionKey mk = (MotionKey)mUniKeyboard.mUIBtns[i].Key[j];
temp.Add(mk);
tempInputAllData |= (ulong)mk;
}
}
}
Vector2Int inputV2 = mUniKeyboard.mJoystick.RawInputV2;
//Debug.Log($"{inputV2.x},{inputV2.y}");
if (inputV2.x > 0)
{
temp.Add(MotionKey.P1_RIGHT);
tempInputAllData |= (ulong)MotionKey.P1_RIGHT;
}
else if (inputV2.x < 0)
{
temp.Add(MotionKey.P1_LEFT);
tempInputAllData |= (ulong)MotionKey.P1_LEFT;
}
if (inputV2.y > 0)
{
temp.Add(MotionKey.P1_UP);
tempInputAllData |= (ulong)MotionKey.P1_UP;
}
else if (inputV2.y < 0)
{
temp.Add(MotionKey.P1_DOWN);
tempInputAllData |= (ulong)MotionKey.P1_DOWN;
}
CurryInpuAllData = tempInputAllData;
mCurrKey = temp.ToArray();
}
public MotionKey[] GetPressedKeys(out ulong InputData)
{
//UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurryInpuAllData);
UMAME.instance.mReplayWriter.NextFramebyFrameIdx((int)UMAME.instance.mUniVideoPlayer.mFrame, CurryInpuAllData);
InputData = CurryInpuAllData;
return mCurrKey;
}
}
public class ReplayMode
{
public MotionKey[] mCurrKey = new MotionKey[0];
MotionKey[] ReplayCheckKey;
public ReplayMode()
{
ReplayCheckKey = dictKeyCfgs.Values.ToArray();
}
public MotionKey[] GetPressedKeys(out ulong InputData)
{
List<MotionKey> temp = new List<MotionKey>();
//Óб仯
//if (UMAME.instance.mReplayReader.NextFrame(out AxiReplay.ReplayStep stepData))
int targetFrame = (int)UMAME.instance.mUniVideoPlayer.mFrame;
//if (UMAME.instance.mReplayReader.NextFramebyFrameIdx(targetFrame, out AxiReplay.ReplayStep stepData))
//{
// temp.Clear();
// //ÓÐÊý¾Ý
// for (int i = 0; i < ReplayCheckKey.Length; i++)
// {
// if ((stepData.InPut & (ulong)ReplayCheckKey[i]) > 0)
// temp.Add(ReplayCheckKey[i]);
// }
// mCurrKey = temp.ToArray();
//}
UMAME.instance.mReplayReader.NextFramebyFrameIdx(targetFrame, out AxiReplay.ReplayStep stepData);
temp.Clear();
//ÓÐÊý¾Ý
for (int i = 0; i < ReplayCheckKey.Length; i++)
{
if ((stepData.InPut & (ulong)ReplayCheckKey[i]) > 0)
temp.Add(ReplayCheckKey[i]);
}
mCurrKey = temp.ToArray();
InputData = stepData.InPut;
return mCurrKey;
}
}
#endregion
}