mirror of
https://github.com/esuo1198/TaikoArcadeLoader.git
synced 2026-10-01 19:27:55 +03:00
optimize bnusio_GetAnalogIn
add High Resolution Timer move chs_voice to testmode remove garmc dirty logs fix pollasync keyboard & mouse wheel
This commit is contained in:
@@ -140,6 +140,7 @@ set(SOURCES
|
||||
# src/patches/qr.cpp
|
||||
src/patches/layeredfs.cpp
|
||||
src/patches/testmode.cpp
|
||||
src/patches/timer.cpp
|
||||
src/patches/versions/JPN00.cpp
|
||||
src/patches/versions/JPN08.cpp
|
||||
src/patches/versions/JPN39.cpp
|
||||
|
||||
+39
-45
@@ -125,10 +125,14 @@ bool valueStates[] = {false, false, false, false, false, false, false, false};
|
||||
Keybindings *analogButtons[]
|
||||
= {&P1_LEFT_BLUE, &P1_LEFT_RED, &P1_RIGHT_RED, &P1_RIGHT_BLUE, &P2_LEFT_BLUE, &P2_LEFT_RED, &P2_RIGHT_RED, &P2_RIGHT_BLUE};
|
||||
|
||||
u16 buttonWaitPeriodP1 = 0;
|
||||
u16 buttonWaitPeriodP2 = 0;
|
||||
std::queue<u8> buttonQueueP1;
|
||||
std::queue<u8> buttonQueueP2;
|
||||
u16 cooldown[8] = { 0 };
|
||||
u16 buttonWaitPeriod[] = { 0, 0 };
|
||||
std::queue<u8> buttonQueue[] = { {}, {} };
|
||||
|
||||
// u16 buttonWaitPeriodP1 = 0;
|
||||
// u16 buttonWaitPeriodP2 = 0;
|
||||
// std::queue<u8> buttonQueueP1;
|
||||
// std::queue<u8> buttonQueueP2;
|
||||
|
||||
bool analogInput;
|
||||
SDLAxis analogBindings[] = {
|
||||
@@ -139,52 +143,39 @@ SDLAxis analogBindings[] = {
|
||||
u16
|
||||
bnusio_GetAnalogIn (const u8 which) {
|
||||
if (analogInput) {
|
||||
if (const u16 analogValue = static_cast<u16> (32768 * ControllerAxisIsDown (analogBindings[which])); analogValue > 100) return analogValue;
|
||||
return 0;
|
||||
const u16 analogValue = static_cast<u16> (32768 * ControllerAxisIsDown (analogBindings[which]));
|
||||
if (analogValue > 100) return analogValue;
|
||||
else return 0;
|
||||
}
|
||||
const auto button = analogButtons[which];
|
||||
if (which == 0) {
|
||||
if (buttonWaitPeriodP1 > 0) buttonWaitPeriodP1--;
|
||||
if (buttonWaitPeriodP2 > 0) buttonWaitPeriodP2--;
|
||||
}
|
||||
if (const bool isP1 = which / 4 == 0; (isP1 && !buttonQueueP1.empty ()) || (!isP1 && !buttonQueueP2.empty ())) {
|
||||
if ((isP1 && buttonQueueP1.front () == which && buttonWaitPeriodP1 == 0)
|
||||
|| (!isP1 && buttonQueueP2.front () == which && buttonWaitPeriodP2 == 0)) {
|
||||
if (isP1) {
|
||||
buttonQueueP1.pop ();
|
||||
buttonWaitPeriodP1 = drumWaitPeriod;
|
||||
} else {
|
||||
buttonQueueP2.pop ();
|
||||
buttonWaitPeriodP2 = drumWaitPeriod;
|
||||
}
|
||||
const int blue = !(which % 4 % 3);
|
||||
const int player = which / 4;
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
return (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
if (IsButtonTapped (*button)) {
|
||||
if (isP1) buttonQueueP1.push (which);
|
||||
else buttonQueueP2.push (which);
|
||||
}
|
||||
return 0;
|
||||
} else if (IsButtonTapped (*button)) {
|
||||
if (isP1 && buttonWaitPeriodP1 > 0) {
|
||||
buttonQueueP1.push (which);
|
||||
return 0;
|
||||
}
|
||||
if (!isP1 && buttonWaitPeriodP2 > 0) {
|
||||
buttonQueueP2.push (which);
|
||||
return 0;
|
||||
}
|
||||
if (isP1) buttonWaitPeriodP1 = drumWaitPeriod;
|
||||
else buttonWaitPeriodP2 = drumWaitPeriod;
|
||||
u16 analogValue = 0;
|
||||
if (which == 0) {
|
||||
for (int i=0; i<2; i++) if (buttonWaitPeriod[i] > 0) buttonWaitPeriod[i]--;
|
||||
for (int i=0; i<8; i++) if (cooldown[i] > 0) cooldown[i]--;
|
||||
}
|
||||
if (buttonWaitPeriod[player] == 0 && !buttonQueue[player].empty () && buttonQueue[player].front () == which) {
|
||||
buttonQueue[player].pop ();
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
return (hitValue << 15) / 100 + 1;
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
if (IsButtonTapped (*button)) {
|
||||
if (drumWaitPeriod > 0) {
|
||||
if (blue && buttonWaitPeriod[player] > 0) buttonQueue[player].push (which);
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
} else if (blue && cooldown[which] > 0) return 0;
|
||||
|
||||
return 0;
|
||||
if (blue) cooldown[which] = 4;
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
return analogValue;
|
||||
}
|
||||
|
||||
u16 __fastcall bnusio_GetCoin (i32 a1) {
|
||||
@@ -277,10 +268,10 @@ void
|
||||
UpdateLoop () {
|
||||
LogMessage (LogLevel::WARN, "Using Async Update (experimental)!");
|
||||
std::unique_lock<std::mutex> syncLock(syncMtx);
|
||||
while (exited < 50) {
|
||||
while (exited < 120) {
|
||||
syncCV.wait (syncLock);
|
||||
#endif
|
||||
if (exited && ++exited >= 50) ExitProcess (0);
|
||||
if (exited && ++exited >= 120) ExitProcess (0);
|
||||
if (!inited) {
|
||||
windowHandle = FindWindowA ("nuFoundation.Window", nullptr);
|
||||
InitializePoll (windowHandle);
|
||||
@@ -301,7 +292,10 @@ UpdateLoop () {
|
||||
if (IsButtonTapped (COIN_ADD)) coin_count++;
|
||||
if (IsButtonTapped (SERVICE) && !testEnabled) service_count++;
|
||||
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
|
||||
if (IsButtonTapped (EXIT)) { exited += 1; testEnabled = 1; patches::Plugins::Exit (); }
|
||||
if (IsButtonTapped (EXIT)) {
|
||||
LogMessage (LogLevel::INFO, "Exit By Press Exit Button!");
|
||||
exited += 1; testEnabled = 1; patches::Plugins::Exit ();
|
||||
}
|
||||
if (GameVersion::CHN00 == gameVersion) {
|
||||
if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Qr::CommitLogin (accessCode1);
|
||||
if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Qr::CommitLogin (accessCode2);
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#define ASYNC_UPDATE
|
||||
// #define ASYNC_UPDATE
|
||||
namespace bnusio {
|
||||
void Init ();
|
||||
void Update ();
|
||||
|
||||
@@ -266,6 +266,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
patches::LayeredFs::Init ();
|
||||
patches::TestMode::Init ();
|
||||
|
||||
patches::Timer::Init ();
|
||||
|
||||
LogMessage (LogLevel::INFO, "==== Finished Loading patches!");
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -55,6 +55,7 @@ void Init ();
|
||||
void Append (const pugi::xml_node &node, const wchar_t *attr, const std::wstring &append);
|
||||
void SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode);
|
||||
int ReadTestModeValue (const wchar_t *itemId);
|
||||
void SetTestModeValue (const wchar_t *itemId, int value);
|
||||
Menu *CreateMenu (const std::wstring &menuName, const std::wstring &menuId);
|
||||
void RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod, Menu *menu);
|
||||
void RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod);
|
||||
@@ -114,4 +115,7 @@ std::vector<uint8_t> &ReadQRData (std::vector<uint8_t> &buffer);
|
||||
std::vector<uint8_t> &ReadQRImage (std::vector<uint8_t> &buffer);
|
||||
} // namespace Qr
|
||||
} // namespace Scanner
|
||||
namespace Timer {
|
||||
void Init ();
|
||||
} // namespace timer
|
||||
} // namespace patches
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace Qr {
|
||||
}
|
||||
std::vector<uint8_t> buffer = {};
|
||||
std::string accessQRDataBase = "BNTTCNID";
|
||||
if (!accessCode._Starts_with (accessQRDataBase))
|
||||
if (!accessCode.starts_with (accessQRDataBase))
|
||||
for (char word : accessQRDataBase) buffer.push_back (word);
|
||||
for (char word : accessCode) buffer.push_back (word);
|
||||
return patches::Scanner::Qr::Commit (buffer);
|
||||
|
||||
@@ -82,7 +82,10 @@ public:
|
||||
if (size == 0) return node;
|
||||
size_t maxPage = size <= 14 ? 1 : (size / 13 + (size % 13 > 0));
|
||||
LogMessage (LogLevel::DEBUG, "Render testmode menu with items(size={}, page={})", size, maxPage);
|
||||
std::wstring parentId = node->parent ().parent ().attribute (L"id").value ();
|
||||
std::wstring menuName = L"menu";
|
||||
pugi::xml_node parentNode = node->parent ();
|
||||
while (parentNode.name() != menuName) parentNode = parentNode.parent ();
|
||||
std::wstring parentId = parentNode.attribute (L"id").value ();
|
||||
|
||||
pugi::xml_document menuItem;
|
||||
menuItem.load_string (std::format (L"<root><menu-item label=\"{}\" menu=\"{}\"/></root>", this->menuName, this->menuId).c_str ());
|
||||
@@ -289,6 +292,16 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
originalTestModeSetMenuHook (testModeLibrary, fileName.c_str ());
|
||||
}
|
||||
|
||||
// HOOK_DYNAMIC (void, TestModeGetValueHook, u64 *reader, const wchar_t *lItemName, int *value) {
|
||||
// originalTestModeGetValueHook (reader, lItemName, value);
|
||||
// LogMessage (LogLevel::DEBUG, L"TestMode get Item: {} Value: {}", lItemName, *value);
|
||||
// }
|
||||
|
||||
// HOOK_DYNAMIC (void, TestModeSetValueHook, u64 *reader, const wchar_t *lItemName, int value) {
|
||||
// LogMessage (LogLevel::DEBUG, L"TestMode set Item: {} Value: {}", lItemName, value);
|
||||
// originalTestModeSetValueHook (reader, lItemName, value);
|
||||
// }
|
||||
|
||||
void
|
||||
CommonModify () {
|
||||
// Default off Close time
|
||||
@@ -424,7 +437,14 @@ Init () {
|
||||
const auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
|
||||
const u64 testModeSetMenuAddress = PROC_ADDRESS_OFFSET ("TestModeLibrary.dll", 0x99D0);
|
||||
const u64 testModeLibrary = (u64)GetModuleHandle ("TestModeLibrary.dll");
|
||||
const u64 testModeSetMenu = testModeLibrary + 0x99D0;
|
||||
// const u64 testModeGetValue = testModeLibrary + 0x6FB18;
|
||||
// const u64 testModeSetValue = testModeLibrary + 0x6FAC8;
|
||||
|
||||
LogMessage (LogLevel::DEBUG, "TestModeLibrary: {}", testModeLibrary);
|
||||
// LogMessage (LogLevel::DEBUG, "TestModeLibrary set: {}", testModeSetValue);
|
||||
// LogMessage (LogLevel::DEBUG, "TestModeLibrary get: {}", testModeGetValue);
|
||||
switch (gameVersion) {
|
||||
case GameVersion::UNKNOWN: break;
|
||||
case GameVersion::JPN00: break;
|
||||
@@ -442,7 +462,9 @@ Init () {
|
||||
|
||||
CommonModify ();
|
||||
|
||||
INSTALL_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenuAddress);
|
||||
INSTALL_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenu);
|
||||
// INSTALL_HOOK_DYNAMIC (TestModeGetValueHook, testModeGetValue);
|
||||
// INSTALL_HOOK_DYNAMIC (TestModeSetValueHook, testModeSetValue);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -457,7 +479,9 @@ ReadTestModeValue (const wchar_t *itemId) {
|
||||
if (const u64 testModeMain = refTestMode (appAccessor)) {
|
||||
int value = 0;
|
||||
u64 *reader = *reinterpret_cast<u64 **> (testModeMain + 16);
|
||||
// LogMessage (LogLevel::DEBUG, "TestMode get:{} set:{}", *reader + 256, *reader + 176);
|
||||
(*reinterpret_cast<void (__fastcall **) (u64 *, const wchar_t *, int *)> (*reader + 256)) (reader, itemId, &value);
|
||||
// originalTestModeGetValueHook (reader, itemId, &value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -465,6 +489,17 @@ ReadTestModeValue (const wchar_t *itemId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
SetTestModeValue (const wchar_t *itemId, int value) {
|
||||
if (appAccessor) {
|
||||
if (const u64 testModeMain = refTestMode (appAccessor)) {
|
||||
u64 *reader = *reinterpret_cast<u64 **> (testModeMain + 16);
|
||||
(*reinterpret_cast<void (__fastcall **) (u64 *, const wchar_t *, int)> (*reader + 176)) (reader, itemId, value);
|
||||
// ((TestModeSetValueHook)whereTestModeSetMenuHook) (reader, itemId, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu *
|
||||
CreateMenu (const std::wstring &menuName, const std::wstring &menuId) {
|
||||
LogMessage (LogLevel::DEBUG, L"Create MenuName: {} MenuId: {}", menuName, menuId);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "constants.h"
|
||||
#include "helpers.h"
|
||||
#include "patches.h"
|
||||
|
||||
extern "C" NTSTATUS NTAPI NtSetTimerResolution(
|
||||
IN ULONG DesiredResolution,
|
||||
IN BOOLEAN SetResolution,
|
||||
OUT PULONG CurrentResolution
|
||||
);
|
||||
|
||||
extern "C" NTSTATUS NTAPI NtQueryTimerResolution(
|
||||
OUT PULONG CurrentResolution,
|
||||
OUT PULONG MinimumResolution,
|
||||
OUT PULONG MaximumResolution
|
||||
);
|
||||
|
||||
namespace patches::Timer {
|
||||
ULONG currentResolution = 0;
|
||||
ULONG minimumResolution = 0;
|
||||
ULONG maximumResolution = 0;
|
||||
|
||||
void
|
||||
Release () {
|
||||
NtSetTimerResolution(currentResolution, FALSE, ¤tResolution);
|
||||
}
|
||||
|
||||
void
|
||||
Init () {
|
||||
NTSTATUS queryStatus = NtQueryTimerResolution(¤tResolution, &minimumResolution, &maximumResolution);
|
||||
if (queryStatus == 0) {
|
||||
bool setHighResolutionTimer = currentResolution > maximumResolution;
|
||||
LogMessage (LogLevel::INFO, "Timer Resolution current: {}ms maximum: {}ms", currentResolution / 10000.0, maximumResolution / 10000.0);
|
||||
|
||||
if (setHighResolutionTimer) {
|
||||
NTSTATUS status = NtSetTimerResolution(maximumResolution, TRUE, ¤tResolution);
|
||||
if (status == 0) {
|
||||
LogMessage (LogLevel::INFO, "Successfully change Timer resolution to {}ms", maximumResolution / 10000.0);
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR, "Failed to change Timer resolution, status={}", status);
|
||||
}
|
||||
atexit (Release);
|
||||
}
|
||||
} else LogMessage (LogLevel::ERROR, "Failed to query Timer resolution, status={}", queryStatus);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,10 @@ HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) {
|
||||
originalcurl_easy_setopt (a1, 81, 0, 0, 0);
|
||||
return originalcurl_easy_setopt (a1, a2, a3, a4, a5);
|
||||
}
|
||||
HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) {
|
||||
// remove garmc log
|
||||
return;
|
||||
}
|
||||
|
||||
FUNCTION_PTR (i64, GetPlayDataManagerRef, ASLR (0x140024AC0), i64);
|
||||
|
||||
@@ -50,6 +54,7 @@ HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) {
|
||||
LogMessage (LogLevel::HOOKS, "DeviceCheck was called");
|
||||
TestMode::SetupAccessor (a3, RefTestModeMain);
|
||||
componentAccessor = a2;
|
||||
appAccessor = a3;
|
||||
return originalDeviceCheck (a1, a2, a3);
|
||||
}
|
||||
|
||||
@@ -75,7 +80,8 @@ MID_HOOK (DifficultyPanelCrown, ASLR (0x1403F2A25), SafetyHookContext &ctx) {
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo024 was called");
|
||||
if (const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); tournamentMode == 1) return originalAvailableMode_Collabo024 (a1);
|
||||
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo024 (a1);
|
||||
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo024");
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo024 (a1);
|
||||
@@ -240,7 +246,7 @@ get_bank_id (const std::string &bankName) {
|
||||
void
|
||||
check_voice_tail (const std::string &bankName, u8 *pBinfBlock, std::map<std::string, bool> &voiceExist, const std::string &tail) {
|
||||
// check if any voice_xxx.nus3bank has xxx_cn audio inside while loading
|
||||
if (enableSwitchVoice && bankName.starts_with ("voice_")) {
|
||||
if (bankName.starts_with ("voice_")) {
|
||||
const int binfLength = *reinterpret_cast<int *> (pBinfBlock + 4);
|
||||
u8 *pGrpBlock = pBinfBlock + 8 + binfLength;
|
||||
const int grpLength = *reinterpret_cast<int *> (pGrpBlock + 4);
|
||||
@@ -261,7 +267,10 @@ check_voice_tail (const std::string &bankName, u8 *pBinfBlock, std::map<std::str
|
||||
if (titleOffset > 0) {
|
||||
std::string title (reinterpret_cast<char *> (currToneBase + titleOffset));
|
||||
if (title.ends_with (tail)) {
|
||||
if (!voiceExist.contains (bankName) || !voiceExist[bankName]) voiceExist[bankName] = true;
|
||||
if (!voiceExist.contains (bankName) || !voiceExist[bankName]) {
|
||||
voiceExist[bankName] = true;
|
||||
enableSwitchVoice = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -288,32 +297,34 @@ MID_HOOK (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) {
|
||||
}
|
||||
|
||||
std::string
|
||||
FixToneName (const std::string &bankName, std::string toneName) {
|
||||
if (language == 2 || language == 4) {
|
||||
FixToneName (const std::string &bankName, std::string toneName, int voiceLang) {
|
||||
if (voiceLang == 1) {
|
||||
if (voiceCnExist.contains (bankName) && voiceCnExist[bankName]) return toneName + "_cn";
|
||||
}
|
||||
return toneName;
|
||||
}
|
||||
|
||||
size_t commonSize = 0;
|
||||
HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySound was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundMain was called");
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName (lua_tolstring (a1, -3, &commonSize));
|
||||
if (bankName[0] == 'v') {
|
||||
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize)).c_str ());
|
||||
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize), lang).c_str ());
|
||||
lua_replace (a1, -3);
|
||||
}
|
||||
}
|
||||
return originalPlaySound (a1);
|
||||
return originalPlaySoundMain (a1);
|
||||
}
|
||||
|
||||
HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundMulti was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName (const_cast<char *> (lua_tolstring (a1, -3, &commonSize)));
|
||||
if (bankName[0] == 'v') {
|
||||
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize)).c_str ());
|
||||
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize), lang).c_str ());
|
||||
lua_replace (a1, -3);
|
||||
}
|
||||
}
|
||||
@@ -323,8 +334,8 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
FUNCTION_PTR (u64 *, append_chars_to_basic_string, ASLR (0x140028DA0), u64 *, const char *, size_t);
|
||||
|
||||
u64 *
|
||||
FixToneNameEnso (u64 *Src, const std::string &bankName) {
|
||||
if (language == 2 || language == 4) {
|
||||
FixToneNameEnso (u64 *Src, const std::string &bankName, int voiceLang) {
|
||||
if (voiceLang == 1) {
|
||||
if (voiceCnExist.contains (bankName) && voiceCnExist[bankName]) Src = append_chars_to_basic_string (Src, "_cn", 3);
|
||||
}
|
||||
return Src;
|
||||
@@ -332,18 +343,20 @@ FixToneNameEnso (u64 *Src, const std::string &bankName) {
|
||||
|
||||
HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundEnso was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang);
|
||||
}
|
||||
return originalPlaySoundEnso (a1, a2, a3);
|
||||
}
|
||||
|
||||
HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundSpecial was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang);
|
||||
}
|
||||
return originalPlaySoundSpecial (a1, a2);
|
||||
}
|
||||
@@ -437,6 +450,23 @@ HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (DWORD*, AcquireMostCompatibleDisplayMode, ASLR (0x14064C870), i64 a1, DWORD *a2, DWORD *a3) {
|
||||
LogMessage (LogLevel::DEBUG, "AcquireMostCompatibleDisplayMode {:d} {:d} {:f} {:f}", a3[0], a3[1], (float)(int)a3[2], (float)(int)a3[3]);
|
||||
a3[2] = (DWORD)(int)120.0f;
|
||||
LogMessage (LogLevel::DEBUG, "AcquireMostCompatibleDisplayMode {:d} {:d} {:f} {:f}", a3[0], a3[1], (float)(int)a3[2], (float)(int)a3[3]);
|
||||
return originalAcquireMostCompatibleDisplayMode (a1, a2, a3);
|
||||
}
|
||||
|
||||
HOOK (char, SceneTestModeLoading, ASLR (0x1404793D0), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin SceneTestModeLoading");
|
||||
char result = originalSceneTestModeLoading (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End originalSceneTestModeLoading");
|
||||
TestMode::SetTestModeValue (L"EnableSwitchVoice", (int)enableSwitchVoice);
|
||||
if (!enableSwitchVoice) TestMode::SetTestModeValue (L"VoiceLanguageItem", 0);
|
||||
LogMessage (LogLevel::DEBUG, "End SceneTestModeLoading");
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
|
||||
safetyhook::Allocation datatableBuffer1;
|
||||
safetyhook::Allocation datatableBuffer2;
|
||||
@@ -506,15 +536,13 @@ Init () {
|
||||
INSTALL_HOOK (EnsoGraphicManagerPreparing);
|
||||
INSTALL_HOOK (EnsoGameManagerStart);
|
||||
INSTALL_HOOK (EnsoGameManagerChechEnsoEnd);
|
||||
INSTALL_HOOK (AcquireMostCompatibleDisplayMode);
|
||||
INSTALL_HOOK (SceneTestModeLoading);
|
||||
|
||||
// Apply common config patch
|
||||
WRITE_MEMORY (ASLR (0x140494533), i32, xRes);
|
||||
WRITE_MEMORY (ASLR (0x14049453A), i32, yRes);
|
||||
if (!vsync) WRITE_MEMORY (ASLR (0x14064C7E9), u8, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x90);
|
||||
if (unlockSongs) {
|
||||
WRITE_MEMORY (ASLR (0x1403F45CF), u8, 0xB0, 0x01);
|
||||
INSTALL_MID_HOOK (CountLockedCrown);
|
||||
}
|
||||
|
||||
// Bypass errors
|
||||
WRITE_MEMORY (ASLR (0x140041A00), u8, 0xC3);
|
||||
@@ -564,18 +592,39 @@ Init () {
|
||||
ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ());
|
||||
}
|
||||
|
||||
// Fix Language
|
||||
TestMode::RegisterItem(
|
||||
// Language
|
||||
TestMode::Menu *langPatchesMenu = TestMode::CreateMenu (L"LANGUAGE PATCHES", L"LanguagePatchesMenu");
|
||||
TestMode::Menu *langResourceIndicator = TestMode::CreateMenu (L"RESOURCE INDICATOR", L"LanguageResourceIndicatorMenu");
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"FIX LANGUAGE\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModFixLanguage\" max=\"1\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (GetLanguage);
|
||||
INSTALL_HOOK (GetRegionLanguage);
|
||||
INSTALL_HOOK (GetCabinetLanguage);
|
||||
}, langPatchesMenu
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"CHS_VOICE FILE\" param-offset-x=\"35\" id=\"EnableSwitchVoice\" select-skip=\"True\" "
|
||||
L"replace-text=\"0:@Color/Red;NONE@Color/Default;, 1:@Color/Lime;FOUND@Color/Default;\" param-color=\"Color/White\"/>",
|
||||
langResourceIndicator
|
||||
);
|
||||
TestMode::RegisterItemAfter(
|
||||
L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='LanguageItem']",
|
||||
L"<select-item label=\"VOICE\" param-offset-x=\"35\" invisible=\"True/EnableSwitchVoice:0\" disable=\"True/EnableSwitchVoice:0\" "
|
||||
L"replace-text=\"0:JPN, 1:CHN\" group=\"Setting\" id=\"VoiceLanguageItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&](){
|
||||
INSTALL_HOOK (PlaySoundMain);
|
||||
INSTALL_HOOK (PlaySoundMulti);
|
||||
INSTALL_HOOK (PlaySoundEnso);
|
||||
INSTALL_HOOK (PlaySoundSpecial);
|
||||
}
|
||||
);
|
||||
TestMode::RegisterItem(langResourceIndicator, langPatchesMenu);
|
||||
TestMode::RegisterItem(langPatchesMenu);
|
||||
|
||||
// Unlock Songs
|
||||
TestMode::RegisterItem(
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"UNLOCK SONGS\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON, "
|
||||
L"2:FORCE\" group=\"Setting\" id=\"ModUnlockSongs\" max=\"2\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
@@ -653,6 +702,7 @@ Init () {
|
||||
L"replace-text=\"0:ON, 1:OFF\" group=\"Setting\" id=\"AttractDemoItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&](){ INSTALL_MID_HOOK (AttractDemo); }
|
||||
);
|
||||
|
||||
// for (size_t i=0; i < 40; i++) TestMode::RegisterItem(std::format (L"<text-item label=\"TEST{}\"/>", i + 1));
|
||||
|
||||
// Instant Result
|
||||
@@ -696,23 +746,6 @@ Init () {
|
||||
});
|
||||
}
|
||||
|
||||
// Fix language
|
||||
if (fixLanguage) {
|
||||
INSTALL_HOOK (GetLanguage); // Language will use in other place
|
||||
INSTALL_HOOK (GetRegionLanguage);
|
||||
INSTALL_HOOK (GetCabinetLanguage);
|
||||
}
|
||||
|
||||
// if both chsPatch & fixLanguage enabled, try use cn voice from nus3bank
|
||||
// don't worry, we will check if cn voice existed
|
||||
if (chsPatch && fixLanguage) {
|
||||
enableSwitchVoice = true;
|
||||
INSTALL_HOOK (PlaySound);
|
||||
INSTALL_HOOK (PlaySoundMulti);
|
||||
INSTALL_HOOK (PlaySoundEnso);
|
||||
INSTALL_HOOK (PlaySoundSpecial);
|
||||
}
|
||||
|
||||
// Fix normal song play after passing through silent song
|
||||
INSTALL_MID_HOOK (GenNus3bankId);
|
||||
INSTALL_HOOK (LoadedBankAll);
|
||||
@@ -734,5 +767,6 @@ Init () {
|
||||
// Redirect garmc requests
|
||||
auto garmcHandle = reinterpret_cast<u64> (GetModuleHandle ("garmc.dll"));
|
||||
INSTALL_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast<void *> (garmcHandle + 0x1FBBB0));
|
||||
INSTALL_HOOK_DYNAMIC (garmc_logger_log, reinterpret_cast<void *> (garmcHandle + 0x13AB70));
|
||||
}
|
||||
} // namespace patches::JPN39
|
||||
|
||||
+98
-68
@@ -5,6 +5,10 @@
|
||||
extern bool jpLayout;
|
||||
extern int exited;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
bool wndForeground = false;
|
||||
|
||||
bool currentKeyboardState[0xFF] = { false };
|
||||
@@ -13,6 +17,12 @@ int keyboardDiff[0xFF] = { 0 };
|
||||
bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX] = { false };
|
||||
int controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 };
|
||||
int controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 };
|
||||
char currentMouseWheelDirection = 0;
|
||||
int mouseWheelCount[2] = { 0 };
|
||||
int mouseWheelDiff[2] = { 0 };
|
||||
|
||||
int maxCount = 1;
|
||||
|
||||
SDLAxisState currentControllerAxisState;
|
||||
|
||||
SDL_Window *window;
|
||||
@@ -96,7 +106,7 @@ LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
DWORD keyCode = pKeyboard->vkCode;
|
||||
switch (wParam) {
|
||||
case WM_KEYDOWN: if (wndForeground) {
|
||||
if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] ++;
|
||||
if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] = MIN (keyboardCount[keyCode] + 1, maxCount);
|
||||
currentKeyboardState[keyCode] = true;
|
||||
} break;
|
||||
// keyup will accepted even if you're not focus in this window
|
||||
@@ -118,63 +128,14 @@ DisposeKeyboard () {
|
||||
if (keyboardHook) UnhookWindowsHookEx(keyboardHook);
|
||||
}
|
||||
|
||||
void
|
||||
UpdateLoop () {
|
||||
LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop");
|
||||
SDL_Event event;
|
||||
SDL_GameController *controller;
|
||||
while (!exited) {
|
||||
while (SDL_WaitEvent (&event) != 0) {
|
||||
switch (event.type) {
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
|
||||
controller = SDL_GameControllerOpen (event.cdevice.which);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
|
||||
+ ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "Controller connected!");
|
||||
controllers[event.cdevice.which] = controller;
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
LogMessage (LogLevel::DEBUG, "Controller removed!");
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
SDL_GameControllerClose (controllers[event.cdevice.which]);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
if (wndForeground) {
|
||||
if (event.wheel.y > 0) currentMouseState.ScrolledUp = true;
|
||||
else if (event.wheel.y < 0) currentMouseState.ScrolledDown = true;
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
// keyup will accepted even if you're not focus in this window
|
||||
currentControllerButtonsState[event.cbutton.button] = false; break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
if (wndForeground) {
|
||||
if (!currentControllerButtonsState[event.cbutton.button]) controllerCount[event.cbutton.button]++;
|
||||
currentControllerButtonsState[event.cbutton.button] = true;
|
||||
} else LogMessage (LogLevel::WARN, "Controller button pressed but window not focused!");
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
float sensorValue = event.caxis.value == 0 ? 0 : event.caxis.value / (event.caxis.value > 0 ? 32767.0f : -32768.0f);
|
||||
if (wndForeground || sensorValue == 0) {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = sensorValue; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// void
|
||||
// UpdateLoop () {
|
||||
// LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop");
|
||||
|
||||
// while (!exited) {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
bool
|
||||
InitializePoll (HWND windowHandle) {
|
||||
@@ -223,8 +184,8 @@ InitializePoll (HWND windowHandle) {
|
||||
|
||||
atexit (DisposePoll);
|
||||
|
||||
updatePollThread = std::thread (UpdateLoop);
|
||||
updatePollThread.detach ();
|
||||
// updatePollThread = std::thread (UpdateLoop);
|
||||
// updatePollThread.detach ();
|
||||
|
||||
return hasRumble;
|
||||
}
|
||||
@@ -243,15 +204,78 @@ void
|
||||
UpdatePoll (HWND windowHandle) {
|
||||
if (!CheckForegroundWindow (windowHandle)) return;
|
||||
|
||||
// currentMouseState.ScrolledUp = false;
|
||||
// currentMouseState.ScrolledDown = false;
|
||||
currentMouseState.ScrolledUp = false;
|
||||
currentMouseState.ScrolledDown = false;
|
||||
for (int i=0; i<255; i++) keyboardCount[i] -= (bool)keyboardDiff[i];
|
||||
for (int i=0; i<SDL_CONTROLLER_BUTTON_MAX; i++) controllerCount[i] -= (bool)controllerDiff[i];
|
||||
for (int i=0; i<2; i++) if (mouseWheelCount[i] > 0) mouseWheelCount[i] -= (bool)mouseWheelDiff[i];
|
||||
std::fill_n (keyboardDiff, 0xFF, 0);
|
||||
std::fill_n (controllerDiff, SDL_CONTROLLER_BUTTON_MAX, 0);
|
||||
std::fill_n (mouseWheelDiff, 2, 0);
|
||||
|
||||
// GetCursorPos (¤tMouseState.Position);
|
||||
// ScreenToClient (windowHandle, ¤tMouseState.Position);
|
||||
SDL_Event event;
|
||||
SDL_GameController *controller;
|
||||
while (SDL_PollEvent (&event) != 0) {
|
||||
// LogMessage (LogLevel::DEBUG, "Receive SDL Event! type={}", (u64)event.type);
|
||||
switch (event.type) {
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
controller = SDL_GameControllerOpen (event.cdevice.which);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
|
||||
+ ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "Controller connected!");
|
||||
controllers[event.cdevice.which] = controller;
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
LogMessage (LogLevel::DEBUG, "Controller removed!");
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
SDL_GameControllerClose (controllers[event.cdevice.which]);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
if (wndForeground) {
|
||||
// LogMessage (LogLevel::DEBUG, "Mouse Wheel moves {}", event.wheel.y);
|
||||
if (event.wheel.y > 0) {
|
||||
mouseWheelCount[0] = MIN (mouseWheelCount[0] + event.wheel.y, maxCount);
|
||||
mouseWheelCount[1] = 0;
|
||||
currentMouseState.ScrolledUp = true;
|
||||
} else if (event.wheel.y < 0) {
|
||||
mouseWheelCount[1] = MIN (mouseWheelCount[1] - event.wheel.y, maxCount);
|
||||
mouseWheelCount[0] = 0;
|
||||
currentMouseState.ScrolledDown = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
// keyup will accepted even if you're not focus in this window
|
||||
currentControllerButtonsState[event.cbutton.button] = false; break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
if (wndForeground) {
|
||||
if (!currentControllerButtonsState[event.cbutton.button]) {
|
||||
controllerCount[event.cbutton.button] = MIN (controllerCount[event.cbutton.button] + 1, maxCount);
|
||||
}
|
||||
currentControllerButtonsState[event.cbutton.button] = true;
|
||||
} else LogMessage (LogLevel::WARN, "Controller button pressed but window not focused!");
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
float sensorValue = event.caxis.value == 0 ? 0 : event.caxis.value / (event.caxis.value > 0 ? 32767.0f : -32768.0f);
|
||||
if (wndForeground || sensorValue == 0) {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = sensorValue; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -330,16 +354,22 @@ GetMouseScrollDown () {
|
||||
|
||||
bool
|
||||
GetMouseScrollIsDown (const Scroll scroll) {
|
||||
return false;
|
||||
// if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
|
||||
// else return GetMouseScrollDown ();
|
||||
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
|
||||
else return GetMouseScrollDown ();
|
||||
}
|
||||
|
||||
int maxWheelCount = 1;
|
||||
bool
|
||||
GetMouseScrollIsTapped (const Scroll scroll) {
|
||||
return false;
|
||||
// if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp () && !GetWasMouseScrollUp ();
|
||||
// else return GetMouseScrollDown () && !GetWasMouseScrollDown ();
|
||||
if (scroll == MOUSE_SCROLL_INVALID) return false;
|
||||
if (mouseWheelCount[scroll - 1] > 0) {
|
||||
if (maxWheelCount < mouseWheelCount[scroll - 1]) {
|
||||
maxWheelCount = mouseWheelCount[scroll - 1];
|
||||
LogMessage (LogLevel::DEBUG, "MAX WHEEL COLLECTED {} {}", (int)scroll, maxWheelCount);
|
||||
}
|
||||
mouseWheelDiff[scroll - 1] = 1;
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
Reference in New Issue
Block a user