From 56308aec430784f970ac73a9b0efdf4c62d6654f Mon Sep 17 00:00:00 2001 From: frknkrc44 Date: Mon, 28 Jul 2025 11:21:29 +0300 Subject: [PATCH 1/2] add loop and ignore auto pause for pv mode --- .../source/plugins/TLAC/Components/Pause.cpp | 64 ++++++++++++++++++- .../source/plugins/TLAC/Components/Pause.h | 22 ++++++- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/source-code/source/plugins/TLAC/Components/Pause.cpp b/source-code/source/plugins/TLAC/Components/Pause.cpp index c6952da6..9c9d76d8 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.cpp +++ b/source-code/source/plugins/TLAC/Components/Pause.cpp @@ -18,6 +18,8 @@ namespace TLAC::Components bool Pause::isPaused = false; bool Pause::giveUp = false; bool Pause::autoPause = false; + bool Pause::ignoreAutoPause = false; + bool Pause::autoReplay = false; bool Pause::showUI = true; int Pause::selResultAet1 = 0; int Pause::selResultAet2 = 0; @@ -43,6 +45,7 @@ namespace TLAC::Components uint8_t* Pause::ageageHairPatchAddress = (uint8_t*)0x14054352c; std::vector Pause::streamPlayStates; bool(*divaGiveUpFunc)(void*) = (bool(*)(void* cls))GIVEUP_FUNC_ADDRESS; + void(*divaPVEndFunc)(uint64_t, char, char) = (void(*)(uint64_t, char, char))0x140108260; PlayerData* Pause::playerData; InputState* Pause::inputState; TouchSliderState* Pause::sliderState; @@ -56,7 +59,7 @@ namespace TLAC::Components { { "RESUME", unpause, false }, { "RESTART", restart, false }, - { "SE VOLUME", sevolmenu, false }, + { "SE VOLUME", sevolorpvmenu, false }, { "GIVE UP", giveup, false }, } }, @@ -68,6 +71,13 @@ namespace TLAC::Components { "-", sevolminus, true }, } }, + { + "PV OPTIONS", + { + { "XX", pvloop, false }, + { "XX", pvignoreautopause, false }, + } + }, }; Pause::Pause() @@ -113,6 +123,11 @@ namespace TLAC::Components DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)divaGiveUpFunc, hookedGiveUpFunc); DetourTransactionCommit(); + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)divaPVEndFunc, hookedDivaPVEndFunc); + DetourTransactionCommit(); } void Pause::Update() @@ -260,7 +275,9 @@ namespace TLAC::Components } } - if (curMenuSet == MENUSET_SEVOL) + switch (curMenuSet) + { + case MENUSET_SEVOL: { const char volformat[] = "%d"; size_t size = snprintf(nullptr, 0, volformat, playerData->act_vol) + 1; @@ -268,6 +285,28 @@ namespace TLAC::Components snprintf(buf, size, volformat, playerData->act_vol); menu[MENUSET_SEVOL].items[1].name = buf; delete[] buf; + break; + } + case MENUSET_PV: + { + char* buf1 = new char[11]; + snprintf(buf1, 11, "PV LOOP: %s", autoReplay ? "Y" : "N"); + menu[MENUSET_PV].items[0].name = buf1; + delete[] buf1; + + char* buf2 = new char[12]; + snprintf(buf2, 12, "NO PAUSE: %s", ignoreAutoPause ? "Y" : "N"); + menu[MENUSET_PV].items[1].name = buf2; + delete[] buf2; + break; + } + case MENUSET_MAIN: + { + menu[MENUSET_MAIN].items[2].name = isInPV() + ? menu[MENUSET_PV].name + : menu[MENUSET_SEVOL].name; + break; + } } } } @@ -342,6 +381,13 @@ namespace TLAC::Components inputState->IntervalTapped.Buttons = (JvsButtons)(inputState->IntervalTapped.Buttons & ~filteredButtons); lastTouchType = panelState->ContactType; + + // ensure the PV-only temporary values aren't retained + if ((autoReplay || ignoreAutoPause) && *(uint8_t*)PV_LOADING_STATE_ADDRESS < 8) + { + ignoreAutoPause = false; + autoReplay = false; + } } // returns the midpoint of a menu button @@ -589,7 +635,7 @@ namespace TLAC::Components void Pause::OnFocusLost() { - if (autoPause && isInGame()) + if (autoPause && isInGame() && !ignoreAutoPause) pause = true; } @@ -622,6 +668,18 @@ namespace TLAC::Components return false; } + void Pause::hookedDivaPVEndFunc(uint64_t p1, char p2, char p3) + { + if (autoReplay && isInPV()) + { + restart(); + } + else + { + divaPVEndFunc(p1, p2, p3); + } + } + void Pause::setSEVolume(int amount) { playerData->act_vol += amount; diff --git a/source-code/source/plugins/TLAC/Components/Pause.h b/source-code/source/plugins/TLAC/Components/Pause.h index 1162ec62..4a7ee5da 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.h +++ b/source-code/source/plugins/TLAC/Components/Pause.h @@ -31,6 +31,8 @@ namespace TLAC::Components static bool giveUp; // set give up to end current song static bool autoPause; // pause when window loses focus + static bool ignoreAutoPause; // ignore pause on PV + static bool autoReplay; // loop PV private: // this is a mess of static so that menuItems can work static bool isPauseKeyTapped(); @@ -56,6 +58,7 @@ namespace TLAC::Components static uint8_t* ageageHairPatchAddress; static bool hookedGiveUpFunc(void* cls); + static void hookedDivaPVEndFunc(uint64_t, char, char); static void setSEVolume(int amount); @@ -95,6 +98,7 @@ namespace TLAC::Components { MENUSET_MAIN = 0, MENUSET_SEVOL = 1, + MENUSET_PV = 2, }; struct menuItem @@ -194,12 +198,26 @@ namespace TLAC::Components InjectCode((void*)0x1401038cd, { 0x12 }); InjectCode((void*)0x140103b94, { 0x16 }); unpause(); } - static void giveup() { giveUp = true; }; - static void sevolmenu() { setMenuPos(MENUSET_SEVOL, 1); }; + static void giveup() { + ignoreAutoPause = false; + autoReplay = false; + giveUp = true; + }; + + static void sevolorpvmenu() { + setMenuPos(isInPV() ? MENUSET_PV : MENUSET_SEVOL, 1); + }; + + static void pvloop() { autoReplay = !autoReplay; } + static void pvignoreautopause() { ignoreAutoPause = !ignoreAutoPause; } static void sevolplus() { setSEVolume(10); }; static void sevolminus() { setSEVolume(-10); }; + static bool isInPV() { + return isInGame() && *(char*)0x140C94438 == 2; + } + // contents are in Pause.cpp because they can't be inline here for a static (const) array/vec static std::vector menu; From 3e4d5002e8263a857c13339381da07ee6feb03ff Mon Sep 17 00:00:00 2001 From: frknkrc44 Date: Tue, 29 Jul 2025 03:51:33 +0300 Subject: [PATCH 2/2] fix END_FADEOUT included PVs --- .../source/plugins/TLAC/Components/Pause.cpp | 28 +++++++++++++++++++ .../source/plugins/TLAC/Components/Pause.h | 17 ++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/source-code/source/plugins/TLAC/Components/Pause.cpp b/source-code/source/plugins/TLAC/Components/Pause.cpp index 9c9d76d8..f3ff749c 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.cpp +++ b/source-code/source/plugins/TLAC/Components/Pause.cpp @@ -46,6 +46,7 @@ namespace TLAC::Components std::vector Pause::streamPlayStates; bool(*divaGiveUpFunc)(void*) = (bool(*)(void* cls))GIVEUP_FUNC_ADDRESS; void(*divaPVEndFunc)(uint64_t, char, char) = (void(*)(uint64_t, char, char))0x140108260; + char(*divaScriptCommandFunc)(uint64_t, uint64_t, uint64_t, void*, void*, char, char) = (char(*)(uint64_t, uint64_t, uint64_t, void*, void*, char, char))0x14011CBA0; PlayerData* Pause::playerData; InputState* Pause::inputState; TouchSliderState* Pause::sliderState; @@ -128,6 +129,11 @@ namespace TLAC::Components DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)divaPVEndFunc, hookedDivaPVEndFunc); DetourTransactionCommit(); + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)divaScriptCommandFunc, hookedScriptCommandFunc); + DetourTransactionCommit(); } void Pause::Update() @@ -672,6 +678,8 @@ namespace TLAC::Components { if (autoReplay && isInPV()) { + printf("[TLAC] END triggered, restarting the PV\n"); + restart(); } else @@ -680,6 +688,26 @@ namespace TLAC::Components } } + char Pause::hookedScriptCommandFunc(uint64_t p1, uint64_t p2, uint64_t p3, void* p4, void* p5, char p6, char p7) + { + int position = *(int*)(p1 + 180012); + int cmd = *(int*)(p1 + 4 * position + 12); + + // printf("ARG: %lld, %lld, %lld, %p, %p, %d, %d - POS: %d, CMD: %d\n", p1, p2, p3, p4, p5, p6, p7, position, cmd); + + if (cmd == 83 && autoReplay) + { + printf("[TLAC] END_FADEOUT triggered but ignored\n"); + + // fix stucking at restart and the PV Script Command Error + *(int*)(p1 + 180012) = position + 3; + + return 1; + } + + return divaScriptCommandFunc(p1, p2, p3, p4, p5, p6, p7); + } + void Pause::setSEVolume(int amount) { playerData->act_vol += amount; diff --git a/source-code/source/plugins/TLAC/Components/Pause.h b/source-code/source/plugins/TLAC/Components/Pause.h index 4a7ee5da..a7dea7de 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.h +++ b/source-code/source/plugins/TLAC/Components/Pause.h @@ -59,6 +59,7 @@ namespace TLAC::Components static bool hookedGiveUpFunc(void* cls); static void hookedDivaPVEndFunc(uint64_t, char, char); + static char hookedScriptCommandFunc(uint64_t, uint64_t, uint64_t, void*, void*, char, char); static void setSEVolume(int amount); @@ -199,13 +200,15 @@ namespace TLAC::Components unpause(); } - static void giveup() { + static void giveup() + { ignoreAutoPause = false; autoReplay = false; giveUp = true; }; - static void sevolorpvmenu() { + static void sevolorpvmenu() + { setMenuPos(isInPV() ? MENUSET_PV : MENUSET_SEVOL, 1); }; @@ -214,8 +217,14 @@ namespace TLAC::Components static void sevolplus() { setSEVolume(10); }; static void sevolminus() { setSEVolume(-10); }; - static bool isInPV() { - return isInGame() && *(char*)0x140C94438 == 2; + static bool isInPV(bool checkIsInGame = true) + { + if (checkIsInGame && !isInGame()) + { + return false; + } + + return *(char*)0x140C94438 == 2; } // contents are in Pause.cpp because they can't be inline here for a static (const) array/vec