mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-03 07:10:42 -07:00
gitadora: option to disable frame limiter (#848)
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change There is a patch for GITADORA series that fixes frame pacing on modern Windows. Turn it into a signature patch and embed it into the game. ## Testing should work for all 64-bit gitadora versions, pre-GWD
This commit is contained in:
@@ -31,6 +31,7 @@ namespace games::gitadora {
|
|||||||
|
|
||||||
// settings
|
// settings
|
||||||
bool TWOCHANNEL = false;
|
bool TWOCHANNEL = false;
|
||||||
|
bool DISABLE_FRAME_LIMITER = false;
|
||||||
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
std::optional<unsigned int> CAB_TYPE = std::nullopt;
|
||||||
bool P1_LEFTY = false;
|
bool P1_LEFTY = false;
|
||||||
bool P2_LEFTY = false;
|
bool P2_LEFTY = false;
|
||||||
@@ -65,6 +66,46 @@ namespace games::gitadora {
|
|||||||
|
|
||||||
return CreateDirectoryA(lpPathName, lpSecurityAttributes);
|
return CreateDirectoryA(lpPathName, lpSecurityAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// libshare-pj paces mainloop with separate 12 ms and 16 ms waits. these waits
|
||||||
|
// interfere with the game's normal display synchronization on modern Windows
|
||||||
|
// and can hold a nominal 60 FPS game near 58 FPS. locate the instruction
|
||||||
|
// sequences at runtime so the fix does not depend on per-version file offsets.
|
||||||
|
static void disable_mainloop_frame_limiter(HMODULE sharepj_module) {
|
||||||
|
if (!sharepj_module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// both limiters have the same shape, only the millisecond target xx differs
|
||||||
|
// (0Ch for the 12 ms limiter, 10h for the 16 ms one):
|
||||||
|
//
|
||||||
|
// 48 83 F8 xx: cmp rax, xx; compare elapsed frame time with the target
|
||||||
|
// 73 10: jae +10h; skip the wait once the target has elapsed
|
||||||
|
// B9 xx 00 00 00: mov ecx, xx; load the target
|
||||||
|
// 48 2B C8: sub rcx, rax; calculate the remaining wait time
|
||||||
|
// 74 06: je +6h; skip the following six-byte Sleep call if no wait remains
|
||||||
|
//
|
||||||
|
// changing jae (73h) to jmp (EBh) makes each block always take its existing
|
||||||
|
// skip path, which bypasses only the associated Sleep call and leaves the 10h
|
||||||
|
// branch displacement and every other wait untouched.
|
||||||
|
const auto limiter_12ms_disabled = replace_pattern(
|
||||||
|
sharepj_module,
|
||||||
|
"4883F80C7310B90C000000482BC87406",
|
||||||
|
"????????EB??????????????????????", 0, 0);
|
||||||
|
const auto limiter_16ms_disabled = replace_pattern(
|
||||||
|
sharepj_module,
|
||||||
|
"4883F8107310B910000000482BC87406",
|
||||||
|
"????????EB??????????????????????", 0, 0);
|
||||||
|
|
||||||
|
if (!limiter_12ms_disabled || !limiter_16ms_disabled) {
|
||||||
|
log_fatal(
|
||||||
|
"gitadora",
|
||||||
|
"failed to disable libshare-pj mainloop frame limiter (-gdnoframelimiter), ensure patch is not already applied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("gitadora", "successfully disabled libshare-pj mainloop frame limiter (-gdnoframelimiter)");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -687,6 +728,12 @@ namespace games::gitadora {
|
|||||||
HMODULE system_module = libutils::try_module("libsystem.dll");
|
HMODULE system_module = libutils::try_module("libsystem.dll");
|
||||||
|
|
||||||
// patches
|
// patches
|
||||||
|
#ifdef SPICE64
|
||||||
|
if (DISABLE_FRAME_LIMITER && !is_arena_model()) {
|
||||||
|
disable_mainloop_frame_limiter(sharepj_module);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
detour::inline_hook((void *) eam_network_detected_ip_change, libutils::try_proc(
|
detour::inline_hook((void *) eam_network_detected_ip_change, libutils::try_proc(
|
||||||
sharepj_module, "eam_network_detected_ip_change"));
|
sharepj_module, "eam_network_detected_ip_change"));
|
||||||
detour::inline_hook((void *) eam_network_settings_conflict, libutils::try_proc(
|
detour::inline_hook((void *) eam_network_settings_conflict, libutils::try_proc(
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace games::gitadora {
|
|||||||
|
|
||||||
// settings
|
// settings
|
||||||
extern bool TWOCHANNEL;
|
extern bool TWOCHANNEL;
|
||||||
|
extern bool DISABLE_FRAME_LIMITER;
|
||||||
extern std::optional<unsigned int> CAB_TYPE;
|
extern std::optional<unsigned int> CAB_TYPE;
|
||||||
extern bool P1_LEFTY;
|
extern bool P1_LEFTY;
|
||||||
extern bool P2_LEFTY;
|
extern bool P2_LEFTY;
|
||||||
|
|||||||
@@ -644,6 +644,9 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::LoadGitaDoraModule].value_bool()) {
|
if (options[launcher::Options::LoadGitaDoraModule].value_bool()) {
|
||||||
attach_gitadora = true;
|
attach_gitadora = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::GitaDoraDisableFrameLimiter].value_bool()) {
|
||||||
|
games::gitadora::DISABLE_FRAME_LIMITER = true;
|
||||||
|
}
|
||||||
if (options[launcher::Options::GitaDoraCabinetType].is_active()) {
|
if (options[launcher::Options::GitaDoraCabinetType].is_active()) {
|
||||||
games::gitadora::CAB_TYPE = options[launcher::Options::GitaDoraCabinetType].value_uint32();
|
games::gitadora::CAB_TYPE = options[launcher::Options::GitaDoraCabinetType].value_uint32();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1202,6 +1202,19 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options",
|
.category = "Game Options",
|
||||||
.quick_setting_category = "Game",
|
.quick_setting_category = "Game",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.title = "GitaDora Disable Frame Limiter (EXPERIMENTAL)",
|
||||||
|
.name = "gdnoframelimiter",
|
||||||
|
.desc = "Only for GITADORA to GALAXY WAVE; not for XG series or Arena Model.\n\n"
|
||||||
|
"Game engine's built-in frame limiter can result in unstable frame pacing "
|
||||||
|
"(around 56-58 FPS) on modern Windows. Turning this on disables that and "
|
||||||
|
"forces the game to rely on V-Sync instead, resulting in a stable FPS.\n\n"
|
||||||
|
"Ensure your monitors are set to 60Hz.",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "GitaDora",
|
||||||
|
.category = "Game Options",
|
||||||
|
.quick_setting_category = "Game",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.title = "GitaDora Cabinet Type",
|
.title = "GitaDora Cabinet Type",
|
||||||
.name = "gdcabtype",
|
.name = "gdcabtype",
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ namespace launcher {
|
|||||||
LoadHelloPopnMusicModule,
|
LoadHelloPopnMusicModule,
|
||||||
LoadGitaDoraModule,
|
LoadGitaDoraModule,
|
||||||
GitaDoraTwoChannelAudio,
|
GitaDoraTwoChannelAudio,
|
||||||
|
GitaDoraDisableFrameLimiter,
|
||||||
GitaDoraCabinetType,
|
GitaDoraCabinetType,
|
||||||
GitaDoraLefty,
|
GitaDoraLefty,
|
||||||
GitaDoraWailHold,
|
GitaDoraWailHold,
|
||||||
|
|||||||
Reference in New Issue
Block a user