2024-06-01 14:30:03 +02:00
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
|
|
|
|
|
|
using HarmonyLib;
|
2024-07-08 20:56:35 +02:00
|
|
|
|
using Manager;
|
|
|
|
|
using Manager.UserDatas;
|
2024-06-01 14:30:03 +02:00
|
|
|
|
using Monitor;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
|
|
|
|
|
namespace UnlockFrameRate;
|
|
|
|
|
|
|
|
|
|
[HarmonyPatch]
|
|
|
|
|
internal class PatchFrameTime
|
|
|
|
|
{
|
|
|
|
|
private const float OriginalFrameRate = 60f;
|
|
|
|
|
private const float OriginalFrameTime = 1000f / OriginalFrameRate;
|
|
|
|
|
private const float OriginalFramePerMilliseconds = OriginalFrameRate / 1000;
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<MethodBase> TargetMethods()
|
|
|
|
|
{
|
2024-07-08 20:56:35 +02:00
|
|
|
|
// This shouldn't be patched, because they make the judgements
|
|
|
|
|
// harder or easier depending on your frame rate.
|
|
|
|
|
// var noteJudge = AccessTools.TypeByName("NoteJudge");
|
|
|
|
|
// var juggeTiming = AccessTools.Inner(noteJudge, "JuggeTiming"); // lol
|
|
|
|
|
|
|
|
|
|
// yield return AccessTools.Constructor(juggeTiming);
|
|
|
|
|
|
|
|
|
|
// This changes the effect of judgement timing based on the set FPS,
|
|
|
|
|
// so +2.0 at 120Hz will only add 17ms instead of 33ms.
|
|
|
|
|
if (FrameRatePlugin.Instance.PatchJudgementTiming)
|
|
|
|
|
{
|
|
|
|
|
yield return AccessTools.Method(typeof(NoteJudge), nameof(NoteJudge.GetJudgeTiming));
|
|
|
|
|
yield return AccessTools.Method(typeof(NoteJudge), nameof(NoteJudge.GetSlideJudgeTiming));
|
|
|
|
|
yield return AccessTools.Method(typeof(UserOption), nameof(UserOption.GetAdjustMSec));
|
|
|
|
|
}
|
2024-06-01 14:30:03 +02:00
|
|
|
|
|
|
|
|
|
yield return AccessTools.Method(typeof(NoteBase), "IsNoteCheckTimeStart");
|
|
|
|
|
yield return AccessTools.Method(typeof(TouchNoteB), "GetNoteYPosition");
|
|
|
|
|
yield return AccessTools.Method(typeof(SlideRoot), "IsNoteCheckTimeStart");
|
|
|
|
|
yield return AccessTools.Method(typeof(SlideJudge), nameof(SlideJudge.Initialize));
|
|
|
|
|
yield return AccessTools.Method(typeof(JudgeGrade), nameof(JudgeGrade.Initialize));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getPlayFirstMsec));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getPlayFinalMsec));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesManager), nameof(NotesManager.getCurrentDrawFrame));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.calcFrame));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.GetBPM_Frame));
|
|
|
|
|
yield return AccessTools.Method(typeof(NotesReader), nameof(NotesReader.getMeter_Frame));
|
|
|
|
|
yield return AccessTools.Method(typeof(NoteData), nameof(NoteData.getLengthFrame));
|
|
|
|
|
yield return AccessTools.Method(typeof(GameManager), nameof(GameManager.UpdateGameTimer));
|
|
|
|
|
yield return AccessTools.PropertyGetter(typeof(NotesTime), nameof(NotesTime.frame));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
|
|
|
|
|
{
|
2024-07-08 20:56:35 +02:00
|
|
|
|
var targetFrameTime = 1000f / FrameRatePlugin.Instance.TargetFrameRate;
|
|
|
|
|
var targetFramePerMs = (float)FrameRatePlugin.Instance.TargetFrameRate / 1000;
|
2024-06-01 14:30:03 +02:00
|
|
|
|
var i = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var instruction in instructions)
|
|
|
|
|
{
|
|
|
|
|
if (instruction.opcode != OpCodes.Ldc_R4 || instruction.operand is not float operand)
|
|
|
|
|
{
|
|
|
|
|
yield return instruction;
|
|
|
|
|
i++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var overridden = false;
|
|
|
|
|
|
|
|
|
|
if (Math.Abs(operand - OriginalFrameTime) < float.Epsilon)
|
|
|
|
|
{
|
|
|
|
|
instruction.operand = targetFrameTime;
|
|
|
|
|
overridden = true;
|
|
|
|
|
}
|
|
|
|
|
else if (Math.Abs(operand - OriginalFramePerMilliseconds) < float.Epsilon)
|
|
|
|
|
{
|
|
|
|
|
instruction.operand = targetFramePerMs;
|
|
|
|
|
overridden = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (overridden)
|
|
|
|
|
{
|
|
|
|
|
FrameRatePlugin.Logger.LogDebug(
|
|
|
|
|
"Overrode constant at opcode index {0} in {1}: {2} => {3}",
|
|
|
|
|
i,
|
|
|
|
|
__originalMethod.Name,
|
|
|
|
|
operand,
|
|
|
|
|
instruction.operand);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield return instruction;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|