mirror of
https://github.com/esuo1198/TaikoArcadeLoader.git
synced 2026-09-29 10:18:13 +03:00
Merge pull request #21 from ryumiyax/Refactor
[Experimental] IO Refactor & High Resolution Timer & etc
This commit is contained in:
+4
-1
@@ -17,7 +17,8 @@ else()
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# Add project definitions
|
||||
# Add project definitions (Add ASYNC_UPDATE/ASYNC_IO to enable new async feature [experimental])
|
||||
# add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS -DASYNC_UPDATE)
|
||||
add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
# Include FetchContent module
|
||||
@@ -128,6 +129,7 @@ set(SOURCES
|
||||
src/helpers.cpp
|
||||
src/logger.cpp
|
||||
src/poll.cpp
|
||||
src/pollasync.cpp
|
||||
src/bnusio.cpp
|
||||
src/patches/amauth.cpp
|
||||
src/patches/dxgi.cpp
|
||||
@@ -138,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
|
||||
|
||||
@@ -135,4 +135,4 @@ cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build --config Release --target bnusio
|
||||
```
|
||||
|
||||
The compiled dll of TaikoArcadeLoader will be written in the `dist` folder.
|
||||
The compiled dll of TaikoArcadeLoader will be written in the `dist` folder.
|
||||
Vendored
+1
-1
@@ -15,7 +15,7 @@ version = "auto" # Patch version
|
||||
# | - JPN39: For use with Taiko JPN 39.06
|
||||
# | - CHN00: For use with Taiko CHN 00.32
|
||||
unlock_songs = true
|
||||
|
||||
high_res_timer = true # (experimental) Enable High Resolution Timer, which might improve judgement timing
|
||||
|
||||
[patches.chn00] # These patches are only available for version CHN00
|
||||
fix_language = false # Sync test mode language to attract etc
|
||||
|
||||
+135
-109
@@ -17,6 +17,7 @@ extern bool autoIme;
|
||||
extern bool emulateUsio;
|
||||
extern bool emulateCardReader;
|
||||
extern bool acceptInvalidCards;
|
||||
extern HWND hGameWnd;
|
||||
|
||||
typedef i32 (*callbackAttach) (i32, i32, i32 *);
|
||||
typedef void (*callbackTouch) (i32, i32, u8[168], u64);
|
||||
@@ -47,6 +48,9 @@ Keybindings P2_LEFT_BLUE = {.keycodes = {'Z'}};
|
||||
Keybindings P2_LEFT_RED = {.keycodes = {'X'}};
|
||||
Keybindings P2_RIGHT_RED = {.keycodes = {'C'}};
|
||||
Keybindings P2_RIGHT_BLUE = {.keycodes = {'V'}};
|
||||
// Keybindings ALL[] = { EXIT, TEST, SERVICE, DEBUG_UP, DEBUG_DOWN, DEBUG_ENTER, COIN_ADD,
|
||||
// CARD_INSERT_1, CARD_INSERT_2, QR_DATA_READ, QR_IMAGE_READ, P1_LEFT_BLUE, P1_LEFT_RED,
|
||||
// P1_RIGHT_RED, P1_RIGHT_BLUE, P2_LEFT_BLUE, P2_LEFT_RED, P2_RIGHT_RED, P2_RIGHT_BLUE };
|
||||
|
||||
int exited = 0;
|
||||
bool testEnabled = false;
|
||||
@@ -55,6 +59,7 @@ int service_count = 0;
|
||||
bool inited = false;
|
||||
bool updateByCoin = false;
|
||||
HWND windowHandle = nullptr;
|
||||
bool usePoll = false;
|
||||
HKL currentLayout;
|
||||
|
||||
namespace bnusio {
|
||||
@@ -118,16 +123,21 @@ bnusio_GetSwIn () {
|
||||
return sw;
|
||||
}
|
||||
|
||||
bool waitAll = false;
|
||||
u16 drumWaitPeriod = 4;
|
||||
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[] = {
|
||||
@@ -138,52 +148,40 @@ 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 bool 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) {
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
buttonQueue[player].pop ();
|
||||
|
||||
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 ((waitAll || blue) && buttonWaitPeriod[player] > 0) {
|
||||
buttonQueue[player].push (which);
|
||||
return analogValue;
|
||||
} else if ((waitAll || blue) && cooldown[which] > 0) return 0;
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
if (waitAll || blue) cooldown[which] = 4;
|
||||
|
||||
return 0;
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
return analogValue;
|
||||
}
|
||||
|
||||
u16 __fastcall bnusio_GetCoin (i32 a1) {
|
||||
@@ -193,30 +191,6 @@ u16 __fastcall bnusio_GetCoin (i32 a1) {
|
||||
u16 __fastcall bnusio_GetService (i32 a1) { return service_count; }
|
||||
}
|
||||
|
||||
void
|
||||
InspectWaitTouch (const i32 a1, const i32 a2, u8 _cardData[168], const u64 _touchData) {
|
||||
if (AreAllBytesZero (_cardData, 0x00, 168)) // This happens when you enter test mode.
|
||||
return touchCallback (a1, a2, _cardData, _touchData);
|
||||
|
||||
const bool valid = !AreAllBytesZero (_cardData, 0x50, 21);
|
||||
if (valid) {
|
||||
LogMessage (LogLevel::DEBUG, "Card is valid");
|
||||
} else {
|
||||
memcpy (_cardData + 0x50, _cardData + 0x2C, 16); // 16 to match felica lite serial number length
|
||||
LogMessage (LogLevel::DEBUG, "Card is usually not supported");
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < 168; ++i) {
|
||||
oss << std::setw (2) << std::setfill ('0') << std::hex << static_cast<int> (_cardData[i]) << " ";
|
||||
if ((i + 1) % 21 == 0) oss << "\n";
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::DEBUG, "A1: %d, A2: %d, Card data: \n%s", a1, a2, oss.str ().c_str ());
|
||||
|
||||
if (touchCallback) return valid ? touchCallback (a1, a2, _cardData, _touchData) : touchCallback (0, 0, _cardData, _touchData);
|
||||
}
|
||||
|
||||
FUNCTION_PTR (i64, bnusio_Open_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_Open"));
|
||||
FUNCTION_PTR (i64, bnusio_Close_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_Close"));
|
||||
FUNCTION_PTR (u64, bnusio_Communication_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_Communication"), i32);
|
||||
@@ -263,6 +237,65 @@ FUNCTION_PTR (i64, bnusio_DecCoin_Original, PROC_ADDRESS ("bnusio_original.dll",
|
||||
FUNCTION_PTR (u64, bnusio_DecService_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_DecService"), i32, u16);
|
||||
FUNCTION_PTR (i64, bnusio_ResetCoin_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_ResetCoin"));
|
||||
|
||||
#ifndef ASYNC_UPDATE
|
||||
void
|
||||
Update () {
|
||||
#else
|
||||
std::thread pollThread;
|
||||
std::thread updateThread;
|
||||
std::mutex syncMtx;
|
||||
std::condition_variable syncCV;
|
||||
|
||||
void
|
||||
UpdateLoop () {
|
||||
LogMessage (LogLevel::WARN, "(experimental) Using Async Update!");
|
||||
std::unique_lock<std::mutex> syncLock(syncMtx);
|
||||
while (exited < 120) {
|
||||
syncCV.wait (syncLock);
|
||||
#endif
|
||||
if (exited && ++exited >= 120) ExitProcess (0);
|
||||
|
||||
#ifndef ASYNC_IO
|
||||
if (!inited) {
|
||||
windowHandle = FindWindowA ("nuFoundation.Window", nullptr);
|
||||
InitializePoll (windowHandle);
|
||||
if (autoIme) {
|
||||
currentLayout = GetKeyboardLayout (0);
|
||||
auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE);
|
||||
ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS);
|
||||
}
|
||||
|
||||
patches::Plugins::Init ();
|
||||
inited = true;
|
||||
}
|
||||
|
||||
UpdatePoll (windowHandle);
|
||||
#endif
|
||||
std::vector<uint8_t> buffer = {};
|
||||
if (IsButtonTapped (COIN_ADD)) coin_count++;
|
||||
if (IsButtonTapped (SERVICE) && !testEnabled) service_count++;
|
||||
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
|
||||
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);
|
||||
} else {
|
||||
if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Card::Commit (accessCode1, chipId1);
|
||||
if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Card::Commit (accessCode2, chipId2);
|
||||
}
|
||||
if (IsButtonTapped (QR_DATA_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRData (buffer));
|
||||
if (IsButtonTapped (QR_IMAGE_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRImage (buffer));
|
||||
|
||||
patches::Plugins::Update ();
|
||||
patches::Scanner::Update ();
|
||||
#ifdef ASYNC_UPDATE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Init () {
|
||||
SetKeyboardButtons ();
|
||||
@@ -274,8 +307,8 @@ Init () {
|
||||
if (config_ptr) {
|
||||
const toml_table_t *config = config_ptr.get ();
|
||||
if (const auto controller = openConfigSection (config, "controller")) {
|
||||
drumWaitPeriod = static_cast<u16> (readConfigInt (controller, "wait_period", drumWaitPeriod));
|
||||
analogInput = readConfigBool (controller, "analog_input", analogInput);
|
||||
drumWaitPeriod = static_cast<u16> (readConfigInt (controller, "wait_period", drumWaitPeriod));
|
||||
analogInput = readConfigBool (controller, "analog_input", analogInput);
|
||||
if (analogInput) LogMessage (LogLevel::WARN, "Using analog input mode. All the keyboard drum inputs have been disabled.");
|
||||
}
|
||||
auto graphics = openConfigSection (config, "graphics");
|
||||
@@ -292,28 +325,31 @@ Init () {
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> keyConfig_ptr (openConfig (keyConfigPath), toml_free);
|
||||
if (keyConfig_ptr) {
|
||||
const toml_table_t *keyConfig = keyConfig_ptr.get ();
|
||||
SetConfigValue (keyConfig, "EXIT", &EXIT);
|
||||
SetConfigValue (keyConfig, "EXIT", &EXIT, &usePoll);
|
||||
|
||||
SetConfigValue (keyConfig, "TEST", &TEST);
|
||||
SetConfigValue (keyConfig, "SERVICE", &SERVICE);
|
||||
SetConfigValue (keyConfig, "DEBUG_UP", &DEBUG_UP);
|
||||
SetConfigValue (keyConfig, "DEBUG_DOWN", &DEBUG_DOWN);
|
||||
SetConfigValue (keyConfig, "DEBUG_ENTER", &DEBUG_ENTER);
|
||||
SetConfigValue (keyConfig, "TEST", &TEST, &usePoll);
|
||||
SetConfigValue (keyConfig, "SERVICE", &SERVICE, &usePoll);
|
||||
SetConfigValue (keyConfig, "DEBUG_UP", &DEBUG_UP, &usePoll);
|
||||
SetConfigValue (keyConfig, "DEBUG_DOWN", &DEBUG_DOWN, &usePoll);
|
||||
SetConfigValue (keyConfig, "DEBUG_ENTER", &DEBUG_ENTER, &usePoll);
|
||||
|
||||
SetConfigValue (keyConfig, "COIN_ADD", &COIN_ADD);
|
||||
SetConfigValue (keyConfig, "CARD_INSERT_1", &CARD_INSERT_1);
|
||||
SetConfigValue (keyConfig, "CARD_INSERT_2", &CARD_INSERT_2);
|
||||
SetConfigValue (keyConfig, "QR_DATA_READ", &QR_DATA_READ);
|
||||
SetConfigValue (keyConfig, "QR_IMAGE_READ", &QR_IMAGE_READ);
|
||||
SetConfigValue (keyConfig, "COIN_ADD", &COIN_ADD, &usePoll);
|
||||
SetConfigValue (keyConfig, "CARD_INSERT_1", &CARD_INSERT_1, &usePoll);
|
||||
SetConfigValue (keyConfig, "CARD_INSERT_2", &CARD_INSERT_2, &usePoll);
|
||||
SetConfigValue (keyConfig, "QR_DATA_READ", &QR_DATA_READ, &usePoll);
|
||||
SetConfigValue (keyConfig, "QR_IMAGE_READ", &QR_IMAGE_READ, &usePoll);
|
||||
|
||||
SetConfigValue (keyConfig, "P1_LEFT_BLUE", &P1_LEFT_BLUE);
|
||||
SetConfigValue (keyConfig, "P1_LEFT_RED", &P1_LEFT_RED);
|
||||
SetConfigValue (keyConfig, "P1_RIGHT_RED", &P1_RIGHT_RED);
|
||||
SetConfigValue (keyConfig, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE);
|
||||
SetConfigValue (keyConfig, "P2_LEFT_BLUE", &P2_LEFT_BLUE);
|
||||
SetConfigValue (keyConfig, "P2_LEFT_RED", &P2_LEFT_RED);
|
||||
SetConfigValue (keyConfig, "P2_RIGHT_RED", &P2_RIGHT_RED);
|
||||
SetConfigValue (keyConfig, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE);
|
||||
SetConfigValue (keyConfig, "P1_LEFT_BLUE", &P1_LEFT_BLUE, &usePoll);
|
||||
SetConfigValue (keyConfig, "P1_LEFT_RED", &P1_LEFT_RED, &usePoll);
|
||||
SetConfigValue (keyConfig, "P1_RIGHT_RED", &P1_RIGHT_RED, &usePoll);
|
||||
SetConfigValue (keyConfig, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE, &usePoll);
|
||||
SetConfigValue (keyConfig, "P2_LEFT_BLUE", &P2_LEFT_BLUE, &usePoll);
|
||||
SetConfigValue (keyConfig, "P2_LEFT_RED", &P2_LEFT_RED, &usePoll);
|
||||
SetConfigValue (keyConfig, "P2_RIGHT_RED", &P2_RIGHT_RED, &usePoll);
|
||||
SetConfigValue (keyConfig, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE, &usePoll);
|
||||
if (!usePoll) {
|
||||
LogMessage (LogLevel::WARN, "Only Keyboard config detected, disable poll!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!emulateUsio && !exists (std::filesystem::current_path () / "bnusio_original.dll")) {
|
||||
@@ -369,14 +405,20 @@ Init () {
|
||||
INSTALL_HOOK_DIRECT (bnusio_ResetCoin, bnusio_ResetCoin_Original);
|
||||
LogMessage (LogLevel::WARN, "USIO emulation disabled");
|
||||
}
|
||||
#ifdef ASYNC_UPDATE
|
||||
else {
|
||||
updateThread = std::thread (bnusio::UpdateLoop);
|
||||
updateThread.detach ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ASYNC_UPDATE
|
||||
void
|
||||
Update () {
|
||||
if (exited && ++exited >= 50) ExitProcess (0);
|
||||
if (!inited) {
|
||||
windowHandle = FindWindowA ("nuFoundation.Window", nullptr);
|
||||
InitializePoll (windowHandle);
|
||||
if (usePoll) InitializePoll (windowHandle);
|
||||
if (autoIme) {
|
||||
currentLayout = GetKeyboardLayout (0);
|
||||
auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE);
|
||||
@@ -386,31 +428,15 @@ Update () {
|
||||
patches::Plugins::Init ();
|
||||
inited = true;
|
||||
}
|
||||
|
||||
UpdatePoll (windowHandle);
|
||||
std::vector<uint8_t> buffer = {};
|
||||
if (IsButtonTapped (COIN_ADD) && !testEnabled) coin_count++;
|
||||
if (IsButtonTapped (SERVICE) && !testEnabled) service_count++;
|
||||
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
|
||||
if (IsButtonTapped (EXIT)) { exited += 1; testEnabled = 1; }
|
||||
if (GameVersion::CHN00 == gameVersion) {
|
||||
if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Qr::CommitLogin (accessCode1);
|
||||
if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Qr::CommitLogin (accessCode2);
|
||||
} else {
|
||||
if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Card::Commit (accessCode1, chipId1);
|
||||
if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Card::Commit (accessCode2, chipId2);
|
||||
}
|
||||
if (IsButtonTapped (QR_DATA_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRData (buffer));
|
||||
if (IsButtonTapped (QR_IMAGE_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRImage (buffer));
|
||||
|
||||
patches::Plugins::Update ();
|
||||
patches::Scanner::Update ();
|
||||
UpdatePoll (windowHandle, usePoll);
|
||||
syncCV.notify_all ();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Close () {
|
||||
if (autoIme) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS);
|
||||
patches::Plugins::Exit ();
|
||||
// patches::Plugins::Exit ();
|
||||
CleanupLogger ();
|
||||
}
|
||||
} // namespace bnusio
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#define ASYNC_UPDATE
|
||||
namespace bnusio {
|
||||
void Init ();
|
||||
void Update ();
|
||||
|
||||
+17
-2
@@ -22,6 +22,7 @@ char accessCode1[21] = "00000000000000000001";
|
||||
char accessCode2[21] = "00000000000000000002";
|
||||
char chipId1[33] = "00000000000000000000000000000001";
|
||||
char chipId2[33] = "00000000000000000000000000000002";
|
||||
bool highResTimer = true;
|
||||
bool windowed = false;
|
||||
bool autoIme = false;
|
||||
bool jpLayout = false;
|
||||
@@ -149,6 +150,11 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
|
||||
LogMessage (LogLevel::INFO, "Loading config...");
|
||||
|
||||
#ifdef ASYNC_IO
|
||||
LogMessage (LogLevel::WARN, "(experimental) Using Async IO!");
|
||||
InitializeKeyboard ();
|
||||
#endif
|
||||
|
||||
std::string version = "auto";
|
||||
const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml";
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
@@ -171,7 +177,10 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
std::strcat (placeId, countryCode.c_str ());
|
||||
std::strcat (placeId, "0FF0");
|
||||
}
|
||||
if (const auto patches = openConfigSection (config, "patches")) version = readConfigString (patches, "version", version);
|
||||
if (const auto patches = openConfigSection (config, "patches")) {
|
||||
version = readConfigString (patches, "version", version);
|
||||
highResTimer = readConfigBool (patches, "high_res_timer", highResTimer);
|
||||
}
|
||||
if (const auto emulation = openConfigSection (config, "emulation")) {
|
||||
emulateUsio = readConfigBool (emulation, "usio", emulateUsio);
|
||||
emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader);
|
||||
@@ -223,7 +232,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
GetPrivateProfileStringA ("card", "accessCode2", accessCode2, accessCode2, 21, ".\\card.ini");
|
||||
GetPrivateProfileStringA ("card", "chipId2", chipId2, chipId2, 33, ".\\card.ini");
|
||||
|
||||
LogMessage (LogLevel::WARN, "Loading patches, please wait...");
|
||||
LogMessage (LogLevel::INFO, "==== Loading patches, please wait...");
|
||||
|
||||
if (cursor) INSTALL_HOOK (ShowMouse);
|
||||
INSTALL_HOOK (ExitWindows);
|
||||
@@ -260,6 +269,12 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
patches::AmAuth::Init ();
|
||||
patches::LayeredFs::Init ();
|
||||
patches::TestMode::Init ();
|
||||
|
||||
if (highResTimer) {
|
||||
patches::Timer::Init ();
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::INFO, "==== Finished Loading patches!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -253,6 +253,7 @@ LayeredFsHandler (const std::string &originalFileName, const std::string ¤
|
||||
|
||||
HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
bool changed = false;
|
||||
const auto originalFileName = std::string (lpFileName);
|
||||
std::string currentFileName = originalFileName;
|
||||
LogMessage (LogLevel::HOOKS, ("CreateFileA: " + originalFileName).c_str ());
|
||||
@@ -260,23 +261,34 @@ HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPC
|
||||
if (!beforeHandlers.empty ()) {
|
||||
for (const auto handler : beforeHandlers) {
|
||||
std::string result = handler->handlerMethod (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
if (result != "") {
|
||||
currentFileName = result;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useLayeredFs) {
|
||||
const std::string result = LayeredFsHandler (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
if (result != "") {
|
||||
currentFileName = result;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!afterHandlers.empty ()) {
|
||||
for (const auto handler : afterHandlers) {
|
||||
std::string result = handler->handlerMethod (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
if (result != "") {
|
||||
currentFileName = result;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return originalCreateFileAHook (currentFileName.c_str (), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
LPCSTR pFinalFileName = changed ? currentFileName.c_str () : lpFileName;
|
||||
if (changed) LogMessage (LogLevel::DEBUG, "Final Redirect: {}", currentFileName);
|
||||
return originalCreateFileAHook (pFinalFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
|
||||
@@ -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::WARN, "(experimental) 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::WARN, "(experimental) Successfully change Timer resolution to {}ms", maximumResolution / 10000.0);
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR, "(experimental) Failed to change Timer resolution, status={}", status);
|
||||
}
|
||||
atexit (Release);
|
||||
}
|
||||
} else LogMessage (LogLevel::ERROR, "(experimental) Failed to query Timer resolution, status={}", queryStatus);
|
||||
}
|
||||
}
|
||||
+133
-101
@@ -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);
|
||||
}
|
||||
@@ -374,68 +387,85 @@ HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) {
|
||||
return originalSetMasterVolumeSpeaker (a1 > 100 ? 100 : a1);
|
||||
}
|
||||
|
||||
std::string *fontName = nullptr;
|
||||
HOOK (u8, SetupFontInfo, ASLR (0x14049D820), u64 a1, u64 a2, size_t a3, u64 a4) {
|
||||
LogMessage (LogLevel::HOOKS, "SetupFontInfo was called");
|
||||
if (fontName != nullptr) delete fontName;
|
||||
fontName = new std::string (reinterpret_cast<char *> (a1) + 120);
|
||||
return originalSetupFontInfo (a1, a2, a3, a4);
|
||||
}
|
||||
// std::string *fontName = nullptr;
|
||||
// HOOK (u8, SetupFontInfo, ASLR (0x14049D820), u64 a1, u64 a2, size_t a3, u64 a4) {
|
||||
// LogMessage (LogLevel::HOOKS, "SetupFontInfo was called");
|
||||
// if (fontName != nullptr) delete fontName;
|
||||
// fontName = new std::string (reinterpret_cast<char *> (a1) + 120);
|
||||
// return originalSetupFontInfo (a1, a2, a3, a4);
|
||||
// }
|
||||
|
||||
HOOK (u32, ReadFontInfoInt, ASLR (0x14049EAC0), u64 a1, u64 a2) {
|
||||
LogMessage (LogLevel::HOOKS, "ReadFontInfoInt was called");
|
||||
const std::string attribute (reinterpret_cast<char *> (a2));
|
||||
u32 result = originalReadFontInfoInt (a1, a2);
|
||||
if (fontName->starts_with ("cn_") && attribute == "offsetV") result += 1;
|
||||
return result;
|
||||
}
|
||||
// HOOK (u32, ReadFontInfoInt, ASLR (0x14049EAC0), u64 a1, u64 a2) {
|
||||
// LogMessage (LogLevel::HOOKS, "ReadFontInfoInt was called");
|
||||
// const std::string attribute (reinterpret_cast<char *> (a2));
|
||||
// u32 result = originalReadFontInfoInt (a1, a2);
|
||||
// if (fontName->starts_with ("cn_") && attribute == "offsetV") result += 1;
|
||||
// return result;
|
||||
// }
|
||||
|
||||
MID_HOOK (AttractDemo, ASLR (0x14045A720), SafetyHookContext &ctx) {
|
||||
if (TestMode::ReadTestModeValue (L"AttractDemoItem") == 1) ctx.r14 = 0;
|
||||
}
|
||||
|
||||
// HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize");
|
||||
// u64 result = originalEnsoGameManagerInitialize (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result);
|
||||
// return result;
|
||||
// }
|
||||
HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize");
|
||||
u64 result = originalEnsoGameManagerInitialize (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading");
|
||||
// u64 result = originalEnsoGameManagerLoading (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result);
|
||||
// return result;
|
||||
// }
|
||||
HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading");
|
||||
u64 result = originalEnsoGameManagerLoading (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing");
|
||||
// bool result = originalEnsoGameManagerPreparing (a1); // crashes here
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result);
|
||||
// return result;
|
||||
// }
|
||||
HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing");
|
||||
bool result = originalEnsoGameManagerPreparing (a1, a2, a3); // crashes here
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing");
|
||||
// u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result);
|
||||
// return result;
|
||||
// }
|
||||
HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing");
|
||||
u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart");
|
||||
// u64 result = originalEnsoGameManagerStart (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result);
|
||||
// return result;
|
||||
HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart");
|
||||
u64 result = originalEnsoGameManagerStart (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd");
|
||||
u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result);
|
||||
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 (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd");
|
||||
// u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result);
|
||||
// return result;
|
||||
// }
|
||||
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;
|
||||
@@ -471,7 +501,6 @@ Init () {
|
||||
i32 yRes = 1080;
|
||||
bool vsync = false;
|
||||
bool unlockSongs = true;
|
||||
bool fixLanguage = false;
|
||||
bool chsPatch = false;
|
||||
bool useLayeredfs = false;
|
||||
|
||||
@@ -481,7 +510,6 @@ Init () {
|
||||
if (auto patches = openConfigSection (config_ptr.get (), "patches")) {
|
||||
unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
|
||||
if (auto jpn39 = openConfigSection (patches, "jpn39")) {
|
||||
fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage);
|
||||
chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
|
||||
}
|
||||
}
|
||||
@@ -500,21 +528,19 @@ Init () {
|
||||
// Hook to get AppAccessor and ComponentAccessor
|
||||
INSTALL_HOOK (DeviceCheck);
|
||||
INSTALL_HOOK (luaL_newstate);
|
||||
// INSTALL_HOOK (EnsoGameManagerInitialize);
|
||||
// INSTALL_HOOK (EnsoGameManagerLoading);
|
||||
// INSTALL_HOOK (EnsoGameManagerPreparing);
|
||||
// INSTALL_HOOK (EnsoGraphicManagerPreparing);
|
||||
// INSTALL_HOOK (EnsoGameManagerStart);
|
||||
// INSTALL_HOOK (EnsoGameManagerChechEnsoEnd);
|
||||
INSTALL_HOOK (EnsoGameManagerInitialize);
|
||||
INSTALL_HOOK (EnsoGameManagerLoading);
|
||||
INSTALL_HOOK (EnsoGameManagerPreparing);
|
||||
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 +590,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 +700,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
|
||||
@@ -683,8 +731,8 @@ Init () {
|
||||
WRITE_MEMORY (ASLR (0x140CD1E68), wchar_t, L"加載中..\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加載中...\0");
|
||||
INSTALL_MID_HOOK (ChangeLanguageType);
|
||||
INSTALL_HOOK (SetupFontInfo);
|
||||
INSTALL_HOOK (ReadFontInfoInt);
|
||||
// INSTALL_HOOK (SetupFontInfo);
|
||||
// INSTALL_HOOK (ReadFontInfoInt);
|
||||
}
|
||||
|
||||
LayeredFs::RegisterBefore ([=] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string {
|
||||
@@ -696,23 +744,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 +765,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
|
||||
|
||||
+8
-305
@@ -1,311 +1,9 @@
|
||||
#include "poll.h"
|
||||
|
||||
#ifndef ASYNC_IO
|
||||
#include "polldef.h"
|
||||
extern bool jpLayout;
|
||||
|
||||
struct KeyCodePair {
|
||||
const char *string;
|
||||
u8 keycode;
|
||||
};
|
||||
size_t ConfigKeyboardButtonsCount = 0;
|
||||
KeyCodePair *ConfigKeyboardButtons = nullptr;
|
||||
KeyCodePair ConfigKeyboardButtons_US[] = {
|
||||
// Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Row 1
|
||||
{"ESCAPE", VK_ESCAPE},
|
||||
{"F1", VK_F1},
|
||||
{"F2", VK_F2},
|
||||
{"F3", VK_F3},
|
||||
{"F4", VK_F4},
|
||||
{"F5", VK_F5},
|
||||
{"F6", VK_F6},
|
||||
{"F7", VK_F7},
|
||||
{"F8", VK_F8},
|
||||
{"F9", VK_F9},
|
||||
{"F10", VK_F10},
|
||||
{"F11", VK_F11},
|
||||
{"F12", VK_F12},
|
||||
|
||||
// Row 2
|
||||
{"`", VK_OEM_3},
|
||||
{"1", '1'},
|
||||
{"2", '2'},
|
||||
{"3", '3'},
|
||||
{"4", '4'},
|
||||
{"5", '5'},
|
||||
{"6", '6'},
|
||||
{"7", '7'},
|
||||
{"8", '8'},
|
||||
{"9", '9'},
|
||||
{"0", '0'},
|
||||
{"-", VK_OEM_MINUS},
|
||||
{"=", VK_OEM_PLUS},
|
||||
{"BACKSPACE", VK_BACK},
|
||||
|
||||
// Row 3
|
||||
{"TAB", VK_TAB},
|
||||
{"Q", 'Q'},
|
||||
{"W", 'W'},
|
||||
{"E", 'E'},
|
||||
{"R", 'R'},
|
||||
{"T", 'T'},
|
||||
{"Y", 'Y'},
|
||||
{"U", 'U'},
|
||||
{"I", 'I'},
|
||||
{"O", 'O'},
|
||||
{"P", 'P'},
|
||||
{"[", VK_OEM_4},
|
||||
{"]", VK_OEM_6},
|
||||
{"BACKSLASH", VK_OEM_5},
|
||||
|
||||
// Row 4
|
||||
{"CAPS_LOCK", VK_CAPITAL},
|
||||
{"A", 'A'},
|
||||
{"S", 'S'},
|
||||
{"D", 'D'},
|
||||
{"F", 'F'},
|
||||
{"G", 'G'},
|
||||
{"H", 'H'},
|
||||
{"J", 'J'},
|
||||
{"K", 'K'},
|
||||
{"L", 'L'},
|
||||
{";", VK_OEM_1},
|
||||
{"'", VK_OEM_7},
|
||||
{"ENTER", VK_RETURN},
|
||||
|
||||
// Row 5
|
||||
{"SHIFT", VK_SHIFT},
|
||||
{"Z", 'Z'},
|
||||
{"X", 'X'},
|
||||
{"C", 'C'},
|
||||
{"V", 'V'},
|
||||
{"B", 'B'},
|
||||
{"N", 'N'},
|
||||
{"M", 'M'},
|
||||
{",", VK_OEM_COMMA},
|
||||
{".", VK_OEM_PERIOD},
|
||||
{"SLASH", VK_OEM_2},
|
||||
|
||||
// Row 6
|
||||
{"CONTROL", VK_CONTROL},
|
||||
{"L_WIN", VK_LWIN},
|
||||
{"ALT", VK_MENU},
|
||||
{"SPACE", VK_SPACE},
|
||||
{"R_WIN", VK_RWIN},
|
||||
{"MENU", VK_APPS},
|
||||
|
||||
// Other Keys
|
||||
// PrtSc is more important when making snapshots, therefore comment it as reserved
|
||||
//{"PRINT_SCREEN", VK_SNAPSHOT},
|
||||
{"SCROLL_LOCK", VK_SCROLL},
|
||||
{"PAUSE", VK_PAUSE},
|
||||
{"INSERT", VK_INSERT},
|
||||
{"DELETE", VK_DELETE},
|
||||
{"HOME", VK_HOME},
|
||||
{"END", VK_END},
|
||||
{"PAGE_UP", VK_PRIOR},
|
||||
{"PAGE_DOWN", VK_NEXT},
|
||||
|
||||
// Arrow Keys
|
||||
{"UPARROW", VK_UP},
|
||||
{"LEFTARROW", VK_LEFT},
|
||||
{"DOWNARROW", VK_DOWN},
|
||||
{"RIGHTARROW", VK_RIGHT},
|
||||
|
||||
// NUMPAD Keys
|
||||
{"NUM_LOCK", VK_NUMLOCK},
|
||||
{"DIVIDE", VK_DIVIDE},
|
||||
{"MULTIPLY", VK_MULTIPLY},
|
||||
{"SUBTRACT", VK_SUBTRACT},
|
||||
{"NUM7", VK_NUMPAD7},
|
||||
{"NUM8", VK_NUMPAD8},
|
||||
{"NUM9", VK_NUMPAD9},
|
||||
{"ADD", VK_ADD},
|
||||
{"NUM4", VK_NUMPAD4},
|
||||
{"NUM5", VK_NUMPAD5},
|
||||
{"NUM6", VK_NUMPAD6},
|
||||
{"NUM1", VK_NUMPAD1},
|
||||
{"NUM2", VK_NUMPAD2},
|
||||
{"NUM3", VK_NUMPAD3},
|
||||
{"NUM0", VK_NUMPAD0},
|
||||
{"DECIMAL", VK_DECIMAL},
|
||||
};
|
||||
KeyCodePair ConfigKeyboardButtons_JP[] = {
|
||||
// Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Row 1
|
||||
{"ESCAPE", VK_ESCAPE},
|
||||
{"F1", VK_F1},
|
||||
{"F2", VK_F2},
|
||||
{"F3", VK_F3},
|
||||
{"F4", VK_F4},
|
||||
{"F5", VK_F5},
|
||||
{"F6", VK_F6},
|
||||
{"F7", VK_F7},
|
||||
{"F8", VK_F8},
|
||||
{"F9", VK_F9},
|
||||
{"F10", VK_F10},
|
||||
{"F11", VK_F11},
|
||||
{"F12", VK_F12},
|
||||
|
||||
// Row 2
|
||||
{"1", '1'},
|
||||
{"2", '2'},
|
||||
{"3", '3'},
|
||||
{"4", '4'},
|
||||
{"5", '5'},
|
||||
{"6", '6'},
|
||||
{"7", '7'},
|
||||
{"8", '8'},
|
||||
{"9", '9'},
|
||||
{"0", '0'},
|
||||
{"-", VK_OEM_MINUS},
|
||||
{"^", VK_OEM_7},
|
||||
{"YEN", VK_OEM_5},
|
||||
{"BACKSPACE", VK_BACK},
|
||||
|
||||
// Row 3
|
||||
{"TAB", VK_TAB},
|
||||
{"Q", 'Q'},
|
||||
{"W", 'W'},
|
||||
{"E", 'E'},
|
||||
{"R", 'R'},
|
||||
{"T", 'T'},
|
||||
{"Y", 'Y'},
|
||||
{"U", 'U'},
|
||||
{"I", 'I'},
|
||||
{"O", 'O'},
|
||||
{"P", 'P'},
|
||||
{"@", VK_OEM_3},
|
||||
{"[", VK_OEM_4},
|
||||
|
||||
// Row 4
|
||||
{"CAPS_LOCK", VK_CAPITAL},
|
||||
{"A", 'A'},
|
||||
{"S", 'S'},
|
||||
{"D", 'D'},
|
||||
{"F", 'F'},
|
||||
{"G", 'G'},
|
||||
{"H", 'H'},
|
||||
{"J", 'J'},
|
||||
{"K", 'K'},
|
||||
{"L", 'L'},
|
||||
{";", VK_OEM_PLUS},
|
||||
{":", VK_OEM_1},
|
||||
{"]", VK_OEM_6},
|
||||
{"ENTER", VK_RETURN},
|
||||
|
||||
// Row 5
|
||||
{"SHIFT", VK_SHIFT},
|
||||
{"Z", 'Z'},
|
||||
{"X", 'X'},
|
||||
{"C", 'C'},
|
||||
{"V", 'V'},
|
||||
{"B", 'B'},
|
||||
{"N", 'N'},
|
||||
{"M", 'M'},
|
||||
{",", VK_OEM_COMMA},
|
||||
{".", VK_OEM_PERIOD},
|
||||
{"SLASH", VK_OEM_2},
|
||||
{"BACKSLASH", VK_OEM_102},
|
||||
|
||||
// Row 6
|
||||
{"CONTROL", VK_CONTROL},
|
||||
{"L_WIN", VK_LWIN},
|
||||
{"ALT", VK_MENU},
|
||||
{"SPACE", VK_SPACE},
|
||||
{"R_WIN", VK_RWIN},
|
||||
{"MENU", VK_APPS},
|
||||
|
||||
// Other Keys
|
||||
// PrtSc is more important when making snapshots, therefore comment it as reserved
|
||||
//{"PRINT_SCREEN", VK_SNAPSHOT},
|
||||
{"SCROLL_LOCK", VK_SCROLL},
|
||||
{"PAUSE", VK_PAUSE},
|
||||
{"INSERT", VK_INSERT},
|
||||
{"DELETE", VK_DELETE},
|
||||
{"HOME", VK_HOME},
|
||||
{"END", VK_END},
|
||||
{"PAGE_UP", VK_PRIOR},
|
||||
{"PAGE_DOWN", VK_NEXT},
|
||||
|
||||
// Arrow Keys
|
||||
{"UPARROW", VK_UP},
|
||||
{"LEFTARROW", VK_LEFT},
|
||||
{"DOWNARROW", VK_DOWN},
|
||||
{"RIGHTARROW", VK_RIGHT},
|
||||
|
||||
// NUMPAD Keys
|
||||
{"NUM_LOCK", VK_NUMLOCK},
|
||||
{"DIVIDE", VK_DIVIDE},
|
||||
{"MULTIPLY", VK_MULTIPLY},
|
||||
{"SUBTRACT", VK_SUBTRACT},
|
||||
{"NUM7", VK_NUMPAD7},
|
||||
{"NUM8", VK_NUMPAD8},
|
||||
{"NUM9", VK_NUMPAD9},
|
||||
{"ADD", VK_ADD},
|
||||
{"NUM4", VK_NUMPAD4},
|
||||
{"NUM5", VK_NUMPAD5},
|
||||
{"NUM6", VK_NUMPAD6},
|
||||
{"NUM1", VK_NUMPAD1},
|
||||
{"NUM2", VK_NUMPAD2},
|
||||
{"NUM3", VK_NUMPAD3},
|
||||
{"NUM0", VK_NUMPAD0},
|
||||
{"DECIMAL", VK_DECIMAL},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
SDL_GameControllerButton button;
|
||||
} ConfigControllerButtons[] = {
|
||||
{"SDL_A", SDL_CONTROLLER_BUTTON_A},
|
||||
{"SDL_B", SDL_CONTROLLER_BUTTON_B},
|
||||
{"SDL_X", SDL_CONTROLLER_BUTTON_X},
|
||||
{"SDL_Y", SDL_CONTROLLER_BUTTON_Y},
|
||||
{"SDL_BACK", SDL_CONTROLLER_BUTTON_BACK},
|
||||
{"SDL_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE},
|
||||
{"SDL_START", SDL_CONTROLLER_BUTTON_START},
|
||||
{"SDL_LSTICK_PRESS", SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||
{"SDL_RSTICK_PRESS", SDL_CONTROLLER_BUTTON_RIGHTSTICK},
|
||||
{"SDL_LSHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{"SDL_RSHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{"SDL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||
{"SDL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN},
|
||||
{"SDL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
||||
{"SDL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
||||
{"SDL_MISC", SDL_CONTROLLER_BUTTON_MISC1},
|
||||
{"SDL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1},
|
||||
{"SDL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2},
|
||||
{"SDL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3},
|
||||
{"SDL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4},
|
||||
{"SDL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
SDLAxis axis;
|
||||
} ConfigControllerAXIS[] = {
|
||||
{"SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN},
|
||||
{"SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT}, {"SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP},
|
||||
{"SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT}, {"SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN},
|
||||
{"SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
Scroll scroll;
|
||||
} ConfigMouseScroll[] = {
|
||||
{"SCROLL_UP", MOUSE_SCROLL_UP},
|
||||
{"SCROLL_DOWN", MOUSE_SCROLL_DOWN},
|
||||
};
|
||||
|
||||
struct MouseState {
|
||||
POINT Position;
|
||||
POINT RelativePosition;
|
||||
bool ScrolledUp;
|
||||
bool ScrolledDown;
|
||||
} currentMouseState, lastMouseState;
|
||||
|
||||
bool currentKeyboardState[0xFF];
|
||||
bool lastKeyboardState[0xFF];
|
||||
|
||||
@@ -325,7 +23,7 @@ SetKeyboardButtons () {
|
||||
}
|
||||
|
||||
void
|
||||
SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind) {
|
||||
SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind, bool *usePoll) {
|
||||
const toml_array_t *array = toml_array_in (table, key);
|
||||
if (!array) {
|
||||
LogMessage (LogLevel::WARN, std::string (key) + ": Cannot find array");
|
||||
@@ -344,6 +42,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
|
||||
switch (value.type) {
|
||||
case keycode: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->keycodes); i++) {
|
||||
if (key_bind->keycodes[i] == 0) {
|
||||
key_bind->keycodes[i] = value.keycode;
|
||||
@@ -353,6 +52,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
break;
|
||||
}
|
||||
case button: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->buttons); i++) {
|
||||
if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
|
||||
key_bind->buttons[i] = value.button;
|
||||
@@ -362,6 +62,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
break;
|
||||
}
|
||||
case axis: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->axis); i++) {
|
||||
if (key_bind->axis[i] == 0) {
|
||||
key_bind->axis[i] = value.axis;
|
||||
@@ -370,6 +71,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
}
|
||||
}
|
||||
case scroll: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->scroll); i++) {
|
||||
if (key_bind->scroll[i] == 0) {
|
||||
key_bind->scroll[i] = value.scroll;
|
||||
@@ -784,3 +486,4 @@ float
|
||||
IsButtonDown (const Keybindings &bindings) {
|
||||
return GetInternalButtonState (bindings).Down;
|
||||
}
|
||||
#endif
|
||||
+38
-25
@@ -1,6 +1,13 @@
|
||||
#pragma once
|
||||
#include <SDL.h>
|
||||
#include "helpers.h"
|
||||
#include "bnusio.h"
|
||||
|
||||
#ifdef ASYNC_UPDATE
|
||||
#define ASYNC_IO
|
||||
#endif
|
||||
|
||||
// #define ASYNC_IO
|
||||
|
||||
enum SDLAxis {
|
||||
SDL_AXIS_NULL,
|
||||
@@ -58,17 +65,29 @@ struct InternalButtonState {
|
||||
};
|
||||
|
||||
bool InitializePoll (HWND windowHandle);
|
||||
void UpdatePoll (HWND windowHandle);
|
||||
void DisposePoll ();
|
||||
void SetKeyboardButtons ();
|
||||
ConfigValue StringToConfigEnum (const char *value);
|
||||
void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind);
|
||||
void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *keybind, bool *usePoll);
|
||||
InternalButtonState GetInternalButtonState (const Keybindings &bindings);
|
||||
void SetRumble (int left, int right, int length);
|
||||
|
||||
bool KeyboardIsDown (u8 keycode);
|
||||
bool KeyboardIsUp (u8 keycode);
|
||||
bool KeyboardIsTapped (u8 keycode);
|
||||
bool KeyboardIsDown (const uint8_t keycode);
|
||||
bool KeyboardIsTapped (const uint8_t keycode);
|
||||
bool GetMouseScrollUp ();
|
||||
bool GetMouseScrollDown ();
|
||||
bool GetMouseScrollIsDown (const Scroll scroll);
|
||||
bool GetMouseScrollIsTapped (const Scroll scroll);
|
||||
bool ControllerButtonIsDown (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsTapped (const SDL_GameControllerButton button);
|
||||
float ControllerAxisIsDown (const SDLAxis axis);
|
||||
bool ControllerAxisIsTapped (const SDLAxis axis);
|
||||
bool IsButtonTapped (const Keybindings &bindings);
|
||||
float IsButtonDown (const Keybindings &bindings);
|
||||
|
||||
#ifndef ASYNC_IO
|
||||
void UpdatePoll (HWND windowHandle);
|
||||
bool KeyboardIsUp (const u8 keycode);
|
||||
bool KeyboardIsReleased (u8 keycode);
|
||||
bool KeyboardWasDown (u8 keycode);
|
||||
bool KeyboardWasUp (u8 keycode);
|
||||
@@ -76,26 +95,20 @@ POINT GetMousePosition ();
|
||||
POINT GetLastMousePosition ();
|
||||
POINT GetMouseRelativePosition ();
|
||||
POINT GetLastMouseRelativePosition ();
|
||||
void SetMousePosition (POINT newPosition);
|
||||
bool GetMouseScrollUp ();
|
||||
bool GetMouseScrollDown ();
|
||||
void SetMousePosition (const POINT newPosition);
|
||||
bool GetWasMouseScrollUp ();
|
||||
bool GetWasMouseScrollDown ();
|
||||
bool GetMouseScrollIsReleased (Scroll scroll);
|
||||
bool GetMouseScrollIsDown (Scroll scroll);
|
||||
bool GetMouseScrollIsTapped (Scroll scroll);
|
||||
bool ControllerButtonIsDown (SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsUp (SDL_GameControllerButton button);
|
||||
bool ControllerButtonWasDown (SDL_GameControllerButton button);
|
||||
bool ControllerButtonWasUp (SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsTapped (SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsReleased (SDL_GameControllerButton button);
|
||||
float ControllerAxisIsDown (SDLAxis axis);
|
||||
bool ControllerAxisIsUp (SDLAxis axis);
|
||||
float ControllerAxisWasDown (SDLAxis axis);
|
||||
bool ControllerAxisWasUp (SDLAxis axis);
|
||||
bool ControllerAxisIsTapped (SDLAxis axis);
|
||||
bool ControllerAxisIsReleased (SDLAxis axis);
|
||||
bool IsButtonTapped (const Keybindings &bindings);
|
||||
bool GetMouseScrollIsReleased (const Scroll scroll);
|
||||
bool ControllerButtonWasDown (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonWasUp (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsReleased (const SDL_GameControllerButton button);
|
||||
bool ControllerAxisIsUp (const SDLAxis axis);
|
||||
float ControllerAxisWasDown (const SDLAxis axis);
|
||||
bool ControllerAxisWasUp (const SDLAxis axis);
|
||||
bool ControllerAxisIsReleased (const SDLAxis axis);
|
||||
bool IsButtonReleased (const Keybindings &bindings);
|
||||
float IsButtonDown (const Keybindings &bindings);
|
||||
#else
|
||||
void UpdatePoll (HWND windowHandle, bool useController);
|
||||
void InitializeKeyboard ();
|
||||
void DisposeKeyboard ();
|
||||
#endif
|
||||
@@ -0,0 +1,482 @@
|
||||
#include "poll.h"
|
||||
|
||||
#ifdef ASYNC_IO
|
||||
#include "polldef.h"
|
||||
extern bool jpLayout;
|
||||
extern int exited;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
bool wndForeground = false;
|
||||
|
||||
bool currentKeyboardState[0xFF] = { false };
|
||||
int keyboardCount[0xFF] = { 0 };
|
||||
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;
|
||||
SDL_GameController *controllers[255];
|
||||
|
||||
std::thread updatePollThread;
|
||||
|
||||
void
|
||||
SetKeyboardButtons () {
|
||||
ConfigKeyboardButtonsCount = jpLayout ? std::size (ConfigKeyboardButtons_JP) : std::size (ConfigKeyboardButtons_US);
|
||||
ConfigKeyboardButtons = static_cast<KeyCodePair *> (malloc (ConfigKeyboardButtonsCount * sizeof (KeyCodePair)));
|
||||
memcpy (ConfigKeyboardButtons, jpLayout ? ConfigKeyboardButtons_JP : ConfigKeyboardButtons_US, ConfigKeyboardButtonsCount * sizeof (KeyCodePair));
|
||||
}
|
||||
|
||||
void
|
||||
SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind, bool *usePoll) {
|
||||
const toml_array_t *array = toml_array_in (table, key);
|
||||
if (!array) {
|
||||
LogMessage (LogLevel::WARN, std::string (key) + ": Cannot find array");
|
||||
return;
|
||||
}
|
||||
|
||||
memset (key_bind, 0, sizeof (*key_bind));
|
||||
for (size_t i = 0; i < std::size (key_bind->buttons); i++)
|
||||
key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID;
|
||||
|
||||
for (int idx = 0;; idx++) {
|
||||
const auto [ok, u] = toml_string_at (array, idx);
|
||||
if (!ok) break;
|
||||
const ConfigValue value = StringToConfigEnum (u.s);
|
||||
free (u.s);
|
||||
|
||||
switch (value.type) {
|
||||
case keycode: {
|
||||
for (int i = 0; i < std::size (key_bind->keycodes); i++) {
|
||||
if (key_bind->keycodes[i] == 0) {
|
||||
key_bind->keycodes[i] = value.keycode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case button: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->buttons); i++) {
|
||||
if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
|
||||
key_bind->buttons[i] = value.button;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case axis: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->axis); i++) {
|
||||
if (key_bind->axis[i] == 0) {
|
||||
key_bind->axis[i] = value.axis;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case scroll: {
|
||||
for (int i = 0; i < std::size (key_bind->scroll); i++) {
|
||||
if (key_bind->scroll[i] == 0) {
|
||||
key_bind->scroll[i] = value.scroll;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 钩子句柄
|
||||
HHOOK keyboardHook;
|
||||
HHOOK mouseHook;
|
||||
|
||||
// 钩子回调函数
|
||||
LRESULT CALLBACK InputProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
if (nCode == HC_ACTION) {
|
||||
switch (wParam) {
|
||||
case WM_KEYDOWN: if (wndForeground) {
|
||||
KBDLLHOOKSTRUCT* pKeyboard = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||
DWORD keyCode = pKeyboard->vkCode;
|
||||
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
|
||||
case WM_KEYUP: {
|
||||
KBDLLHOOKSTRUCT* pKeyboard = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||
DWORD keyCode = pKeyboard->vkCode;
|
||||
currentKeyboardState[keyCode] = false;
|
||||
} break;
|
||||
case WM_MOUSEWHEEL: if (wndForeground) {
|
||||
MSLLHOOKSTRUCT *pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
|
||||
int wheelDelta = GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData);
|
||||
if (wheelDelta > 0) {
|
||||
mouseWheelCount[0] = MIN (mouseWheelCount[0] + wheelDelta, maxCount);
|
||||
currentMouseState.ScrolledUp = true;
|
||||
} else if (wheelDelta < 0) {
|
||||
mouseWheelCount[1] = MIN (mouseWheelCount[1] - wheelDelta, maxCount);
|
||||
currentMouseState.ScrolledDown = true;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
void
|
||||
InitializeKeyboard () {
|
||||
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, InputProc, nullptr, 0);
|
||||
if (keyboardHook == nullptr) LogMessage (LogLevel::ERROR, "Failed to install keyboard hook!\n");
|
||||
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, InputProc, nullptr, 0);
|
||||
if (maxCount > 1) LogMessage (LogLevel::ERROR, "CHEATING MODE! max count is set to {}", maxCount);
|
||||
atexit (DisposeKeyboard);
|
||||
}
|
||||
|
||||
void
|
||||
DisposeKeyboard () {
|
||||
if (keyboardHook) UnhookWindowsHookEx(keyboardHook);
|
||||
if (mouseHook) UnhookWindowsHookEx(mouseHook);
|
||||
}
|
||||
|
||||
// void
|
||||
// UpdateLoop () {
|
||||
// LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop");
|
||||
|
||||
// while (!exited) {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
bool
|
||||
InitializePoll (HWND windowHandle) {
|
||||
LogMessage (LogLevel::DEBUG, "InitializePoll");
|
||||
bool hasRumble = true;
|
||||
wndForeground = windowHandle == GetForegroundWindow ();
|
||||
SDL_SetMainReady ();
|
||||
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
|
||||
hasRumble = false;
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR,
|
||||
std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
|
||||
+ SDL_GetError ());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
|
||||
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt");
|
||||
SDL_GameControllerEventState (SDL_ENABLE);
|
||||
SDL_JoystickEventState (SDL_ENABLE);
|
||||
|
||||
for (int i = 0; i < SDL_NumJoysticks (); i++) {
|
||||
if (!SDL_IsGameController (i)) continue;
|
||||
|
||||
SDL_GameController *controller = SDL_GameControllerOpen (i);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::DEBUG, "Init Controller connected!");
|
||||
controllers[i] = controller;
|
||||
}
|
||||
|
||||
window = SDL_CreateWindowFrom (windowHandle);
|
||||
if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ());
|
||||
|
||||
atexit (DisposePoll);
|
||||
|
||||
// updatePollThread = std::thread (UpdateLoop);
|
||||
// updatePollThread.detach ();
|
||||
|
||||
return hasRumble;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckForegroundWindow (HWND processWindow) {
|
||||
if (processWindow == nullptr) return false;
|
||||
if (wndForeground ^ (processWindow == GetForegroundWindow ())) {
|
||||
wndForeground = !wndForeground;
|
||||
LogMessage (LogLevel::DEBUG, "window focus={}", wndForeground);
|
||||
}
|
||||
return wndForeground;
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePoll (HWND windowHandle, bool useController) {
|
||||
if (!CheckForegroundWindow (windowHandle)) return;
|
||||
|
||||
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);
|
||||
if (useController) {
|
||||
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
|
||||
DisposePoll () {
|
||||
SDL_DestroyWindow (window);
|
||||
SDL_Quit ();
|
||||
}
|
||||
|
||||
ConfigValue
|
||||
StringToConfigEnum (const char *value) {
|
||||
ConfigValue rval = {};
|
||||
for (size_t i = 0; i < ConfigKeyboardButtonsCount; ++i)
|
||||
if (!strcmp (value, ConfigKeyboardButtons[i].string)) {
|
||||
rval.type = keycode;
|
||||
rval.keycode = ConfigKeyboardButtons[i].keycode;
|
||||
return rval;
|
||||
}
|
||||
for (const auto &[string, button_] : ConfigControllerButtons)
|
||||
if (!strcmp (value, string)) {
|
||||
rval.type = button;
|
||||
rval.button = button_;
|
||||
return rval;
|
||||
}
|
||||
for (const auto &[string, axis_] : ConfigControllerAXIS)
|
||||
if (!strcmp (value, string)) {
|
||||
rval.type = axis;
|
||||
rval.axis = axis_;
|
||||
return rval;
|
||||
}
|
||||
for (auto &[string, scroll_] : ConfigMouseScroll)
|
||||
if (!strcmp (value, string)) {
|
||||
rval.type = scroll;
|
||||
rval.scroll = scroll_;
|
||||
return rval;
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::ERROR, std::string (value) + ": Unknown value");
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
SetRumble (int left, int right, int length) {
|
||||
for (auto &controller : controllers) {
|
||||
if (!controller || !SDL_GameControllerHasRumble (controller)) continue;
|
||||
SDL_GameControllerRumble (controller, left, right, length);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyboardIsDown (const uint8_t keycode) {
|
||||
return currentKeyboardState[keycode];
|
||||
}
|
||||
|
||||
int maxKeyboardCount = 1;
|
||||
bool
|
||||
KeyboardIsTapped (const uint8_t keycode) {
|
||||
if (keyboardCount[keycode] > 0) {
|
||||
if (maxKeyboardCount < keyboardCount[keycode]) {
|
||||
maxKeyboardCount = keyboardCount[keycode];
|
||||
LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount);
|
||||
}
|
||||
keyboardDiff[keycode] = 1;
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GetMouseScrollUp () {
|
||||
return currentMouseState.ScrolledUp;
|
||||
}
|
||||
|
||||
bool
|
||||
GetMouseScrollDown () {
|
||||
return currentMouseState.ScrolledDown;
|
||||
}
|
||||
|
||||
bool
|
||||
GetMouseScrollIsDown (const Scroll scroll) {
|
||||
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
|
||||
else return GetMouseScrollDown ();
|
||||
}
|
||||
|
||||
int maxWheelCount = 1;
|
||||
bool
|
||||
GetMouseScrollIsTapped (const Scroll scroll) {
|
||||
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
|
||||
ControllerButtonIsDown (const SDL_GameControllerButton button) {
|
||||
return currentControllerButtonsState[button];
|
||||
}
|
||||
|
||||
int maxButtonCount = 1;
|
||||
bool
|
||||
ControllerButtonIsTapped (const SDL_GameControllerButton button) {
|
||||
if (controllerCount[button] > 0) {
|
||||
if (maxButtonCount < controllerCount[button]) {
|
||||
maxButtonCount = controllerCount[button];
|
||||
LogMessage (LogLevel::DEBUG, "MAX BUTTON COLLECTED {} {}", (int)button, maxButtonCount);
|
||||
}
|
||||
controllerDiff[button] = 1;
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
|
||||
float
|
||||
ControllerAxisIsDown (const SDLAxis axis) {
|
||||
switch (axis) {
|
||||
case SDL_AXIS_LEFT_LEFT: return currentControllerAxisState.LeftLeft;
|
||||
case SDL_AXIS_LEFT_RIGHT: return currentControllerAxisState.LeftRight;
|
||||
case SDL_AXIS_LEFT_UP: return currentControllerAxisState.LeftUp;
|
||||
case SDL_AXIS_LEFT_DOWN: return currentControllerAxisState.LeftDown;
|
||||
case SDL_AXIS_RIGHT_LEFT: return currentControllerAxisState.RightLeft;
|
||||
case SDL_AXIS_RIGHT_RIGHT: return currentControllerAxisState.RightRight;
|
||||
case SDL_AXIS_RIGHT_UP: return currentControllerAxisState.RightUp;
|
||||
case SDL_AXIS_RIGHT_DOWN: return currentControllerAxisState.RightDown;
|
||||
case SDL_AXIS_LTRIGGER_DOWN: return currentControllerAxisState.LTriggerDown;
|
||||
case SDL_AXIS_RTRIGGER_DOWN: return currentControllerAxisState.RTriggerDown;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerAxisIsTapped (const SDLAxis axis) {
|
||||
return ControllerAxisIsDown (axis);
|
||||
}
|
||||
|
||||
bool
|
||||
IsButtonTapped (const Keybindings &bindings) {
|
||||
|
||||
for (size_t i = 0; i < ConfigKeyboardButtonsCount; i++) {
|
||||
if (bindings.keycodes[i] == 0) continue;
|
||||
if (KeyboardIsTapped (bindings.keycodes[i])) return true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
|
||||
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
|
||||
if (ControllerButtonIsTapped (bindings.buttons[i])) return true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) {
|
||||
if (bindings.axis[i] == 0) continue;
|
||||
if (float val = ControllerAxisIsTapped (bindings.axis[i]); val > 0) return true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigMouseScroll); i++) {
|
||||
if (bindings.scroll[i] == 0) continue;
|
||||
if (GetMouseScrollIsTapped (bindings.scroll[i])) return true;
|
||||
}
|
||||
return false;
|
||||
// return GetInternalButtonState (bindings).Tapped;
|
||||
}
|
||||
|
||||
float
|
||||
IsButtonDown (const Keybindings &bindings) {
|
||||
for (size_t i = 0; i < ConfigKeyboardButtonsCount; i++) {
|
||||
if (bindings.keycodes[i] == 0) continue;
|
||||
if (KeyboardIsDown (bindings.keycodes[i])) return 1.0f;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
|
||||
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
|
||||
if (ControllerButtonIsDown (bindings.buttons[i])) return 1.0f;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) {
|
||||
if (bindings.axis[i] == 0) continue;
|
||||
if (float val = ControllerAxisIsDown (bindings.axis[i]); val > 0) return val;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigMouseScroll); i++) {
|
||||
if (bindings.scroll[i] == 0) continue;
|
||||
if (GetMouseScrollIsDown (bindings.scroll[i])) return 1.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
// return GetInternalButtonState (bindings).Down;
|
||||
}
|
||||
#endif
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
#include "poll.h"
|
||||
|
||||
struct KeyCodePair {
|
||||
const char *string;
|
||||
u8 keycode;
|
||||
};
|
||||
size_t ConfigKeyboardButtonsCount = 0;
|
||||
KeyCodePair *ConfigKeyboardButtons = nullptr;
|
||||
KeyCodePair ConfigKeyboardButtons_US[] = {
|
||||
// Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Row 1
|
||||
{"ESCAPE", VK_ESCAPE},
|
||||
{"F1", VK_F1},
|
||||
{"F2", VK_F2},
|
||||
{"F3", VK_F3},
|
||||
{"F4", VK_F4},
|
||||
{"F5", VK_F5},
|
||||
{"F6", VK_F6},
|
||||
{"F7", VK_F7},
|
||||
{"F8", VK_F8},
|
||||
{"F9", VK_F9},
|
||||
{"F10", VK_F10},
|
||||
{"F11", VK_F11},
|
||||
{"F12", VK_F12},
|
||||
|
||||
// Row 2
|
||||
{"`", VK_OEM_3},
|
||||
{"1", '1'},
|
||||
{"2", '2'},
|
||||
{"3", '3'},
|
||||
{"4", '4'},
|
||||
{"5", '5'},
|
||||
{"6", '6'},
|
||||
{"7", '7'},
|
||||
{"8", '8'},
|
||||
{"9", '9'},
|
||||
{"0", '0'},
|
||||
{"-", VK_OEM_MINUS},
|
||||
{"=", VK_OEM_PLUS},
|
||||
{"BACKSPACE", VK_BACK},
|
||||
|
||||
// Row 3
|
||||
{"TAB", VK_TAB},
|
||||
{"Q", 'Q'},
|
||||
{"W", 'W'},
|
||||
{"E", 'E'},
|
||||
{"R", 'R'},
|
||||
{"T", 'T'},
|
||||
{"Y", 'Y'},
|
||||
{"U", 'U'},
|
||||
{"I", 'I'},
|
||||
{"O", 'O'},
|
||||
{"P", 'P'},
|
||||
{"[", VK_OEM_4},
|
||||
{"]", VK_OEM_6},
|
||||
{"BACKSLASH", VK_OEM_5},
|
||||
|
||||
// Row 4
|
||||
{"CAPS_LOCK", VK_CAPITAL},
|
||||
{"A", 'A'},
|
||||
{"S", 'S'},
|
||||
{"D", 'D'},
|
||||
{"F", 'F'},
|
||||
{"G", 'G'},
|
||||
{"H", 'H'},
|
||||
{"J", 'J'},
|
||||
{"K", 'K'},
|
||||
{"L", 'L'},
|
||||
{";", VK_OEM_1},
|
||||
{"'", VK_OEM_7},
|
||||
{"ENTER", VK_RETURN},
|
||||
|
||||
// Row 5
|
||||
{"SHIFT", VK_SHIFT},
|
||||
{"Z", 'Z'},
|
||||
{"X", 'X'},
|
||||
{"C", 'C'},
|
||||
{"V", 'V'},
|
||||
{"B", 'B'},
|
||||
{"N", 'N'},
|
||||
{"M", 'M'},
|
||||
{",", VK_OEM_COMMA},
|
||||
{".", VK_OEM_PERIOD},
|
||||
{"SLASH", VK_OEM_2},
|
||||
|
||||
// Row 6
|
||||
{"CONTROL", VK_CONTROL},
|
||||
{"L_WIN", VK_LWIN},
|
||||
{"ALT", VK_MENU},
|
||||
{"SPACE", VK_SPACE},
|
||||
{"R_WIN", VK_RWIN},
|
||||
{"MENU", VK_APPS},
|
||||
|
||||
// Other Keys
|
||||
// PrtSc is more important when making snapshots, therefore comment it as reserved
|
||||
//{"PRINT_SCREEN", VK_SNAPSHOT},
|
||||
{"SCROLL_LOCK", VK_SCROLL},
|
||||
{"PAUSE", VK_PAUSE},
|
||||
{"INSERT", VK_INSERT},
|
||||
{"DELETE", VK_DELETE},
|
||||
{"HOME", VK_HOME},
|
||||
{"END", VK_END},
|
||||
{"PAGE_UP", VK_PRIOR},
|
||||
{"PAGE_DOWN", VK_NEXT},
|
||||
|
||||
// Arrow Keys
|
||||
{"UPARROW", VK_UP},
|
||||
{"LEFTARROW", VK_LEFT},
|
||||
{"DOWNARROW", VK_DOWN},
|
||||
{"RIGHTARROW", VK_RIGHT},
|
||||
|
||||
// NUMPAD Keys
|
||||
{"NUM_LOCK", VK_NUMLOCK},
|
||||
{"DIVIDE", VK_DIVIDE},
|
||||
{"MULTIPLY", VK_MULTIPLY},
|
||||
{"SUBTRACT", VK_SUBTRACT},
|
||||
{"NUM7", VK_NUMPAD7},
|
||||
{"NUM8", VK_NUMPAD8},
|
||||
{"NUM9", VK_NUMPAD9},
|
||||
{"ADD", VK_ADD},
|
||||
{"NUM4", VK_NUMPAD4},
|
||||
{"NUM5", VK_NUMPAD5},
|
||||
{"NUM6", VK_NUMPAD6},
|
||||
{"NUM1", VK_NUMPAD1},
|
||||
{"NUM2", VK_NUMPAD2},
|
||||
{"NUM3", VK_NUMPAD3},
|
||||
{"NUM0", VK_NUMPAD0},
|
||||
{"DECIMAL", VK_DECIMAL},
|
||||
};
|
||||
KeyCodePair ConfigKeyboardButtons_JP[] = {
|
||||
// Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
// Row 1
|
||||
{"ESCAPE", VK_ESCAPE},
|
||||
{"F1", VK_F1},
|
||||
{"F2", VK_F2},
|
||||
{"F3", VK_F3},
|
||||
{"F4", VK_F4},
|
||||
{"F5", VK_F5},
|
||||
{"F6", VK_F6},
|
||||
{"F7", VK_F7},
|
||||
{"F8", VK_F8},
|
||||
{"F9", VK_F9},
|
||||
{"F10", VK_F10},
|
||||
{"F11", VK_F11},
|
||||
{"F12", VK_F12},
|
||||
|
||||
// Row 2
|
||||
{"1", '1'},
|
||||
{"2", '2'},
|
||||
{"3", '3'},
|
||||
{"4", '4'},
|
||||
{"5", '5'},
|
||||
{"6", '6'},
|
||||
{"7", '7'},
|
||||
{"8", '8'},
|
||||
{"9", '9'},
|
||||
{"0", '0'},
|
||||
{"-", VK_OEM_MINUS},
|
||||
{"^", VK_OEM_7},
|
||||
{"YEN", VK_OEM_5},
|
||||
{"BACKSPACE", VK_BACK},
|
||||
|
||||
// Row 3
|
||||
{"TAB", VK_TAB},
|
||||
{"Q", 'Q'},
|
||||
{"W", 'W'},
|
||||
{"E", 'E'},
|
||||
{"R", 'R'},
|
||||
{"T", 'T'},
|
||||
{"Y", 'Y'},
|
||||
{"U", 'U'},
|
||||
{"I", 'I'},
|
||||
{"O", 'O'},
|
||||
{"P", 'P'},
|
||||
{"@", VK_OEM_3},
|
||||
{"[", VK_OEM_4},
|
||||
|
||||
// Row 4
|
||||
{"CAPS_LOCK", VK_CAPITAL},
|
||||
{"A", 'A'},
|
||||
{"S", 'S'},
|
||||
{"D", 'D'},
|
||||
{"F", 'F'},
|
||||
{"G", 'G'},
|
||||
{"H", 'H'},
|
||||
{"J", 'J'},
|
||||
{"K", 'K'},
|
||||
{"L", 'L'},
|
||||
{";", VK_OEM_PLUS},
|
||||
{":", VK_OEM_1},
|
||||
{"]", VK_OEM_6},
|
||||
{"ENTER", VK_RETURN},
|
||||
|
||||
// Row 5
|
||||
{"SHIFT", VK_SHIFT},
|
||||
{"Z", 'Z'},
|
||||
{"X", 'X'},
|
||||
{"C", 'C'},
|
||||
{"V", 'V'},
|
||||
{"B", 'B'},
|
||||
{"N", 'N'},
|
||||
{"M", 'M'},
|
||||
{",", VK_OEM_COMMA},
|
||||
{".", VK_OEM_PERIOD},
|
||||
{"SLASH", VK_OEM_2},
|
||||
{"BACKSLASH", VK_OEM_102},
|
||||
|
||||
// Row 6
|
||||
{"CONTROL", VK_CONTROL},
|
||||
{"L_WIN", VK_LWIN},
|
||||
{"ALT", VK_MENU},
|
||||
{"SPACE", VK_SPACE},
|
||||
{"R_WIN", VK_RWIN},
|
||||
{"MENU", VK_APPS},
|
||||
|
||||
// Other Keys
|
||||
// PrtSc is more important when making snapshots, therefore comment it as reserved
|
||||
//{"PRINT_SCREEN", VK_SNAPSHOT},
|
||||
{"SCROLL_LOCK", VK_SCROLL},
|
||||
{"PAUSE", VK_PAUSE},
|
||||
{"INSERT", VK_INSERT},
|
||||
{"DELETE", VK_DELETE},
|
||||
{"HOME", VK_HOME},
|
||||
{"END", VK_END},
|
||||
{"PAGE_UP", VK_PRIOR},
|
||||
{"PAGE_DOWN", VK_NEXT},
|
||||
|
||||
// Arrow Keys
|
||||
{"UPARROW", VK_UP},
|
||||
{"LEFTARROW", VK_LEFT},
|
||||
{"DOWNARROW", VK_DOWN},
|
||||
{"RIGHTARROW", VK_RIGHT},
|
||||
|
||||
// NUMPAD Keys
|
||||
{"NUM_LOCK", VK_NUMLOCK},
|
||||
{"DIVIDE", VK_DIVIDE},
|
||||
{"MULTIPLY", VK_MULTIPLY},
|
||||
{"SUBTRACT", VK_SUBTRACT},
|
||||
{"NUM7", VK_NUMPAD7},
|
||||
{"NUM8", VK_NUMPAD8},
|
||||
{"NUM9", VK_NUMPAD9},
|
||||
{"ADD", VK_ADD},
|
||||
{"NUM4", VK_NUMPAD4},
|
||||
{"NUM5", VK_NUMPAD5},
|
||||
{"NUM6", VK_NUMPAD6},
|
||||
{"NUM1", VK_NUMPAD1},
|
||||
{"NUM2", VK_NUMPAD2},
|
||||
{"NUM3", VK_NUMPAD3},
|
||||
{"NUM0", VK_NUMPAD0},
|
||||
{"DECIMAL", VK_DECIMAL},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
SDL_GameControllerButton button;
|
||||
} ConfigControllerButtons[] = {
|
||||
{"SDL_A", SDL_CONTROLLER_BUTTON_A},
|
||||
{"SDL_B", SDL_CONTROLLER_BUTTON_B},
|
||||
{"SDL_X", SDL_CONTROLLER_BUTTON_X},
|
||||
{"SDL_Y", SDL_CONTROLLER_BUTTON_Y},
|
||||
{"SDL_BACK", SDL_CONTROLLER_BUTTON_BACK},
|
||||
{"SDL_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE},
|
||||
{"SDL_START", SDL_CONTROLLER_BUTTON_START},
|
||||
{"SDL_LSTICK_PRESS", SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||
{"SDL_RSTICK_PRESS", SDL_CONTROLLER_BUTTON_RIGHTSTICK},
|
||||
{"SDL_LSHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{"SDL_RSHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{"SDL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||
{"SDL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN},
|
||||
{"SDL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
||||
{"SDL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
||||
{"SDL_MISC", SDL_CONTROLLER_BUTTON_MISC1},
|
||||
{"SDL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1},
|
||||
{"SDL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2},
|
||||
{"SDL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3},
|
||||
{"SDL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4},
|
||||
{"SDL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
SDLAxis axis;
|
||||
} ConfigControllerAXIS[] = {
|
||||
{"SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN},
|
||||
{"SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT}, {"SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP},
|
||||
{"SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT}, {"SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN},
|
||||
{"SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN},
|
||||
};
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
Scroll scroll;
|
||||
} ConfigMouseScroll[] = {
|
||||
{"SCROLL_UP", MOUSE_SCROLL_UP},
|
||||
{"SCROLL_DOWN", MOUSE_SCROLL_DOWN},
|
||||
};
|
||||
|
||||
struct MouseState {
|
||||
POINT Position;
|
||||
POINT RelativePosition;
|
||||
bool ScrolledUp;
|
||||
bool ScrolledDown;
|
||||
} currentMouseState, lastMouseState;
|
||||
Reference in New Issue
Block a user