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:
ptmaster
2024-12-07 06:22:53 +08:00
parent bb3f18a280
commit 0d4ca8b79e
10 changed files with 305 additions and 160 deletions
+1
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
#pragma once
#define ASYNC_UPDATE
// #define ASYNC_UPDATE
namespace bnusio {
void Init ();
void Update ();
+2
View File
@@ -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;
+4
View File
@@ -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
+1 -1
View File
@@ -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);
+38 -3
View File
@@ -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);
+45
View File
@@ -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, &currentResolution);
}
void
Init () {
NTSTATUS queryStatus = NtQueryTimerResolution(&currentResolution, &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, &currentResolution);
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);
}
}
+76 -42
View File
@@ -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
View File
@@ -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 (&currentMouseState.Position);
// ScreenToClient (windowHandle, &currentMouseState.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