mirror of
https://github.com/esuo1198/TaikoArcadeLoader.git
synced 2026-09-28 17:58:11 +03:00
Added Logger to TAL (#13)
* Added Logger for TAL with __VA_ARGS__ support * Added Tatacon entries in SDL DB * Added comments to exported config file * Included keys for LayeredFS * Cleaned up a bit of code in JPN39 patches * Formatted all files using clang-format * Force invalid cards on original readers You can now use any cards with the original namco readers. * Move helper functions to cpp file --------- Co-authored-by: ptmaster <lty2008one@163.com>
This commit is contained in:
committed by
Farewell_
co-authored by
ptmaster
parent
3933ecab00
commit
d0374dca1b
@@ -17,113 +17,81 @@ If your game hangs on a black screen at launch for more than a minute, Start Tai
|
||||
|
||||
```toml
|
||||
[amauth]
|
||||
# server ip
|
||||
server = "127.0.0.1"
|
||||
# server port
|
||||
port = "54430"
|
||||
# dongle serial
|
||||
chassis_id = "284111080000"
|
||||
# shop name
|
||||
shop_id = "TAIKO ARCADE LOADER"
|
||||
# game version
|
||||
game_ver = "00.00"
|
||||
# country code
|
||||
country_code = "JPN"
|
||||
|
||||
[patches]
|
||||
# patch version
|
||||
# auto: hash detection (you need to use the original exe)
|
||||
# JPN00: JPN 00.18
|
||||
# JPN08: JPN 08.18
|
||||
# JPN39: JPN 39.06
|
||||
# CHN00: CHN 00.32 (based on JPN 32.09)
|
||||
version = "auto"
|
||||
# unlock all songs
|
||||
version = "auto" # Patch version
|
||||
# | - auto: hash detection (you need to use the original exe otherwise it will not load).
|
||||
# | - JPN00: For use with Taiko JPN 00.18
|
||||
# | - JPN08: For use with Taiko JPN 08.18
|
||||
# | - JPN39: For use with Taiko JPN 39.06
|
||||
# | - CHN00: For use with Taiko CHN 00.32
|
||||
unlock_songs = true
|
||||
|
||||
[patches.chn00]
|
||||
# sync test mode language to attract etc
|
||||
fix_language = false
|
||||
# show demo movie
|
||||
demo_movie = true
|
||||
# enable one piece collab mode
|
||||
mode_collabo025 = false
|
||||
# enable ai soshina mode
|
||||
mode_collabo026 = false
|
||||
[patches.chn00] # These patches are only available for version CHN00
|
||||
fix_language = false # Sync test mode language to attract etc
|
||||
demo_movie = true # Show demo movie
|
||||
mode_collabo025 = false # Enable one piece collab mode
|
||||
mode_collabo026 = false # Enable ai soshina mode
|
||||
|
||||
[patches.jpn39]
|
||||
# sync test mode language to attract etc
|
||||
fix_language = false
|
||||
# use cn font and chineseS wordlist value
|
||||
chs_patch = false
|
||||
# more options is now moved to testmode
|
||||
[patches.jpn39] # These patches are only available for version JPN39
|
||||
fix_language = false # Sync test mode language to attract etc
|
||||
chs_patch = false # Use Chinese font and Simplified Chinese values from the wordlist
|
||||
# More options are available in the ModManager, in the TestMode menu (Default key is F1)
|
||||
|
||||
[emulation]
|
||||
# If usio emulation is disabled, you need to place bnusio_original.dll (unmodified bnusio.dll) in the executable folder.
|
||||
usio = true
|
||||
card_reader = true
|
||||
qr = true
|
||||
usio = true # If usio emulation is disabled, you need to place bnusio_original.dll (unmodified bnusio.dll) in the executable folder.
|
||||
card_reader = true # Disable this if you have an original namco card reader
|
||||
accept_invalid = false # Enable this if you want to accept cards incompatible with the original readers
|
||||
qr = true # Disable this if you have an original namco qr code scanner
|
||||
|
||||
[graphics]
|
||||
# window resolution
|
||||
res = { x = 1920, y = 1080 }
|
||||
# window mode
|
||||
windowed = false
|
||||
# vertical sync
|
||||
vsync = false
|
||||
# fps limit
|
||||
fpslimit = 120
|
||||
|
||||
[audio]
|
||||
# wasapi shared mode
|
||||
# allows you to have multiple audio sources at once at a cost of having higher latency.
|
||||
wasapi_shared = true
|
||||
# use asio audio mode
|
||||
asio = false
|
||||
# asio driver name
|
||||
# to find it, open up regedit then navigate to HKEY_LOCAL_MACHINE\SOFTWARE\ASIO
|
||||
# the name is case sensitive.
|
||||
asio_driver = ""
|
||||
wasapi_shared = true # Wasapi shared mode, allows you to have multiple audio sources at once at a cost of having higher latency.
|
||||
asio = false # Use asio audio mode
|
||||
asio_driver = "ASIO4ALL v2" # Asio driver name
|
||||
# | If you're not using asio4all, open up regedit then navigate to HKEY_LOCAL_MACHINE\SOFTWARE\ASIO for your driver's name.
|
||||
# | It is case sensitive.
|
||||
|
||||
[qr]
|
||||
# qr image path
|
||||
image_path = ""
|
||||
image_path = "" # Path to the image of the QR Code you want to use
|
||||
|
||||
# qr data used for other events (ex. gaiden, custom folder)
|
||||
[qr.data]
|
||||
# qr serial
|
||||
serial = ""
|
||||
# qr type
|
||||
# 0: default (serial only)
|
||||
# 5: custom folder
|
||||
type = 0
|
||||
# song noes used for custom folder
|
||||
song_no = []
|
||||
|
||||
[drum]
|
||||
# input interval (if using taiko drum controller, should be set to 0)
|
||||
wait_period = 4
|
||||
[qr.data] # qr data used for other events (ex. gaiden, custom folder)
|
||||
serial = "" # qr serial
|
||||
type = 0 # qr type
|
||||
# | 0: default (serial only)
|
||||
# | 5: custom folder
|
||||
song_no = [] # Song noes used for custom folder
|
||||
|
||||
[controller]
|
||||
# use analog input
|
||||
analog_input = false
|
||||
wait_period = 4 # Input interval (if using taiko drum controller, should be set to 0)
|
||||
analog_input = false # Use analog input (you need a compatible controller, this allows playing small and big notes like on arcade cabinets)
|
||||
|
||||
[keyboard]
|
||||
# auto change to english ime mode
|
||||
auto_ime = false
|
||||
# use jp layout scan code (if using jp layout keyboard, must be set to true)
|
||||
jp_layout = false
|
||||
auto_ime = false # Automatically change to english ime mode upon game startup
|
||||
jp_layout = false # Use jp layout scan code (if using jp layout keyboard, must be set to true)
|
||||
|
||||
[layeredfs]
|
||||
# replace assets from the game using a layered file system.
|
||||
# For example if you want to edit the wordlist, add your edited version like so:
|
||||
# .\Data_mods\x64\datatable\wordlist.bin
|
||||
enabled = false
|
||||
# AES encryption keys needed to dynamically encrypt datatable files and fumens.
|
||||
# keys need to be provided in an hexlified form. A missing or incorrect key will crash the game.
|
||||
# keys are not needed if you provide already encrypted files.
|
||||
datatable_key = ""
|
||||
fumen_key = ""
|
||||
enabled = false # Replace assets from the game using a layered file system.
|
||||
# | For example if you want to edit the wordlist, add your edited version like so:
|
||||
# | .\Data_mods\x64\datatable\wordlist.json
|
||||
# | You can provide both unencrypted and encrypted files.
|
||||
|
||||
[logging]
|
||||
log_level = "INFO" # Log level, Can be either "NONE", "ERROR", "WARN", "INFO", "DEBUG" and "HOOKS"
|
||||
# | Keep this as low as possible (Info is usually more than enough) as more logging will slow down your game
|
||||
log_to_file = false # Log to file, set this to true to save the logs from your last session to TaikoArcadeLoader.log
|
||||
# |Again, if you do not have a use for this (debugging mods or whatnot), turn it off.
|
||||
```
|
||||
|
||||
## TestMode options (JPN39 only)
|
||||
@@ -131,15 +99,17 @@ fumen_key = ""
|
||||
TaikoArcadeLoader offers several patches to select in TestMode
|
||||
|
||||
The follow options are available in "MOD MANAGER" menu:
|
||||
- FREEZE TIMER (stop timer count down)
|
||||
- KIMETSU MODE (enable collabo024, will show a blank title)
|
||||
- ONE PIECE MODE (enable collabo025)
|
||||
- AI SOSHINA MODE (enable collabo026)
|
||||
- AOHARU MODE (enable aprilfool001)
|
||||
- INSTANT RESULT (send result per song)
|
||||
|
||||
* FREEZE TIMER (stop timer count down)
|
||||
* KIMETSU MODE (enable collabo024, will show a blank title)
|
||||
* ONE PIECE MODE (enable collabo025)
|
||||
* AI SOSHINA MODE (enable collabo026)
|
||||
* AOHARU MODE (enable aprilfool001)
|
||||
* INSTANT RESULT (send result per song)
|
||||
|
||||
Enhanced original option:
|
||||
- Louder volume (Speaker Volume is now up to 300%, **WARNING: May damage your speakers**)
|
||||
|
||||
* Louder volume (Speaker Volume is now up to 300%, **WARNING: May damage your speakers**)
|
||||
|
||||
## Building
|
||||
|
||||
@@ -147,16 +117,16 @@ TaikoArcadeLoader can be a bit tricky to build if you've never done it before.
|
||||
Go to the TaikoArcadeLoader folder and run the following commands:
|
||||
|
||||
```bash
|
||||
apt install -y npm mingw-w64 ninja-build nasm pip 7zip cmake
|
||||
apt install -y npm mingw-w64 ninja-build nasm 7zip cmake python3-pip
|
||||
pip3 install meson
|
||||
|
||||
npm install n -g && n latest && npm install --global xpm@latest
|
||||
npx xpm init && npx xpm install @xpack-dev-tools/mingw-w64-gcc@latest
|
||||
|
||||
# make sure you entered TaikoArcadeLoader folder
|
||||
# make sure you're in the TaikoArcadeLoader folder before running this
|
||||
export PATH=`pwd`/xpacks/.bin:$PATH
|
||||
make setup
|
||||
make clean-setup
|
||||
```
|
||||
|
||||
Once that's done, run `make` to build TAL.
|
||||
The output will be written in the `out` folder.
|
||||
The output will be written in the `out` folder.
|
||||
|
||||
Vendored
+56
-28
@@ -6,24 +6,36 @@ shop_id = "TAIKO ARCADE LOADER"
|
||||
game_ver = "00.00"
|
||||
country_code = "JPN"
|
||||
|
||||
|
||||
[patches]
|
||||
version = "auto"
|
||||
version = "auto" # Patch version
|
||||
# | - auto: hash detection (you need to use the original exe otherwise it will not load).
|
||||
# | - JPN00: For use with Taiko JPN 00.18
|
||||
# | - JPN08: For use with Taiko JPN 08.18
|
||||
# | - JPN39: For use with Taiko JPN 39.06
|
||||
# | - CHN00: For use with Taiko CHN 00.32
|
||||
unlock_songs = true
|
||||
|
||||
[patches.chn00]
|
||||
fix_language = false
|
||||
demo_movie = true
|
||||
mode_collabo025 = false
|
||||
mode_collabo026 = false
|
||||
|
||||
[patches.jpn39]
|
||||
fix_language = false
|
||||
chs_patch = false
|
||||
[patches.chn00] # These patches are only available for version CHN00
|
||||
fix_language = false # Sync test mode language to attract etc
|
||||
demo_movie = true # Show demo movie
|
||||
mode_collabo025 = false # Enable one piece collab mode
|
||||
mode_collabo026 = false # Enable ai soshina mode
|
||||
|
||||
|
||||
[patches.jpn39] # These patches are only available for version JPN39
|
||||
fix_language = false # Sync test mode language to attract etc
|
||||
chs_patch = false # Use Chinese font and Simplified Chinese values from the wordlist
|
||||
# More options are available in the ModManager, in the TestMode menu (Default key is F1)
|
||||
|
||||
|
||||
[emulation]
|
||||
usio = true
|
||||
card_reader = true
|
||||
qr = true
|
||||
usio = true # Disable this if you want to use an original Namco USIO board. you need to place bnusio_original.dll (unmodified bnusio.dll) in the executable folder.
|
||||
card_reader = true # Disable this if you want to use an original Namco card reader
|
||||
accept_invalid = false # Enable this if you want to accept cards incompatible with the original readers
|
||||
qr = true # Disable this if you want to use an original Namco QR code scanner
|
||||
|
||||
|
||||
[graphics]
|
||||
res = { x = 1920, y = 1080 }
|
||||
@@ -31,30 +43,46 @@ windowed = false
|
||||
vsync = false
|
||||
fpslimit = 120
|
||||
|
||||
|
||||
[audio]
|
||||
wasapi_shared = true
|
||||
asio = false
|
||||
asio_driver = ""
|
||||
wasapi_shared = true # Wasapi shared mode, allows you to have multiple audio sources at once at a cost of having higher latency.
|
||||
asio = false # Use asio audio mode
|
||||
asio_driver = "ASIO4ALL v2" # Asio driver name
|
||||
# | If you're not using asio4all, open up regedit then navigate to HKEY_LOCAL_MACHINE\SOFTWARE\ASIO for your driver's name.
|
||||
# | It is case sensitive.
|
||||
|
||||
|
||||
[qr]
|
||||
image_path = ""
|
||||
image_path = "" # Path to the image of the QR Code you want to use
|
||||
|
||||
[qr.data]
|
||||
serial = ""
|
||||
type = 0
|
||||
song_no = []
|
||||
|
||||
[drum]
|
||||
wait_period = 4
|
||||
[qr.data] # QR data used for other events (ex. gaiden, custom folder)
|
||||
serial = "" # QR serial
|
||||
type = 0 # QR type
|
||||
# | 0: default (serial only)
|
||||
# | 5: custom folder
|
||||
song_no = [] # Song noes used for custom folder
|
||||
|
||||
|
||||
[controller]
|
||||
analog_input = false
|
||||
wait_period = 4 # Input interval (if using taiko drum controller, should be set to 0)
|
||||
analog_input = false # Use analog input (you need a compatible controller, this allows playing small and big notes like on arcade cabinets)
|
||||
|
||||
|
||||
[keyboard]
|
||||
auto_ime = false
|
||||
jp_layout = false
|
||||
auto_ime = false # Automatically change to english ime mode upon game startup
|
||||
jp_layout = false # Use jp layout scan code (if using jp layout keyboard, must be set to true)
|
||||
|
||||
|
||||
[layeredfs]
|
||||
enabled = false
|
||||
datatable_key = ""
|
||||
fumen_key = ""
|
||||
enabled = false # Replace assets from the game using a layered file system.
|
||||
# | For example if you want to edit the wordlist, add your edited version like so:
|
||||
# | .\Data_mods\x64\datatable\wordlist.json
|
||||
# | You can provide both unencrypted and encrypted files.
|
||||
|
||||
|
||||
[logging]
|
||||
log_level = "INFO" # Log level, Can be either "NONE", "ERROR", "WARN", "INFO", "DEBUG" and "HOOKS"
|
||||
# | Keep this as low as possible (Info is usually more than enough) as more logging will slow down your game
|
||||
log_to_file = false # Log to file, set this to true to save the logs from your last session to TaikoArcadeLoader.log
|
||||
# |Again, if you do not have a use for this (debugging mods or whatnot), turn it off.
|
||||
Vendored
+5
@@ -1,6 +1,11 @@
|
||||
# Game Controller DB for SDL in 2.0.16 format
|
||||
# Source: https://github.com/gabomdq/SDL_GameControllerDB
|
||||
|
||||
# Taiko stuff
|
||||
03000000de280000ff11000001007801,HORI Taiko Controller,platform:Windows,leftstick:b6,rightstick:b7,lefttrigger:b4,righttrigger:b5,
|
||||
030000000d0f0000f000000000000000,Hori Taiko Controller,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:b6,righttrigger:b7,platform:Windows,
|
||||
030000000d0f0000f000000011010000,HORI Taiko Controller,leftstick:b10,rightstick:b11,lefttrigger:b6,righttrigger:b7,platform:Linux,
|
||||
|
||||
# Windows
|
||||
03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
|
||||
|
||||
@@ -79,6 +79,7 @@ library(
|
||||
sources : [
|
||||
'src/dllmain.cpp',
|
||||
'src/helpers.cpp',
|
||||
'src/logger.cpp',
|
||||
'src/poll.cpp',
|
||||
'src/bnusio.cpp',
|
||||
'src/patches/amauth.cpp',
|
||||
|
||||
+81
-59
@@ -14,6 +14,7 @@ extern char chipId2[33];
|
||||
extern bool autoIme;
|
||||
extern bool emulateUsio;
|
||||
extern bool emulateCardReader;
|
||||
extern bool acceptInvalidCards;
|
||||
|
||||
typedef i32 (*callbackAttach) (i32, i32, i32 *);
|
||||
typedef void (*callbackTouch) (i32, i32, u8[168], u64);
|
||||
@@ -40,10 +41,10 @@ Keybindings P1_LEFT_BLUE = {.keycodes = {'D'}, .axis = {SDL_AXIS_LEFT_DOWN}};
|
||||
Keybindings P1_LEFT_RED = {.keycodes = {'F'}, .axis = {SDL_AXIS_LEFT_RIGHT}};
|
||||
Keybindings P1_RIGHT_RED = {.keycodes = {'J'}, .axis = {SDL_AXIS_RIGHT_RIGHT}};
|
||||
Keybindings P1_RIGHT_BLUE = {.keycodes = {'K'}, .axis = {SDL_AXIS_RIGHT_DOWN}};
|
||||
Keybindings P2_LEFT_BLUE = {};
|
||||
Keybindings P2_LEFT_RED = {};
|
||||
Keybindings P2_RIGHT_RED = {};
|
||||
Keybindings P2_RIGHT_BLUE = {};
|
||||
Keybindings P2_LEFT_BLUE = {.keycodes = {'Z'}};
|
||||
Keybindings P2_LEFT_RED = {.keycodes = {'X'}};
|
||||
Keybindings P2_RIGHT_RED = {.keycodes = {'C'}};
|
||||
Keybindings P2_RIGHT_BLUE = {.keycodes = {'V'}};
|
||||
|
||||
bool testEnabled = false;
|
||||
int coin_count = 0;
|
||||
@@ -187,6 +188,30 @@ u16 __fastcall bnusio_GetCoin (i32 a1) { return coin_count; }
|
||||
u16 __fastcall bnusio_GetService (i32 a1) { return service_count; }
|
||||
}
|
||||
|
||||
void
|
||||
InspectWaitTouch (i32 a1, i32 a2, u8 _cardData[168], u64 _touchData) {
|
||||
if (AreAllBytesZero (_cardData, 0x00, 168)) // This happens when you enter test mode.
|
||||
return touchCallback (a1, a2, _cardData, _touchData);
|
||||
|
||||
bool valid = !AreAllBytesZero (_cardData, 0x50, 21);
|
||||
if (valid) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Card is valid");
|
||||
} else {
|
||||
memcpy (_cardData + 0x50, _cardData + 0x2C, 16); // 16 to match felica lite serial number length
|
||||
LogMessage (LOG_LEVEL_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 (LOG_LEVEL_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);
|
||||
@@ -238,9 +263,9 @@ HOOK (void, bngrw_Fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; }
|
||||
HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; }
|
||||
HOOK (i32, bngrw_ReqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) { return 1; }
|
||||
HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed"), u32 a1, u32 ledType, i64 a3, i64 a4) { return 1; }
|
||||
HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep"), u32 a1, u32 beepType, i64 a3, i64 a4) { return 1; }
|
||||
HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction"), u32 a1, u32 actionType, i64 a3, i64 a4) { return 1; }
|
||||
HOOK (u64, bngrw_SetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwSetLedPower")) { return 0; }
|
||||
HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; }
|
||||
HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; }
|
||||
@@ -252,22 +277,28 @@ HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo"))
|
||||
HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; }
|
||||
HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; }
|
||||
HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, i32 (*callback) (i32, i32, i32 *), i32 *a6) {
|
||||
HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, callbackAttach callback, i32 *_attachData) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "BngRwAttach");
|
||||
// This is way too fucking jank
|
||||
attachCallback = callback;
|
||||
attachData = a6;
|
||||
attachData = _attachData;
|
||||
return 1;
|
||||
}
|
||||
HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, void (*callback) (i32, i32, u8[168], u64),
|
||||
u64 a5) {
|
||||
waitingForTouch = true;
|
||||
touchCallback = callback;
|
||||
touchData = a5;
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC touchEvent = GetProcAddress (plugin, "WaitTouch");
|
||||
if (touchEvent) ((waitTouchEvent *)touchEvent) (callback, a5);
|
||||
HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, callbackTouch _callback, u64 _touchData) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "BngRwReqWaitTouch");
|
||||
touchCallback = _callback;
|
||||
if (emulateCardReader) {
|
||||
waitingForTouch = true;
|
||||
touchData = _touchData;
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC touchEvent = GetProcAddress (plugin, "WaitTouch");
|
||||
if (touchEvent) ((waitTouchEvent *)touchEvent) (_callback, _touchData);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
// This is called when we use an original card reader and acceptInvalidCards is set to true
|
||||
return originalbngrw_ReqWaitTouch.call<u64> (a1, a2, a3, InspectWaitTouch, _touchData);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -278,12 +309,11 @@ Init () {
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
if (config_ptr) {
|
||||
toml_table_t *config = config_ptr.get ();
|
||||
auto drum = openConfigSection (config, "drum");
|
||||
if (drum) drumWaitPeriod = readConfigInt (drum, "wait_period", drumWaitPeriod);
|
||||
auto controller = openConfigSection (config, "controller");
|
||||
auto controller = openConfigSection (config, "controller");
|
||||
if (controller) {
|
||||
analogInput = readConfigBool (controller, "analog_input", analogInput);
|
||||
if (analogInput) printf ("Using analog input mode. All the keyboard drum inputs have been disabled.\n");
|
||||
drumWaitPeriod = readConfigInt (controller, "wait_period", drumWaitPeriod);
|
||||
analogInput = readConfigBool (controller, "analog_input", analogInput);
|
||||
if (analogInput) LogMessage (LOG_LEVEL_WARN, "Using analog input mode. All the keyboard drum inputs have been disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +347,7 @@ Init () {
|
||||
|
||||
if (!emulateUsio && !std::filesystem::exists (std::filesystem::current_path () / "bnusio_original.dll")) {
|
||||
emulateUsio = true;
|
||||
std::cerr << "[Init] bnusio_original.dll not found! usio emulation enabled" << std::endl;
|
||||
LogMessage (LOG_LEVEL_ERROR, "bnusio_original.dll not found! usio emulation enabled");
|
||||
}
|
||||
|
||||
if (!emulateUsio) {
|
||||
@@ -367,7 +397,7 @@ Init () {
|
||||
INSTALL_HOOK_DIRECT (bnusio_DecService, bnusio_DecService_Original);
|
||||
INSTALL_HOOK_DIRECT (bnusio_ResetCoin, bnusio_ResetCoin_Original);
|
||||
|
||||
std::cout << "[Init] USIO emulation disabled" << std::endl;
|
||||
LogMessage (LOG_LEVEL_WARN, "USIO emulation disabled");
|
||||
}
|
||||
|
||||
if (emulateCardReader) {
|
||||
@@ -393,7 +423,11 @@ Init () {
|
||||
INSTALL_HOOK (bngrw_Attach);
|
||||
INSTALL_HOOK (bngrw_DevReset);
|
||||
} else {
|
||||
std::cout << "[Init] Card reader emulation disabled" << std::endl;
|
||||
LogMessage (LOG_LEVEL_WARN, "Card reader emulation disabled");
|
||||
if (acceptInvalidCards) {
|
||||
LogMessage (LOG_LEVEL_WARN, "Original reader will accept invalid cards!");
|
||||
INSTALL_HOOK (bngrw_ReqWaitTouch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,48 +456,34 @@ Update () {
|
||||
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
|
||||
if (IsButtonTapped (EXIT)) ExitProcess (0);
|
||||
if (waitingForTouch) {
|
||||
static u8 cardData[168]
|
||||
= {0x01, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x2E, 0x58, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x5C, 0x97, 0x44, 0xF0, 0x88, 0x04, 0x00, 0x43, 0x26, 0x2C, 0x33, 0x00, 0x04,
|
||||
0x06, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x43, 0x36,
|
||||
0x00, 0x00, 0xFA, 0xE9, 0x69, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
bool hasInserted = false;
|
||||
if (IsButtonTapped (CARD_INSERT_1)) {
|
||||
if (IsButtonTapped (CARD_INSERT_1) || IsButtonTapped (CARD_INSERT_2)) {
|
||||
bool p1 = IsButtonTapped (CARD_INSERT_1);
|
||||
static u8 cardData[168]
|
||||
= {0x01, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x2E, 0x58, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x5C, 0x97, 0x44, 0xF0, 0x88, 0x04, 0x00, 0x43, 0x26, 0x2C, 0x33, 0x00, 0x04,
|
||||
0x06, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x43, 0x36,
|
||||
0x00, 0x00, 0xFA, 0xE9, 0x69, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC insertEvent = GetProcAddress (plugin, "BeforeCard1Insert");
|
||||
FARPROC insertEvent = GetProcAddress (plugin, p1 ? "BeforeCard1Insert" : "BeforeCard2Insert");
|
||||
if (insertEvent) ((event *)insertEvent) ();
|
||||
}
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC insertEvent = GetProcAddress (plugin, "Card1Insert");
|
||||
insertEvent = GetProcAddress (plugin, p1 ? "Card1Insert" : "Card2Insert");
|
||||
if (insertEvent) {
|
||||
((event *)insertEvent) ();
|
||||
hasInserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInserted) {
|
||||
memcpy (cardData + 0x2C, chipId1, 33);
|
||||
memcpy (cardData + 0x50, accessCode1, 21);
|
||||
touchCallback (0, 0, cardData, touchData);
|
||||
}
|
||||
} else if (IsButtonTapped (CARD_INSERT_2)) {
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC insertEvent = GetProcAddress (plugin, "BeforeCard2Insert");
|
||||
if (insertEvent) ((event *)insertEvent) ();
|
||||
}
|
||||
for (auto plugin : plugins) {
|
||||
FARPROC insertEvent = GetProcAddress (plugin, "Card2Insert");
|
||||
if (insertEvent) {
|
||||
((event *)insertEvent) ();
|
||||
hasInserted = true;
|
||||
}
|
||||
}
|
||||
if (!hasInserted) {
|
||||
memcpy (cardData + 0x2C, chipId2, 33);
|
||||
memcpy (cardData + 0x50, accessCode2, 21);
|
||||
LogMessage (LOG_LEVEL_INFO, "Inserting card for player %d: %s", p1 ? "1" : "2", p1 ? accessCode1 : accessCode2);
|
||||
memcpy (cardData + 0x2C, p1 ? chipId1 : chipId2, 33);
|
||||
memcpy (cardData + 0x50, p1 ? accessCode1 : accessCode2, 21);
|
||||
touchCallback (0, 0, cardData, touchData);
|
||||
}
|
||||
}
|
||||
@@ -486,5 +506,7 @@ Close () {
|
||||
FARPROC exitEvent = GetProcAddress (plugin, "Exit");
|
||||
if (exitEvent) ((event *)exitEvent) ();
|
||||
}
|
||||
|
||||
CleanupLogger ();
|
||||
}
|
||||
} // namespace bnusio
|
||||
|
||||
+50
-27
@@ -3,31 +3,36 @@
|
||||
#include "helpers.h"
|
||||
#include "patches/patches.h"
|
||||
#include "poll.h"
|
||||
#include "logger.h"
|
||||
|
||||
GameVersion gameVersion = GameVersion::UNKNOWN;
|
||||
std::vector<HMODULE> plugins;
|
||||
u64 song_data_size = 1024 * 1024 * 64;
|
||||
void *song_data;
|
||||
|
||||
std::string server = "127.0.0.1";
|
||||
std::string port = "54430";
|
||||
std::string chassisId = "284111080000";
|
||||
std::string shopId = "TAIKO ARCADE LOADER";
|
||||
std::string gameVerNum = "00.00";
|
||||
std::string countryCode = "JPN";
|
||||
char fullAddress[256] = {'\0'};
|
||||
char placeId[16] = {'\0'};
|
||||
char accessCode1[21] = "00000000000000000001";
|
||||
char accessCode2[21] = "00000000000000000002";
|
||||
char chipId1[33] = "00000000000000000000000000000001";
|
||||
char chipId2[33] = "00000000000000000000000000000002";
|
||||
bool windowed = false;
|
||||
bool autoIme = false;
|
||||
bool jpLayout = false;
|
||||
bool useLayeredFs = false;
|
||||
bool emulateUsio = true;
|
||||
bool emulateCardReader = true;
|
||||
bool emulateQr = true;
|
||||
std::string server = "127.0.0.1";
|
||||
std::string port = "54430";
|
||||
std::string chassisId = "284111080000";
|
||||
std::string shopId = "TAIKO ARCADE LOADER";
|
||||
std::string gameVerNum = "00.00";
|
||||
std::string countryCode = "JPN";
|
||||
char fullAddress[256] = {'\0'};
|
||||
char placeId[16] = {'\0'};
|
||||
char accessCode1[21] = "00000000000000000001";
|
||||
char accessCode2[21] = "00000000000000000002";
|
||||
char chipId1[33] = "00000000000000000000000000000001";
|
||||
char chipId2[33] = "00000000000000000000000000000002";
|
||||
bool windowed = false;
|
||||
bool autoIme = false;
|
||||
bool jpLayout = false;
|
||||
bool useLayeredFs = false;
|
||||
bool emulateUsio = true;
|
||||
bool emulateCardReader = true;
|
||||
bool emulateQr = true;
|
||||
bool acceptInvalidCards = false;
|
||||
|
||||
std::string logLevelStr = "INFO";
|
||||
bool logToFile = true;
|
||||
|
||||
HWND hGameWnd;
|
||||
HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse.call<i32> (true); }
|
||||
@@ -120,6 +125,7 @@ GetGameVersion () {
|
||||
|
||||
void
|
||||
CreateCard () {
|
||||
LogMessage (LOG_LEVEL_INFO, "Creating card.ini");
|
||||
const char hexCharacterTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
char buf[64] = {0};
|
||||
srand (time (nullptr));
|
||||
@@ -140,8 +146,12 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
|
||||
// This is bad, dont do this
|
||||
// I/O in DllMain can easily cause a deadlock
|
||||
|
||||
std::string version = "auto";
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
// Init logger for loading config
|
||||
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
|
||||
LogMessage (LOG_LEVEL_INFO, "Loading config...");
|
||||
|
||||
std::string version = "auto";
|
||||
std::filesystem::path configPath = std::filesystem::current_path () / "config.toml";
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
if (config_ptr) {
|
||||
toml_table_t *config = config_ptr.get ();
|
||||
@@ -167,9 +177,10 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
|
||||
if (patches) version = readConfigString (patches, "version", version);
|
||||
auto emulation = openConfigSection (config, "emulation");
|
||||
if (emulation) {
|
||||
emulateUsio = readConfigBool (emulation, "usio", emulateUsio);
|
||||
emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader);
|
||||
emulateQr = readConfigBool (emulation, "qr", emulateQr);
|
||||
emulateUsio = readConfigBool (emulation, "usio", emulateUsio);
|
||||
emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader);
|
||||
acceptInvalidCards = readConfigBool (emulation, "accept_invalid", acceptInvalidCards);
|
||||
emulateQr = readConfigBool (emulation, "qr", emulateQr);
|
||||
}
|
||||
auto graphics = openConfigSection (config, "graphics");
|
||||
if (graphics) windowed = readConfigBool (graphics, "windowed", windowed);
|
||||
@@ -178,8 +189,18 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
|
||||
autoIme = readConfigBool (keyboard, "auto_ime", autoIme);
|
||||
jpLayout = readConfigBool (keyboard, "jp_layout", jpLayout);
|
||||
}
|
||||
|
||||
auto logging = openConfigSection (config, "logging");
|
||||
if (logging) {
|
||||
logLevelStr = readConfigString (logging, "log_level", logLevelStr);
|
||||
logToFile = readConfigBool (logging, "log_to_file", logToFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the logger with the level read from config file.
|
||||
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
|
||||
LogMessage (LOG_LEVEL_INFO, "Application started.");
|
||||
|
||||
if (version == "auto") {
|
||||
GetGameVersion ();
|
||||
} else if (version == "JPN00") {
|
||||
@@ -191,9 +212,11 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
|
||||
} else if (version == "CHN00") {
|
||||
gameVersion = GameVersion::CHN00;
|
||||
} else {
|
||||
LogMessage (LOG_LEVEL_ERROR, "GameVersion is UNKNOWN!");
|
||||
MessageBoxA (nullptr, "Unknown patch version", nullptr, MB_OK);
|
||||
ExitProcess (0);
|
||||
}
|
||||
LogMessage (LOG_LEVEL_INFO, "GameVersion is %s", GameVersionToString (gameVersion));
|
||||
|
||||
auto pluginPath = std::filesystem::current_path () / "plugins";
|
||||
|
||||
@@ -201,13 +224,13 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
|
||||
for (const auto &entry : std::filesystem::directory_iterator (pluginPath)) {
|
||||
if (entry.path ().extension () == ".dll") {
|
||||
auto name = entry.path ().wstring ();
|
||||
auto shortName = entry.path ().filename ().wstring ();
|
||||
HMODULE hModule = LoadLibraryW (name.c_str ());
|
||||
if (!hModule) {
|
||||
wchar_t buf[128];
|
||||
wsprintfW (buf, L"Failed to load plugin %ls", name.c_str ());
|
||||
MessageBoxW (0, buf, name.c_str (), MB_ICONERROR);
|
||||
LogMessage (LOG_LEVEL_ERROR, L"Failed to load plugin " + shortName);
|
||||
} else {
|
||||
plugins.push_back (hModule);
|
||||
LogMessage (LOG_LEVEL_INFO, L"Loaded plugin " + shortName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+69
-43
@@ -1,8 +1,6 @@
|
||||
#include "helpers.h"
|
||||
#include <windows.h>
|
||||
|
||||
void *consoleHandle = 0;
|
||||
|
||||
static void
|
||||
toml_myfree (void *p) {
|
||||
if (p) {
|
||||
@@ -14,13 +12,13 @@ toml_myfree (void *p) {
|
||||
toml_table_t *
|
||||
openConfig (std::filesystem::path path) {
|
||||
if (!std::filesystem::exists (path) || !path.has_filename ()) {
|
||||
printWarning ("%s (%s): file does not exist\n", __func__, path.string ().c_str ());
|
||||
LogMessage (LOG_LEVEL_WARN, (std::string (path.string ()) + ": file does not exist").c_str ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::ifstream stream (path);
|
||||
if (!stream.is_open ()) {
|
||||
printWarning ("%s (%s): could not open\n", __func__, path.string ().c_str ());
|
||||
LogMessage (LOG_LEVEL_WARN, ("Could not open " + std::string (path.string ())).c_str ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,7 +35,7 @@ openConfig (std::filesystem::path path) {
|
||||
free (buf);
|
||||
|
||||
if (!config) {
|
||||
printWarning ("%s (%s): %s\n", __func__, path.string ().c_str (), errorbuf);
|
||||
LogMessage (LOG_LEVEL_WARN, (path.string () + ": " + errorbuf).c_str ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -48,7 +46,7 @@ toml_table_t *
|
||||
openConfigSection (toml_table_t *config, const std::string §ionName) {
|
||||
toml_table_t *section = toml_table_in (config, sectionName.c_str ());
|
||||
if (!section) {
|
||||
printWarning ("%s (%s): cannot find section\n", __func__, sectionName.c_str ());
|
||||
LogMessage (LOG_LEVEL_ERROR, ("Cannot find section " + sectionName).c_str ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -58,33 +56,42 @@ openConfigSection (toml_table_t *config, const std::string §ionName) {
|
||||
bool
|
||||
readConfigBool (toml_table_t *table, const std::string &key, bool notFoundValue) {
|
||||
toml_datum_t data = toml_bool_in (table, key.c_str ());
|
||||
if (!data.ok) return notFoundValue;
|
||||
|
||||
if (!data.ok) {
|
||||
LogMessage (LOG_LEVEL_WARN, ("Could not find Boolean named " + key).c_str ());
|
||||
return notFoundValue;
|
||||
}
|
||||
return (bool)data.u.b;
|
||||
}
|
||||
|
||||
int64_t
|
||||
readConfigInt (toml_table_t *table, const std::string &key, int64_t notFoundValue) {
|
||||
toml_datum_t data = toml_int_in (table, key.c_str ());
|
||||
if (!data.ok) return notFoundValue;
|
||||
|
||||
if (!data.ok) {
|
||||
LogMessage (LOG_LEVEL_WARN, ("Could not find Int named " + key).c_str ());
|
||||
return notFoundValue;
|
||||
}
|
||||
return data.u.i;
|
||||
}
|
||||
|
||||
const std::string
|
||||
readConfigString (toml_table_t *table, const std::string &key, const std::string ¬FoundValue) {
|
||||
toml_datum_t data = toml_string_in (table, key.c_str ());
|
||||
if (!data.ok) return notFoundValue;
|
||||
if (!data.ok) {
|
||||
LogMessage (LOG_LEVEL_WARN, ("Could not find String named " + key).c_str ());
|
||||
return notFoundValue;
|
||||
}
|
||||
std::string str = data.u.s;
|
||||
toml_myfree (data.u.s);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
std::vector<int64_t>
|
||||
readConfigIntArray (toml_table_t *table, const std::string &key, std::vector<int64_t> notFoundValue) {
|
||||
toml_array_t *array = toml_array_in (table, key.c_str ());
|
||||
if (!array) return notFoundValue;
|
||||
if (!array) {
|
||||
LogMessage (LOG_LEVEL_WARN, ("Could not find int Array named " + key).c_str ());
|
||||
return notFoundValue;
|
||||
}
|
||||
|
||||
std::vector<int64_t> datas;
|
||||
for (int i = 0;; i++) {
|
||||
@@ -96,32 +103,17 @@ readConfigIntArray (toml_table_t *table, const std::string &key, std::vector<int
|
||||
return datas;
|
||||
}
|
||||
|
||||
void
|
||||
printColour (int colour, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
|
||||
if (consoleHandle == 0) consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
|
||||
SetConsoleTextAttribute (consoleHandle, colour);
|
||||
vprintf (format, args);
|
||||
SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
std::wstring
|
||||
replace (const std::wstring orignStr, const std::wstring oldStr, const std::wstring newStr) {
|
||||
size_t pos = 0;
|
||||
std::wstring tempStr = orignStr;
|
||||
std::wstring::size_type newStrLen = newStr.length();
|
||||
std::wstring::size_type oldStrLen = oldStr.length();
|
||||
while(true)
|
||||
{
|
||||
pos = tempStr.find(oldStr, pos);
|
||||
size_t pos = 0;
|
||||
std::wstring tempStr = orignStr;
|
||||
std::wstring::size_type newStrLen = newStr.length ();
|
||||
std::wstring::size_type oldStrLen = oldStr.length ();
|
||||
while (true) {
|
||||
pos = tempStr.find (oldStr, pos);
|
||||
if (pos == std::wstring::npos) break;
|
||||
|
||||
tempStr.replace(pos, oldStrLen, newStr);
|
||||
tempStr.replace (pos, oldStrLen, newStr);
|
||||
pos += newStrLen;
|
||||
}
|
||||
|
||||
@@ -130,18 +122,52 @@ replace (const std::wstring orignStr, const std::wstring oldStr, const std::wstr
|
||||
|
||||
std::string
|
||||
replace (const std::string orignStr, const std::string oldStr, const std::string newStr) {
|
||||
size_t pos = 0;
|
||||
std::string tempStr = orignStr;
|
||||
std::string::size_type newStrLen = newStr.length();
|
||||
std::string::size_type oldStrLen = oldStr.length();
|
||||
while(true)
|
||||
{
|
||||
pos = tempStr.find(oldStr, pos);
|
||||
size_t pos = 0;
|
||||
std::string tempStr = orignStr;
|
||||
std::string::size_type newStrLen = newStr.length ();
|
||||
std::string::size_type oldStrLen = oldStr.length ();
|
||||
while (true) {
|
||||
pos = tempStr.find (oldStr, pos);
|
||||
if (pos == std::string::npos) break;
|
||||
|
||||
tempStr.replace(pos, oldStrLen, newStr);
|
||||
tempStr.replace (pos, oldStrLen, newStr);
|
||||
pos += newStrLen;
|
||||
}
|
||||
|
||||
return tempStr;
|
||||
}
|
||||
|
||||
const char *
|
||||
GameVersionToString (GameVersion version) {
|
||||
switch (version) {
|
||||
case GameVersion::JPN00: return "JPN00";
|
||||
case GameVersion::JPN08: return "JPN08";
|
||||
case GameVersion::JPN39: return "JPN39";
|
||||
case GameVersion::CHN00: return "CHN00";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
languageStr (int language) {
|
||||
switch (language) {
|
||||
case 1: return "en_us";
|
||||
case 2: return "cn_tw";
|
||||
case 3: return "kor";
|
||||
case 4: return "cn_cn";
|
||||
default: return "jpn";
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ConvertWideToUtf8 (const std::wstring &wstr) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t> > converter;
|
||||
return converter.to_bytes (wstr);
|
||||
}
|
||||
|
||||
bool
|
||||
AreAllBytesZero (const uint8_t *array, size_t offset, size_t length) {
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
if (array[offset + i] != 0x00) return false;
|
||||
return true;
|
||||
}
|
||||
+67
-16
@@ -10,6 +10,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <toml.h>
|
||||
#include "constants.h"
|
||||
#include "logger.h"
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
@@ -59,8 +61,11 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
void *where##functionName = NULL; \
|
||||
void implOf##functionName (SafetyHookContext &ctx)
|
||||
|
||||
#define INSTALL_HOOK(functionName) \
|
||||
{ original##functionName = safetyhook::create_inline (where##functionName, implOf##functionName); }
|
||||
#define INSTALL_HOOK(functionName) \
|
||||
{ \
|
||||
LogMessage (LOG_LEVEL_DEBUG, (std::string ("Installing hook for ") + #functionName).c_str ()); \
|
||||
original##functionName = safetyhook::create_inline (where##functionName, implOf##functionName); \
|
||||
}
|
||||
|
||||
#define INSTALL_HOOK_DYNAMIC(functionName, location) \
|
||||
{ \
|
||||
@@ -68,8 +73,11 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
INSTALL_HOOK (functionName); \
|
||||
}
|
||||
|
||||
#define INSTALL_HOOK_DIRECT(location, locationOfHook) \
|
||||
{ directHooks.push_back (safetyhook::create_inline ((void *)location, (void *)locationOfHook)); }
|
||||
#define INSTALL_HOOK_DIRECT(location, locationOfHook) \
|
||||
{ \
|
||||
LogMessage (LOG_LEVEL_DEBUG, (std::string ("Installing direct hook for ") + #location).c_str ()); \
|
||||
directHooks.push_back (safetyhook::create_inline ((void *)location, (void *)locationOfHook)); \
|
||||
}
|
||||
|
||||
#define INSTALL_VTABLE_HOOK(className, object, functionName, functionIndex) \
|
||||
{ \
|
||||
@@ -77,8 +85,11 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
INSTALL_HOOK (className##functionName); \
|
||||
}
|
||||
|
||||
#define INSTALL_MID_HOOK(functionName) \
|
||||
{ midHook##functionName = safetyhook::create_mid (where##functionName, implOf##functionName); }
|
||||
#define INSTALL_MID_HOOK(functionName) \
|
||||
{ \
|
||||
LogMessage (LOG_LEVEL_DEBUG, (std::string ("Installing mid hook for ") + #functionName).c_str ()); \
|
||||
midHook##functionName = safetyhook::create_mid (where##functionName, implOf##functionName); \
|
||||
}
|
||||
|
||||
#define INSTALL_MID_HOOK_DYNAMIC(functionName, location) \
|
||||
{ \
|
||||
@@ -86,6 +97,50 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
INSTALL_MID_HOOK (functionName); \
|
||||
}
|
||||
|
||||
bool sendFlag = false;
|
||||
#define SCENE_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \
|
||||
original##functionName.call (a1, a2, a3); \
|
||||
return; \
|
||||
} \
|
||||
sendFlag = true; \
|
||||
original##functionName.call (a1, a2, a3); \
|
||||
ExecuteSendResultData (); \
|
||||
}
|
||||
|
||||
#define SEND_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \
|
||||
original##functionName.call (a1); \
|
||||
return; \
|
||||
} \
|
||||
if (sendFlag) { \
|
||||
sendFlag = false; \
|
||||
original##functionName.call (a1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHANGE_RESULT_SIZE_HOOK(functionName, location, target) \
|
||||
MID_HOOK (functionName, location, SafetyHookContext &ctx) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { return; } \
|
||||
i64 instance = RefPlayDataManager (*(i64 *)ctx.r12); \
|
||||
u32 currentStageCount = *(u32 *)(instance + 8); \
|
||||
ctx.target &= 0xFFFFFFFF00000000; \
|
||||
ctx.target |= currentStageCount; \
|
||||
}
|
||||
|
||||
#define CHANGE_RESULT_INDEX_HOOK(functionName, location, target, offset, skip) \
|
||||
MID_HOOK (functionName, location, SafetyHookContext &ctx) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { return; } \
|
||||
i64 instance = RefPlayDataManager (*(i64 *)ctx.r12); \
|
||||
u32 currentStageCount = *(u32 *)(instance + 8); \
|
||||
ctx.target &= 0xFFFFFFFF00000000; \
|
||||
ctx.target |= currentStageCount - 1; \
|
||||
*(u32 *)(ctx.rsp + offset) = currentStageCount - 1; \
|
||||
ctx.rip += skip; \
|
||||
}
|
||||
|
||||
#define READ_MEMORY(location, type) *(type *)location
|
||||
|
||||
#define WRITE_MEMORY(location, type, ...) \
|
||||
@@ -124,14 +179,7 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
}
|
||||
|
||||
#define COUNTOFARR(arr) sizeof (arr) / sizeof (arr[0])
|
||||
|
||||
#define INFO_COLOUR FOREGROUND_GREEN
|
||||
#define WARNING_COLOUR (FOREGROUND_RED | FOREGROUND_GREEN)
|
||||
#define ERROR_COLOUR FOREGROUND_RED
|
||||
#define printInfo(format, ...) printColour (INFO_COLOUR, format, __VA_ARGS__)
|
||||
#define printWarning(format, ...) printColour (WARNING_COLOUR, format, __VA_ARGS__)
|
||||
#define printError(format, ...) printColour (ERROR_COLOUR, format, __VA_ARGS__)
|
||||
#define round(num) ((num > 0) ? (int)(num + 0.5) : (int)(num - 0.5))
|
||||
#define round(num) ((num > 0) ? (int)(num + 0.5) : (int)(num - 0.5))
|
||||
|
||||
toml_table_t *openConfig (std::filesystem::path path);
|
||||
toml_table_t *openConfigSection (toml_table_t *config, const std::string §ionName);
|
||||
@@ -139,7 +187,10 @@ bool readConfigBool (toml_table_t *table, const std::string &key, bool notFoundV
|
||||
int64_t readConfigInt (toml_table_t *table, const std::string &key, int64_t notFoundValue);
|
||||
const std::string readConfigString (toml_table_t *table, const std::string &key, const std::string ¬FoundValue);
|
||||
std::vector<int64_t> readConfigIntArray (toml_table_t *table, const std::string &key, std::vector<int64_t> notFoundValue);
|
||||
void printColour (int colour, const char *format, ...);
|
||||
std::wstring replace (const std::wstring orignStr, const std::wstring oldStr, const std::wstring newStr);
|
||||
std::string replace (const std::string orignStr, const std::string oldStr, const std::string newStr);
|
||||
std::vector<SafetyHookInline> directHooks = {};
|
||||
std::vector<SafetyHookInline> directHooks = {};
|
||||
const char *GameVersionToString (GameVersion version);
|
||||
const char *languageStr (int language);
|
||||
std::string ConvertWideToUtf8 (const std::wstring &wstr);
|
||||
bool AreAllBytesZero (const uint8_t *array, size_t offset, size_t length);
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
// Copyright (c) 2019 Onur Dundar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
#include "helpers.h"
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static Logger *loggerInstance = NULL;
|
||||
void *consoleHandle = 0;
|
||||
std::mutex logMutex; // Mutex for thread-safe logging
|
||||
|
||||
char timeStr[64];
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
SYSTEMTIME systemTime;
|
||||
|
||||
void
|
||||
InitializeLogger (LogLevel level, bool logToFile) {
|
||||
if (loggerInstance == nullptr) {
|
||||
loggerInstance = (Logger *)malloc (sizeof (Logger));
|
||||
if (consoleHandle == 0) consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
}
|
||||
|
||||
loggerInstance->logLevel = level;
|
||||
|
||||
if (logToFile) {
|
||||
loggerInstance->logFile = fopen ("TaikoArcadeLoader.log", "w"); // Open in write mode
|
||||
if (!loggerInstance->logFile) LogMessage (LOG_LEVEL_WARN, "Failed to open TaikoArcadeLoader.log for writing.");
|
||||
} else loggerInstance->logFile = nullptr; // No file logging
|
||||
}
|
||||
|
||||
void
|
||||
LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const std::string format, ...) {
|
||||
// Return if no logger or log level is too high
|
||||
if (loggerInstance == nullptr || messageLevel > loggerInstance->logLevel) return;
|
||||
|
||||
// Lock for thread safety
|
||||
std::lock_guard<std::mutex> lock (logMutex);
|
||||
|
||||
// Format the user-provided message
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
int requiredSize = vsnprintf (nullptr, 0, format.c_str (), args) + 1; // +1 for null terminator
|
||||
std::unique_ptr<char[]> buffer (new char[requiredSize]); // Allocate buffer dynamically
|
||||
vsnprintf (buffer.get (), requiredSize, format.c_str (), args); // Format the string
|
||||
std::string formattedMessage (buffer.get ()); // Convert to std::string
|
||||
va_end (args);
|
||||
|
||||
// Determine log type string
|
||||
std::string logType = GetLogLevelString (messageLevel);
|
||||
|
||||
// Get current time and milliseconds
|
||||
SYSTEMTIME systemTime;
|
||||
GetSystemTime (&systemTime);
|
||||
time_t rawtime = time (nullptr);
|
||||
struct tm *timeinfo = localtime (&rawtime);
|
||||
std::ostringstream timeStamp;
|
||||
timeStamp << std::put_time (timeinfo, "%Y/%m/%d %H:%M:%S") << "." << std::setw (3) << std::setfill ('0') << systemTime.wMilliseconds;
|
||||
|
||||
// Construct the log message
|
||||
std::ostringstream logStream;
|
||||
logStream << function << " (" << codeFile << ":" << codeLine << "): " << formattedMessage;
|
||||
std::string logMessage = logStream.str ();
|
||||
|
||||
// Print the log message
|
||||
std::cout << "[" << timeStamp.str () << "] "; // Timestamp
|
||||
SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color
|
||||
std::cout << logType; // Level
|
||||
SetConsoleTextAttribute (consoleHandle, 4 | 6 | 7 | 9 | 10 | 13); // Reset console color
|
||||
std::cout << logMessage << std::endl; // Log message
|
||||
std::cout.flush (); // Flush to ensure immediate writing
|
||||
|
||||
if (loggerInstance->logFile) {
|
||||
fprintf (loggerInstance->logFile, "[%s] %s%s\n", timeStamp.str ().c_str (), logType.c_str (), logMessage.c_str ());
|
||||
fflush (loggerInstance->logFile); // Flush to ensure immediate writing
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const std::wstring format, ...) {
|
||||
std::string utf8Message = ConvertWideToUtf8 (format); // Convert wide string to UTF-8
|
||||
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
LogMessageHandler (function, codeFile, codeLine, messageLevel, utf8Message, args); // Delegate to the original handler
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
CleanupLogger () {
|
||||
if (loggerInstance != NULL) {
|
||||
if (loggerInstance->logFile) fclose (loggerInstance->logFile);
|
||||
free (loggerInstance);
|
||||
loggerInstance = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
typedef enum { LOG_LEVEL_NONE = 0, LOG_LEVEL_ERROR = 1, LOG_LEVEL_WARN = 2, LOG_LEVEL_INFO = 3, LOG_LEVEL_DEBUG = 4, LOG_LEVEL_HOOKS = 5 } LogLevel;
|
||||
|
||||
/**
|
||||
* Logger Struct Used to Store Logging Preferences and State
|
||||
*/
|
||||
typedef struct {
|
||||
LogLevel logLevel;
|
||||
FILE *logFile;
|
||||
} Logger;
|
||||
|
||||
/* Initializes a global Logger instance. */
|
||||
void InitializeLogger (LogLevel level, bool logToFile);
|
||||
|
||||
/* Logs a message with file and line information, if the log level permits. */
|
||||
#define LogMessage(level, format, ...) LogMessageHandler (__FUNCTION__, __FILE__, __LINE__, level, format, ##__VA_ARGS__)
|
||||
void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const std::string format, ...);
|
||||
void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const std::wstring format, ...);
|
||||
|
||||
/* Converts a string to a LogLevel type. */
|
||||
LogLevel
|
||||
GetLogLevel (const std::string &logLevelStr) {
|
||||
if (logLevelStr == "DEBUG") return LOG_LEVEL_DEBUG;
|
||||
else if (logLevelStr == "INFO") return LOG_LEVEL_INFO;
|
||||
else if (logLevelStr == "WARN") return LOG_LEVEL_WARN;
|
||||
else if (logLevelStr == "ERROR") return LOG_LEVEL_ERROR;
|
||||
else if (logLevelStr == "HOOKS") return LOG_LEVEL_HOOKS;
|
||||
return LOG_LEVEL_NONE;
|
||||
}
|
||||
|
||||
/* Converts a LogLevel type to a string for logging. */
|
||||
std::string
|
||||
GetLogLevelString (LogLevel messageLevel) {
|
||||
switch (messageLevel) {
|
||||
case LOG_LEVEL_DEBUG: return "DEBUG: ";
|
||||
case LOG_LEVEL_INFO: return "INFO: ";
|
||||
case LOG_LEVEL_WARN: return "WARN: ";
|
||||
case LOG_LEVEL_ERROR: return "ERROR: ";
|
||||
case LOG_LEVEL_HOOKS: return "HOOKS: ";
|
||||
default: return "NONE: ";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GetLogLevelColor (LogLevel messageLevel) {
|
||||
// Colors: https://i.sstatic.net/ZG625.png
|
||||
switch (messageLevel) {
|
||||
case LOG_LEVEL_DEBUG: return 9; // Pale Blue
|
||||
case LOG_LEVEL_INFO: return 10; // Pale Green
|
||||
case LOG_LEVEL_WARN: return 6; // Bright Yellow
|
||||
case LOG_LEVEL_ERROR: return 4; // Bright RED
|
||||
case LOG_LEVEL_HOOKS: return 13; // Pale Purple
|
||||
default: return 7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleans up the logger, closing files if necessary. */
|
||||
void CleanupLogger ();
|
||||
|
||||
#endif /* LOGGER_H */
|
||||
+27
-106
@@ -290,38 +290,19 @@ public:
|
||||
return this->refCount;
|
||||
}
|
||||
|
||||
virtual int64_t Unk3 (uint32_t a1) {
|
||||
// printf ("Unk3 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int64_t Unk3 (uint32_t a1) { return 1; }
|
||||
|
||||
virtual int64_t Unk4 () {
|
||||
// printf ("Unk4 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int64_t Unk4 () { return 1; }
|
||||
|
||||
virtual int32_t Unk5 () {
|
||||
// printf ("Unk5 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk5 () { return 0; }
|
||||
|
||||
virtual int64_t Unk6 () {
|
||||
// printf ("Unk6 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int64_t Unk6 () { return 1; }
|
||||
|
||||
virtual int32_t Unk7 () {
|
||||
// printf ("Unk7 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk7 () { return 0; }
|
||||
|
||||
virtual int32_t Unk8 () {
|
||||
// printf ("Unk8 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk8 () { return 0; }
|
||||
|
||||
virtual int32_t IAuth_GetUpdaterState (amcus_state_t *arr) {
|
||||
// printf("IAuth_GetUpdaterState called\n");
|
||||
memset (arr, 0, sizeof (*arr));
|
||||
// Convert gameVerNum from string to double
|
||||
double ver_d = std::stod (gameVerNum.c_str ());
|
||||
@@ -378,7 +359,6 @@ public:
|
||||
}
|
||||
|
||||
virtual int32_t IAuth_GetCabinetConfig (amcus_network_state_t *state) {
|
||||
// printf("IAuth_GetCabinetConfig called\n");
|
||||
memset (state, 0, sizeof (*state));
|
||||
strcpy_s (state->mode, "STANDALONE");
|
||||
strcpy_s (state->pcbid, "ABLN1080001");
|
||||
@@ -400,7 +380,6 @@ public:
|
||||
}
|
||||
|
||||
virtual int32_t IAuth_GetVersionInfo (amcus_version_info_t *version) {
|
||||
// printf("IAuth_GetVersionInfo called\n");
|
||||
memset (version, 0, sizeof (*version));
|
||||
strcpy_s (version->game_rev, "1");
|
||||
strcpy_s (version->auth_type, "ALL.NET");
|
||||
@@ -414,18 +393,11 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int32_t Unk12 () {
|
||||
// printf ("Unk12 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int32_t Unk12 () { return 1; }
|
||||
|
||||
virtual int32_t Unk13 () {
|
||||
// printf ("Unk13 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int32_t Unk13 () { return 1; }
|
||||
|
||||
virtual int32_t IAuth_GetAuthServerResp (amcus_auth_server_resp_t *resp) {
|
||||
// printf("IAuth_GetAuthServerResp called\n");
|
||||
memset (resp, 0, sizeof (*resp));
|
||||
strcpy_s (resp->uri, fullAddress);
|
||||
strcpy_s (resp->host, fullAddress);
|
||||
@@ -447,24 +419,13 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int32_t Unk15 () {
|
||||
// printf ("Unk15 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk15 () { return 0; }
|
||||
|
||||
virtual int32_t Unk16 () {
|
||||
// printf ("Unk16 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk16 () { return 0; }
|
||||
|
||||
virtual int32_t Unk17 () {
|
||||
// printf ("Unk17 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk17 () { return 0; }
|
||||
|
||||
virtual int32_t IAuth_GetMuchaAuthResponse (mucha_boardauth_resp_t *arr) {
|
||||
// printf("IAuth_GetMuchaAuthResponse called\n");
|
||||
|
||||
memset (arr, 0, sizeof (*arr));
|
||||
strcpy_s (arr->shop_name, sizeof (arr->shop_name), shopId.c_str ());
|
||||
strcpy_s (arr->shop_name_en, sizeof (arr->shop_name_en), shopId.c_str ());
|
||||
@@ -500,80 +461,38 @@ public:
|
||||
}
|
||||
|
||||
virtual int32_t Unk19 (uint8_t *a1) {
|
||||
// printf("Unk19 called\n");
|
||||
memset (a1, 0, 0x38);
|
||||
a1[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual int32_t Unk20 () {
|
||||
// printf ("Unk20 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk20 () { return 0; }
|
||||
|
||||
virtual int32_t Unk21 () {
|
||||
// printf ("Unk21 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int32_t Unk21 () { return 1; }
|
||||
|
||||
virtual int32_t Unk22 () {
|
||||
// printf ("Unk22 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk22 () { return 0; }
|
||||
|
||||
virtual int32_t Unk23 () {
|
||||
// printf ("Unk23 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk23 () { return 0; }
|
||||
|
||||
virtual int32_t Unk24 () {
|
||||
// printf ("Unk24 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk24 () { return 0; }
|
||||
|
||||
virtual int32_t Unk25 () {
|
||||
// printf ("Unk25 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int32_t Unk25 () { return 1; }
|
||||
|
||||
virtual int32_t Unk26 () {
|
||||
// printf ("Unk26 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk26 () { return 0; }
|
||||
|
||||
virtual int32_t Unk27 () {
|
||||
// printf ("Unk27 called\n");
|
||||
return 1;
|
||||
}
|
||||
virtual int32_t Unk27 () { return 1; }
|
||||
|
||||
virtual int32_t Unk28 () {
|
||||
// printf ("Unk28 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk28 () { return 0; }
|
||||
|
||||
virtual int32_t Unk29 () {
|
||||
// printf ("Unk29 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk29 () { return 0; }
|
||||
|
||||
virtual int32_t Unk30 () {
|
||||
// printf ("Unk30 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk30 () { return 0; }
|
||||
|
||||
virtual int32_t PrintDebugInfo () {
|
||||
// printf ("Unk31 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t PrintDebugInfo () { return 0; }
|
||||
|
||||
virtual int32_t Unk32 (void *a1) {
|
||||
// printf ("Unk32 called\n");
|
||||
return 0;
|
||||
}
|
||||
virtual int32_t Unk32 (void *a1) { return 0; }
|
||||
|
||||
virtual void Unk33 () {
|
||||
// printf ("Unk33 called\n");
|
||||
}
|
||||
virtual void Unk33 () {}
|
||||
|
||||
public:
|
||||
CAuth () {}
|
||||
@@ -639,6 +558,8 @@ CoCreateInstanceHook (const IID *const rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsC
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init AmAuth patches");
|
||||
|
||||
g_origCoCreateInstance = safetyhook::create_inline (PROC_ADDRESS ("ole32.dll", "CoCreateInstance"), CoCreateInstanceHook);
|
||||
|
||||
struct addrinfo *res = 0;
|
||||
|
||||
@@ -23,6 +23,8 @@ bool asio = false;
|
||||
std::string asioDriver = "";
|
||||
|
||||
HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_config_t *a3, void *a4) {
|
||||
LogMessage (LOG_LEVEL_INFO, (std::string ("Device mode is ") + (asio ? "ASIO" : (wasapiShared ? "wasapi shared" : "wasapi exclusive"))).c_str ());
|
||||
if (asio) LogMessage (LOG_LEVEL_INFO, (std::string ("ASIO driver is ") + asioDriver).c_str ());
|
||||
a2->device_mode = asio;
|
||||
a2->asio_driver_name = asio ? asioDriver.c_str () : "";
|
||||
a2->wasapi_exclusive = asio ? 1 : wasapiShared ? 0 : 1;
|
||||
@@ -31,6 +33,7 @@ HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_c
|
||||
HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
|
||||
auto result = originalLoadASIODriver.call<bool> (a1, a2);
|
||||
if (!result) {
|
||||
LogMessage (LOG_LEVEL_ERROR, (std::string ("Failed to load ASIO driver ") + asioDriver).c_str ());
|
||||
MessageBoxA (nullptr, "Failed to load ASIO driver", nullptr, MB_OK);
|
||||
ExitProcess (0);
|
||||
}
|
||||
@@ -39,6 +42,8 @@ HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init Audio patches");
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
if (config_ptr) {
|
||||
|
||||
@@ -198,6 +198,7 @@ D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE Drive
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init Dxgi patches");
|
||||
i32 fpsLimit = 120;
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
|
||||
@@ -16,6 +16,7 @@ static u32 i = 0;
|
||||
|
||||
void
|
||||
Init (float fpsLimit) {
|
||||
if (fpsLimit > 0) LogMessage (LOG_LEVEL_DEBUG, "Init Fps Limiter");
|
||||
targetFrameTime = 1000.0 / fpsLimit;
|
||||
}
|
||||
|
||||
|
||||
+45
-56
@@ -3,22 +3,21 @@
|
||||
#include <zlib.h>
|
||||
|
||||
bool useLayeredFs = false;
|
||||
std::string datatableKey = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
std::string fumenKey = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
std::string datatableKey = "3530304242323633353537423431384139353134383346433246464231354534";
|
||||
std::string fumenKey = "4434423946383537303842433443383030333843444132343339373531353830";
|
||||
|
||||
#define CRCPOLY 0x82F63B78
|
||||
|
||||
namespace patches::LayeredFs {
|
||||
class RegisteredHandler {
|
||||
public:
|
||||
std::function<std::string(std::string, std::string)> handlerMethod;
|
||||
RegisteredHandler (const std::function<std::string(std::string, std::string)> &handlerMethod) {
|
||||
this->handlerMethod = handlerMethod;
|
||||
}
|
||||
std::function<std::string (std::string, std::string)> handlerMethod;
|
||||
RegisteredHandler (const std::function<std::string (std::string, std::string)> &handlerMethod) { this->handlerMethod = handlerMethod; }
|
||||
};
|
||||
|
||||
std::vector<RegisteredHandler *> beforeHandlers = {};
|
||||
std::vector<RegisteredHandler *> afterHandlers = {};
|
||||
std::vector<RegisteredHandler *> afterHandlers = {};
|
||||
|
||||
uint32_t
|
||||
CRC32C (uint32_t crc, const unsigned char *buf, size_t len) {
|
||||
@@ -161,12 +160,10 @@ EncryptFile (const std::string &input_file, const std::string &hex_key) {
|
||||
bool
|
||||
IsFumenEncrypted (const std::string &filename) {
|
||||
// Check if the filename ends with ".bin"
|
||||
if (filename.size() < 4 || filename.substr(filename.size() - 4) != ".bin") {
|
||||
std::cout << "Not a Fumen file: " << filename << std::endl;
|
||||
if (filename.size () < 4 || filename.substr (filename.size () - 4) != ".bin")
|
||||
return true; // If it doesn't we return early, as the file we're seeing isn't a fumen !
|
||||
}
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
std::ifstream file (filename, std::ios::binary);
|
||||
file.seekg (0x214, std::ios::beg);
|
||||
std::vector<unsigned char> buffer (24);
|
||||
file.read (reinterpret_cast<char *> (buffer.data ()), buffer.size ());
|
||||
@@ -180,7 +177,7 @@ IsFumenEncrypted (const std::string &filename) {
|
||||
|
||||
std::string
|
||||
LayeredFsHandler (const std::string originalFileName, const std::string currentFileName) {
|
||||
std::filesystem::path path (originalFileName.c_str());
|
||||
std::filesystem::path path (originalFileName.c_str ());
|
||||
if (!path.is_absolute ()) path = std::filesystem::absolute (path);
|
||||
auto originalDataFolder = std::filesystem::current_path ().parent_path ().parent_path () / "Data" / "x64";
|
||||
auto originalLayeredFsFolder = std::filesystem::current_path ().parent_path ().parent_path () / "Data_mods" / "x64";
|
||||
@@ -197,22 +194,24 @@ LayeredFsHandler (const std::string originalFileName, const std::string currentF
|
||||
|
||||
if (std::filesystem::exists (newPath)) { // If a file exists in the datamod folder
|
||||
if (IsFumenEncrypted (newPath)) { // And if it's an encrypted fumen or a different type of file, use it.
|
||||
std::cout << "Redirecting " << std::filesystem::relative (path).string () << std::endl;
|
||||
LogMessage (LOG_LEVEL_DEBUG, ("Redirecting " + std::filesystem::relative (path).string ()).c_str ());
|
||||
return newPath;
|
||||
} else { // Otherwise if it's an unencrypted fumen.
|
||||
if (!std::filesystem::exists (encPath)) { // We check if we don't already have a cached file.
|
||||
if (fumenKey.length () == 64) {
|
||||
std::cout << "Encrypting " << std::filesystem::relative (newPath) << std::endl; // If we don't we encrypt the file
|
||||
LogMessage (LOG_LEVEL_DEBUG,
|
||||
("Encrypting " + std::filesystem::relative (newPath).string ()).c_str ()); // If we don't we encrypt the file
|
||||
std::ifstream crc_file (newPath, std::ios::binary);
|
||||
std::vector<uint8_t> crc_vector ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
|
||||
uint32_t crc = CRC32C (0, crc_vector.data (), crc_vector.size ());
|
||||
WriteFile (encPath, EncryptFile (newPath, fumenKey), crc); // And we save it
|
||||
} else {
|
||||
std::cout << "Missing or invalid fumen key: " << std::filesystem::relative (newPath) << " couldn't be encrypted."
|
||||
<< std::endl;
|
||||
LogMessage (
|
||||
LOG_LEVEL_ERROR,
|
||||
("Missing or invalid fumen key: " + std::filesystem::relative (newPath).string () + " couldn't be encrypted.").c_str ());
|
||||
encPath = path.string ();
|
||||
}
|
||||
} else std::cout << "Using cached file for " << std::filesystem::relative (newPath) << std::endl;
|
||||
} else LogMessage (LOG_LEVEL_DEBUG, ("Using cached file for: " + std::filesystem::relative (newPath).string ()).c_str ());
|
||||
return encPath;
|
||||
}
|
||||
}
|
||||
@@ -232,58 +231,55 @@ LayeredFsHandler (const std::string originalFileName, const std::string currentF
|
||||
|
||||
if (!std::filesystem::exists (encPath) || crcBool) { // And if it hasn't been encrypted before
|
||||
if (datatableKey.length () == 64) {
|
||||
std::cout << "Encrypting " << std::filesystem::relative (json_path) << std::endl; // Encrypt the file
|
||||
// Encrypt the file
|
||||
LogMessage (LOG_LEVEL_DEBUG, ("Encrypting " + std::filesystem::relative (json_path).string ()).c_str ());
|
||||
std::ifstream crc_file (json_path.string (), std::ios::binary);
|
||||
std::vector<uint8_t> crc_vector ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
|
||||
uint32_t crc = CRC32C (0, crc_vector.data (), crc_vector.size ());
|
||||
WriteFile (encPath, EncryptFile (json_path.string (), datatableKey), crc); // And save it
|
||||
} else {
|
||||
std::cout << "Missing or invalid datatable key: " << std::filesystem::relative (newPath) << " couldn't be encrypted."
|
||||
<< std::endl;
|
||||
LogMessage (
|
||||
LOG_LEVEL_ERROR,
|
||||
("Missing or invalid datatable key: " + std::filesystem::relative (newPath).string () + " couldn't be encrypted.").c_str ());
|
||||
encPath = path.string ();
|
||||
}
|
||||
} else
|
||||
std::cout << "Using cached file for " << std::filesystem::relative (json_path)
|
||||
<< std::endl; // Otherwise use the already encrypted file.
|
||||
// Otherwise use the already encrypted file.
|
||||
LogMessage (LOG_LEVEL_DEBUG, ("Using cached file for: " + std::filesystem::relative (json_path).string ()).c_str ());
|
||||
return encPath;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return ""; // we return an empty string, causing the rest of CreateFileAHook to not update the returned value
|
||||
}
|
||||
|
||||
HOOK (
|
||||
HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"),
|
||||
LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile
|
||||
) {
|
||||
// std::wcout << "CreateFileA: file " << lpFileName << std::endl;
|
||||
std::string originalFileName = std::string(lpFileName);
|
||||
std::string currentFileName = originalFileName;
|
||||
HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
std::string originalFileName = std::string (lpFileName);
|
||||
std::string currentFileName = originalFileName;
|
||||
LogMessage (LOG_LEVEL_HOOKS, ("CreateFileA: " + originalFileName).c_str ());
|
||||
|
||||
if (!beforeHandlers.empty()) {
|
||||
if (!beforeHandlers.empty ()) {
|
||||
for (auto handler : beforeHandlers) {
|
||||
std::string result = handler->handlerMethod(originalFileName, currentFileName);
|
||||
std::string result = handler->handlerMethod (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (useLayeredFs) {
|
||||
std::string result = LayeredFsHandler(originalFileName, currentFileName);
|
||||
std::string result = LayeredFsHandler (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!afterHandlers.empty()) {
|
||||
if (!afterHandlers.empty ()) {
|
||||
for (auto handler : afterHandlers) {
|
||||
std::string result = handler->handlerMethod(originalFileName, currentFileName);
|
||||
std::string result = handler->handlerMethod (originalFileName, currentFileName);
|
||||
if (result != "") currentFileName = result;
|
||||
}
|
||||
}
|
||||
|
||||
return originalCreateFileAHook.call<HANDLE> (
|
||||
currentFileName.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile
|
||||
);
|
||||
return originalCreateFileAHook.call<HANDLE> (currentFileName.c_str (), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
// HOOK (HANDLE, CreateFileWHook, PROC_ADDRESS ("kernel32.dll", "CreateFileW"), LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
@@ -315,34 +311,27 @@ HOOK (
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init LayeredFs patches");
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
if (config_ptr) {
|
||||
auto layeredFs = openConfigSection (config_ptr.get(), "layeredfs");
|
||||
if (layeredFs) {
|
||||
useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs);
|
||||
datatableKey = readConfigString (layeredFs, "datatable_key", datatableKey);
|
||||
fumenKey = readConfigString (layeredFs, "fumen_key", fumenKey);
|
||||
}
|
||||
auto layeredFs = openConfigSection (config_ptr.get (), "layeredfs");
|
||||
if (layeredFs) useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs);
|
||||
}
|
||||
|
||||
if (useLayeredFs) {
|
||||
std::wcout << "Using LayeredFs!" << std::endl;
|
||||
}
|
||||
|
||||
register_cipher (&aes_desc);
|
||||
INSTALL_HOOK (CreateFileAHook);
|
||||
// INSTALL_HOOK (CreateFileWHook);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterBefore (const std::function<std::string(const std::string, const std::string)> &fileHandler) {
|
||||
beforeHandlers.push_back (new RegisteredHandler(fileHandler));
|
||||
RegisterBefore (const std::function<std::string (const std::string, const std::string)> &fileHandler) {
|
||||
beforeHandlers.push_back (new RegisteredHandler (fileHandler));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterAfter (const std::function<std::string(const std::string, const std::string)> &fileHandler) {
|
||||
afterHandlers.push_back (new RegisteredHandler(fileHandler));
|
||||
RegisterAfter (const std::function<std::string (const std::string, const std::string)> &fileHandler) {
|
||||
afterHandlers.push_back (new RegisteredHandler (fileHandler));
|
||||
}
|
||||
|
||||
} // namespace patches::LayeredFs
|
||||
|
||||
@@ -35,16 +35,16 @@ void Init ();
|
||||
} // namespace AmAuth
|
||||
namespace LayeredFs {
|
||||
void Init ();
|
||||
void RegisterBefore (const std::function<std::string(const std::string, const std::string)> &fileHandler);
|
||||
void RegisterAfter (const std::function<std::string(const std::string, const std::string)> &fileHandler);
|
||||
void RegisterBefore (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
void RegisterAfter (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
} // namespace LayeredFs
|
||||
namespace TestMode {
|
||||
typedef u64 (*RefTestModeMain)(u64);
|
||||
typedef u64 (*RefTestModeMain) (u64);
|
||||
void Init ();
|
||||
void SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode);
|
||||
int ReadTestModeValue (const wchar_t* itemId);
|
||||
void RegisterItem (const std::wstring item, const std::function<void()> &initMethod);
|
||||
void RegisterModify (const std::wstring query, const std::function<void(pugi::xml_node &)> &nodeModify, const std::function<void()> &initMethod);
|
||||
int ReadTestModeValue (const wchar_t *itemId);
|
||||
void RegisterItem (const std::wstring item, const std::function<void ()> &initMethod);
|
||||
void RegisterModify (const std::wstring query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod);
|
||||
void Append (pugi::xml_node &node, const wchar_t *attr, const std::wstring append);
|
||||
} // namespace TestMode
|
||||
} // namespace patches
|
||||
|
||||
+19
-24
@@ -62,8 +62,7 @@ HOOK_DYNAMIC (bool, Send3, i64, char) { return true; }
|
||||
HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; }
|
||||
HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
if (gState == State::CopyWait) {
|
||||
std::cout << "Copy data, length: " << length << std::endl;
|
||||
|
||||
// std::cout << "Copy data, length: " << length << std::endl;
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
|
||||
@@ -114,9 +113,10 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
byteBuffer.push_back (0xEE);
|
||||
byteBuffer.push_back (0xFF);
|
||||
|
||||
std::stringstream hexStream;
|
||||
for (auto byteData : byteBuffer)
|
||||
std::cout << std::hex << std::uppercase << std::setfill ('0') << std::setw (2) << static_cast<int> (byteData) << " ";
|
||||
std::cout << std::endl;
|
||||
hexStream << std::hex << std::uppercase << std::setfill ('0') << std::setw (2) << static_cast<int> (byteData) << " ";
|
||||
LogMessage (LOG_LEVEL_INFO, ("Data dump: " + hexStream.str ()).c_str ());
|
||||
|
||||
memcpy (dest, byteBuffer.data (), byteBuffer.size ());
|
||||
gState = State::Ready;
|
||||
@@ -132,8 +132,7 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
std::u8string u8PathStr (imagePath.begin (), imagePath.end ());
|
||||
std::filesystem::path u8Path (u8PathStr);
|
||||
if (!std::filesystem::is_regular_file (u8Path)) {
|
||||
std::cerr << "Failed to open image: " << u8Path.string () << " (file not found)"
|
||||
<< "\n";
|
||||
LogMessage (LOG_LEVEL_ERROR, ("Failed to open image: " + u8Path.string () + " (file not found)").c_str ());
|
||||
gState = State::Ready;
|
||||
return 0;
|
||||
}
|
||||
@@ -142,8 +141,7 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
std::unique_ptr<stbi_uc, void (*) (void *)> buffer (stbi_load (u8Path.string ().c_str (), &width, &height, &channels, 3),
|
||||
stbi_image_free);
|
||||
if (!buffer) {
|
||||
std::cerr << "Failed to read image: " << u8Path << " (" << stbi_failure_reason () << ")"
|
||||
<< "\n";
|
||||
LogMessage (LOG_LEVEL_ERROR, ("Failed to read image: " + u8Path.string () + " (" + stbi_failure_reason () + ")").c_str ());
|
||||
gState = State::Ready;
|
||||
return 0;
|
||||
}
|
||||
@@ -151,15 +149,14 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
ZXing::ImageView image{buffer.get (), width, height, ZXing::ImageFormat::RGB};
|
||||
auto result = ReadBarcode (image);
|
||||
if (!result.isValid ()) {
|
||||
std::cerr << "Failed to read QR: " << imagePath << " (" << ToString (result.error ()) << ")"
|
||||
<< "\n";
|
||||
LogMessage (LOG_LEVEL_ERROR, ("Failed to read QR: " + imagePath + " (" + ToString (result.error ()) + ")").c_str ());
|
||||
gState = State::Ready;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Valid" << std::endl;
|
||||
// std::cout << "Valid" << std::endl;
|
||||
auto byteData = result.bytes ();
|
||||
std::cout << ZXing::ToHex (byteData) << std::endl;
|
||||
// std::cout << ZXing::ToHex (byteData) << std::endl;
|
||||
auto dataSize = byteData.size ();
|
||||
|
||||
memcpy (dest, byteData.data (), dataSize);
|
||||
@@ -171,12 +168,13 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
unsigned char plugin_data[length];
|
||||
int buf_len = ((getQrEvent *)getEvent) (length, plugin_data);
|
||||
if (0 < buf_len && buf_len <= length) {
|
||||
std::stringstream hexStream;
|
||||
for (int i = 0; i < buf_len; i++)
|
||||
std::cout << std::hex << std::uppercase << std::setfill ('0') << std::setw (2) << static_cast<int> (plugin_data[i]) << " ";
|
||||
std::cout << std::endl;
|
||||
hexStream << std::hex << std::uppercase << std::setfill ('0') << std::setw (2) << static_cast<int> (plugin_data[i]) << " ";
|
||||
LogMessage (LOG_LEVEL_INFO, ("QR dump: " + hexStream.str ()).c_str ());
|
||||
memcpy (dest, plugin_data, buf_len);
|
||||
} else {
|
||||
std::cerr << "QR discard! Length invalid: " << buf_len << ", valid range: 0~" << length << std::endl;
|
||||
LogMessage (LOG_LEVEL_ERROR, ("QR discard! Length invalid: " + std::to_string (buf_len) + ", valid range: 0~").c_str ());
|
||||
}
|
||||
gState = State::Ready;
|
||||
return buf_len;
|
||||
@@ -198,35 +196,29 @@ void
|
||||
Update () {
|
||||
if (!emulateQr) return;
|
||||
if (gState == State::Ready) {
|
||||
// std::cout << "Insert" << std::endl;
|
||||
if (IsButtonTapped (CARD_INSERT_1)) {
|
||||
if (gameVersion != GameVersion::CHN00) return;
|
||||
|
||||
std::cout << "Insert" << std::endl;
|
||||
accessCode = "BNTTCNID";
|
||||
accessCode += accessCode1;
|
||||
gState = State::CopyWait;
|
||||
gMode = Mode::Card;
|
||||
} else if (IsButtonTapped (CARD_INSERT_2)) {
|
||||
if (gameVersion != GameVersion::CHN00) return;
|
||||
|
||||
std::cout << "Insert" << std::endl;
|
||||
accessCode = "BNTTCNID";
|
||||
accessCode += accessCode2;
|
||||
gState = State::CopyWait;
|
||||
gMode = Mode::Card;
|
||||
} else if (IsButtonTapped (QR_DATA_READ)) {
|
||||
std::cout << "Insert" << std::endl;
|
||||
gState = State::CopyWait;
|
||||
gMode = Mode::Data;
|
||||
} else if (IsButtonTapped (QR_IMAGE_READ)) {
|
||||
std::cout << "Insert" << std::endl;
|
||||
gState = State::CopyWait;
|
||||
gMode = Mode::Image;
|
||||
} else if (qrPluginRegistered) {
|
||||
for (auto plugin : qrPlugins) {
|
||||
FARPROC checkEvent = GetProcAddress (plugin, "CheckQr");
|
||||
if (checkEvent && ((checkQrEvent *)checkEvent) ()) {
|
||||
std::cout << "Insert" << std::endl;
|
||||
gState = State::CopyWait;
|
||||
gMode = Mode::Plugin;
|
||||
gPlugin = plugin;
|
||||
@@ -239,8 +231,10 @@ Update () {
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init Qr patches");
|
||||
|
||||
if (!emulateQr) {
|
||||
std::cout << "[Init] QR emulation disabled" << std::endl;
|
||||
LogMessage (LOG_LEVEL_WARN, "QR emulation disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,7 +246,8 @@ Init () {
|
||||
if (usingQrEvent) qrPlugins.push_back (plugin);
|
||||
}
|
||||
if (qrPlugins.size () > 0) {
|
||||
std::cout << "QR plugin found!" << std::endl;
|
||||
|
||||
LogMessage (LOG_LEVEL_INFO, "QR plugin found!");
|
||||
qrPluginRegistered = true;
|
||||
}
|
||||
|
||||
|
||||
+195
-171
@@ -11,281 +11,303 @@ namespace patches::TestMode {
|
||||
class RegisteredItem {
|
||||
public:
|
||||
std::wstring selectItem;
|
||||
std::function<void()> registerInit;
|
||||
RegisteredItem (const std::wstring selectItem, const std::function<void()> &initMethod) {
|
||||
this->selectItem = selectItem;
|
||||
std::function<void ()> registerInit;
|
||||
RegisteredItem (const std::wstring selectItem, const std::function<void ()> &initMethod) {
|
||||
this->selectItem = selectItem;
|
||||
this->registerInit = initMethod;
|
||||
}
|
||||
};
|
||||
class RegisteredModify {
|
||||
public:
|
||||
std::wstring query;
|
||||
std::function<void(pugi::xml_node &)> nodeModify;
|
||||
std::function<void()> registerInit;
|
||||
RegisteredModify (const std::wstring query, const std::function<void(pugi::xml_node &)> &nodeModify, const std::function<void()> &initMethod) {
|
||||
this->query = query;
|
||||
this->nodeModify = nodeModify;
|
||||
std::function<void (pugi::xml_node &)> nodeModify;
|
||||
std::function<void ()> registerInit;
|
||||
RegisteredModify (const std::wstring query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod) {
|
||||
this->query = query;
|
||||
this->nodeModify = nodeModify;
|
||||
this->registerInit = initMethod;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<RegisteredItem *> registeredItems = {};
|
||||
std::vector<RegisteredItem *> registeredItems = {};
|
||||
std::vector<RegisteredModify *> registeredModifies = {};
|
||||
std::wstring moddedInitial = L"";
|
||||
std::wstring modded = L"";
|
||||
std::wstring moddedInitial = L"";
|
||||
std::wstring modded = L"";
|
||||
|
||||
u64 appAccessor = 0;
|
||||
u64 appAccessor = 0;
|
||||
RefTestModeMain refTestMode = nullptr;
|
||||
|
||||
pugi::xml_document &
|
||||
CreateMenu (pugi::xml_document &menuMain, std::wstring menuId, std::wstring menuName, std::vector<std::wstring> items, std::wstring backId) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, L"Create Menu " + menuName);
|
||||
std::wstring menuBasicLine = L"<menu id=\"" + menuId + L"\"></menu>";
|
||||
if (menuMain.load_string(menuBasicLine.c_str())) {
|
||||
pugi::xml_node menu = menuMain.first_child ();
|
||||
pugi::xml_node menuHeader = menu.append_child(L"layout");
|
||||
pugi::xml_node menuCenter = menu.append_child(L"layout");
|
||||
pugi::xml_node menuFooter = menu.append_child(L"layout");
|
||||
if (menuMain.load_string (menuBasicLine.c_str ())) {
|
||||
pugi::xml_node menu = menuMain.first_child ();
|
||||
pugi::xml_node menuHeader = menu.append_child (L"layout");
|
||||
pugi::xml_node menuCenter = menu.append_child (L"layout");
|
||||
pugi::xml_node menuFooter = menu.append_child (L"layout");
|
||||
// Mod Manager Menu Header
|
||||
menuHeader.append_attribute(L"type") = L"Header";
|
||||
menuHeader.append_child(L"break-item");
|
||||
pugi::xml_node menuTitle = menuHeader.append_child(L"text-item");
|
||||
std::wstring menuNameFull = L" " + menuName;
|
||||
menuTitle.append_attribute(L"label") = menuNameFull.c_str();
|
||||
menuHeader.append_child(L"break-item");
|
||||
menuHeader.append_child(L"break-item");
|
||||
pugi::xml_node menuTitleData = menuHeader.append_child(L"data-item");
|
||||
menuTitleData.append_attribute(L"data") = L"HeaderTextData";
|
||||
menuTitleData.append_attribute(L"param-offset-x") = L"-15";
|
||||
menuHeader.append_child(L"break-item");
|
||||
menuHeader.append_attribute (L"type") = L"Header";
|
||||
menuHeader.append_child (L"break-item");
|
||||
pugi::xml_node menuTitle = menuHeader.append_child (L"text-item");
|
||||
std::wstring menuNameFull = L" " + menuName;
|
||||
menuTitle.append_attribute (L"label") = menuNameFull.c_str ();
|
||||
menuHeader.append_child (L"break-item");
|
||||
menuHeader.append_child (L"break-item");
|
||||
pugi::xml_node menuTitleData = menuHeader.append_child (L"data-item");
|
||||
menuTitleData.append_attribute (L"data") = L"HeaderTextData";
|
||||
menuTitleData.append_attribute (L"param-offset-x") = L"-15";
|
||||
menuHeader.append_child (L"break-item");
|
||||
// Mod Manager Menu Center
|
||||
menuCenter.append_attribute(L"type") = L"Center";
|
||||
menuCenter.append_attribute(L"padding-x") = L"23";
|
||||
menuCenter.append_attribute (L"type") = L"Center";
|
||||
menuCenter.append_attribute (L"padding-x") = L"23";
|
||||
for (std::wstring item : items) {
|
||||
pugi::xml_document menuItem;
|
||||
std::wstring itemLine = L"<root>" + item + L"</root>";
|
||||
if (menuItem.load_string(itemLine.c_str())) {
|
||||
menuCenter.append_copy(menuItem.first_child().first_child());
|
||||
} else {
|
||||
std::wcerr << "[TestMode Error] failed to parse option line: " << item << std::endl;
|
||||
}
|
||||
menuCenter.append_child(L"break-item");
|
||||
if (menuItem.load_string (itemLine.c_str ())) menuCenter.append_copy (menuItem.first_child ().first_child ());
|
||||
else LogMessage (LOG_LEVEL_ERROR, L"Failed to parse option line: " + item);
|
||||
menuCenter.append_child (L"break-item");
|
||||
}
|
||||
menuCenter.append_child(L"break-item");
|
||||
pugi::xml_node menuCenterExit = menuCenter.append_child(L"menu-item");
|
||||
menuCenterExit.append_attribute(L"label") = L"EXIT";
|
||||
menuCenterExit.append_attribute(L"menu") = backId.c_str();
|
||||
menuCenter.append_child (L"break-item");
|
||||
pugi::xml_node menuCenterExit = menuCenter.append_child (L"menu-item");
|
||||
menuCenterExit.append_attribute (L"label") = L"EXIT";
|
||||
menuCenterExit.append_attribute (L"menu") = backId.c_str ();
|
||||
// Mod Manager Menu Footer
|
||||
menuFooter.append_attribute(L"type") = L"Footer";
|
||||
pugi::xml_node menuFooterData = menuFooter.append_child(L"data-item");
|
||||
menuFooterData.append_attribute(L"data") = L"FooterTextData";
|
||||
menuFooterData.append_attribute(L"param-offset-x") = L"-20";
|
||||
menuFooter.append_attribute (L"type") = L"Footer";
|
||||
pugi::xml_node menuFooterData = menuFooter.append_child (L"data-item");
|
||||
menuFooterData.append_attribute (L"data") = L"FooterTextData";
|
||||
menuFooterData.append_attribute (L"param-offset-x") = L"-20";
|
||||
}
|
||||
return menuMain;
|
||||
}
|
||||
|
||||
std::wstring
|
||||
ReadXMLFileSwitcher (std::wstring &fileName) {
|
||||
std::size_t pos = fileName.rfind(L"/");
|
||||
std::wstring base = fileName.substr(0, pos + 1);
|
||||
std::wstring file = fileName.substr(pos + 1, fileName.size());
|
||||
std::size_t pos = fileName.rfind (L"/");
|
||||
std::wstring base = fileName.substr (0, pos + 1);
|
||||
std::wstring file = fileName.substr (pos + 1, fileName.size ());
|
||||
|
||||
if (gameVersion == GameVersion::JPN39 && chsPatch) {
|
||||
if (file.starts_with (L"DeviceInitialize")) base.append(L"DeviceInitialize_china.xml");
|
||||
if (file.starts_with (L"TestMode")) base.append(L"TestMode_china.xml");
|
||||
if (file.starts_with (L"DeviceInitialize")) base.append (L"DeviceInitialize_china.xml");
|
||||
if (file.starts_with (L"TestMode")) base.append (L"TestMode_china.xml");
|
||||
if (std::filesystem::exists (base)) return base;
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t* lFileName) {
|
||||
std::wstring originalFileName = std::wstring(lFileName);
|
||||
std::wstring fileName = originalFileName;
|
||||
if (fileName.ends_with (L"DeviceInitialize.xml") || fileName.ends_with (L"DeviceInitialize_asia.xml") || fileName.ends_with (L"DeviceInitialize_china.xml")) {
|
||||
HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) {
|
||||
std::wstring originalFileName = std::wstring (lFileName);
|
||||
std::wstring fileName = originalFileName;
|
||||
if (fileName.ends_with (L"DeviceInitialize.xml") || fileName.ends_with (L"DeviceInitialize_asia.xml")
|
||||
|| fileName.ends_with (L"DeviceInitialize_china.xml")) {
|
||||
if (moddedInitial == L"") {
|
||||
fileName = ReadXMLFileSwitcher (fileName);
|
||||
pugi::xml_document doc;
|
||||
if (!doc.load_file(fileName.c_str())) {
|
||||
std::wcerr << "Loading DeviceInitialize structure failed! path: " << fileName << std::endl;
|
||||
if (!doc.load_file (fileName.c_str ())) {
|
||||
LogMessage (LOG_LEVEL_ERROR, L"Loading DeviceInitialize structure failed! path: " + fileName);
|
||||
moddedInitial = fileName;
|
||||
} else {
|
||||
std::wstring modFileName = replace (replace (replace (fileName, L"lize_asia.xml", L"lize_mod.xml"), L"lize_china.xml", L"lize_mod.xml"), L"lize.xml", L"lize_mod.xml");
|
||||
pugi::xpath_query dongleQuery = pugi::xpath_query(L"/root/menu[@id='TopMenu']/layout[@type='Center']/select-item[@id='DongleItem']");
|
||||
pugi::xml_node dongleItem = doc.select_node(dongleQuery).node();
|
||||
pugi::xml_node talItem = dongleItem.parent().append_copy(dongleItem);
|
||||
talItem.attribute(L"label").set_value(L"TAIKOARCADELOADER");
|
||||
talItem.attribute(L"id").set_value(L"TaikoArcadeLoader");
|
||||
talItem.append_attribute(L"default") = L"1";
|
||||
dongleItem.parent().append_child(L"break-item");
|
||||
std::wstring modFileName
|
||||
= replace (replace (replace (fileName, L"lize_asia.xml", L"lize_mod.xml"), L"lize_china.xml", L"lize_mod.xml"), L"lize.xml",
|
||||
L"lize_mod.xml");
|
||||
pugi::xpath_query dongleQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']/layout[@type='Center']/select-item[@id='DongleItem']");
|
||||
pugi::xml_node dongleItem = doc.select_node (dongleQuery).node ();
|
||||
pugi::xml_node talItem = dongleItem.parent ().append_copy (dongleItem);
|
||||
talItem.attribute (L"label").set_value (L"TAIKOARCADELOADER");
|
||||
talItem.attribute (L"id").set_value (L"TaikoArcadeLoader");
|
||||
talItem.append_attribute (L"default") = L"1";
|
||||
dongleItem.parent ().append_child (L"break-item");
|
||||
|
||||
doc.save_file(modFileName.c_str());
|
||||
doc.save_file (modFileName.c_str ());
|
||||
moddedInitial = modFileName;
|
||||
fileName = modFileName;
|
||||
fileName = modFileName;
|
||||
}
|
||||
} else fileName = moddedInitial;
|
||||
} else if (fileName.ends_with (L"TestMode.xml") || fileName.ends_with (L"TestMode_asia.xml") || fileName.ends_with (L"TestMode_china.xml")) {
|
||||
if (modded == L"") {
|
||||
if (!registeredItems.empty() || !registeredModifies.empty()) {
|
||||
if (!registeredItems.empty () || !registeredModifies.empty ()) {
|
||||
fileName = ReadXMLFileSwitcher (fileName);
|
||||
pugi::xml_document doc;
|
||||
if (!doc.load_file(fileName.c_str())) {
|
||||
std::wcerr << "Loading TestMode structure failed! path: " << fileName << std::endl;
|
||||
if (!doc.load_file (fileName.c_str ())) {
|
||||
LogMessage (LOG_LEVEL_ERROR, L"Loading TestMode structure failed! path: " + fileName);
|
||||
modded = fileName;
|
||||
} else {
|
||||
std::wstring modFileName = replace (replace (replace (fileName, L"Mode_asia.xml", L"Mode_mod.xml"), L"Mode_china.xml", L"Mode_mod.xml"), L"Mode.xml", L"Mode_mod.xml");
|
||||
if (!registeredItems.empty()) {
|
||||
pugi::xpath_query menuQuery = pugi::xpath_query(L"/root/menu[@id='TopMenu']/layout[@type='Center']/menu-item[@menu='GameOptionsMenu']");
|
||||
pugi::xml_node menuItem = doc.select_node(menuQuery).node();
|
||||
menuItem = menuItem.next_sibling();
|
||||
pugi::xml_node modMenuEntry = menuItem.parent().insert_child_after(L"menu-item", menuItem);
|
||||
modMenuEntry.append_attribute(L"label") = L"MOD MANAGER";
|
||||
modMenuEntry.append_attribute(L"menu") = L"ModManagerMenu";
|
||||
menuItem.parent().insert_child_after(L"break-item", modMenuEntry);
|
||||
std::wstring modFileName
|
||||
= replace (replace (replace (fileName, L"Mode_asia.xml", L"Mode_mod.xml"), L"Mode_china.xml", L"Mode_mod.xml"), L"Mode.xml",
|
||||
L"Mode_mod.xml");
|
||||
if (!registeredItems.empty ()) {
|
||||
pugi::xpath_query menuQuery
|
||||
= pugi::xpath_query (L"/root/menu[@id='TopMenu']/layout[@type='Center']/menu-item[@menu='GameOptionsMenu']");
|
||||
pugi::xml_node menuItem = doc.select_node (menuQuery).node ();
|
||||
menuItem = menuItem.next_sibling ();
|
||||
pugi::xml_node modMenuEntry = menuItem.parent ().insert_child_after (L"menu-item", menuItem);
|
||||
modMenuEntry.append_attribute (L"label") = L"MOD MANAGER";
|
||||
modMenuEntry.append_attribute (L"menu") = L"ModManagerMenu";
|
||||
menuItem.parent ().insert_child_after (L"break-item", modMenuEntry);
|
||||
|
||||
pugi::xml_document modMenu;
|
||||
std::vector<std::wstring> toInsertItems = {};
|
||||
for (RegisteredItem *item : registeredItems) {
|
||||
toInsertItems.push_back(item->selectItem);
|
||||
item->registerInit();
|
||||
toInsertItems.push_back (item->selectItem);
|
||||
item->registerInit ();
|
||||
}
|
||||
CreateMenu(modMenu, L"ModManagerMenu", L"MOD MANAGER", toInsertItems, L"TopMenu");
|
||||
pugi::xpath_query topMenuQuery = pugi::xpath_query(L"/root/menu[@id='TopMenu']");
|
||||
pugi::xml_node topMenu = doc.select_node(topMenuQuery).node();
|
||||
topMenu.parent().insert_copy_after(modMenu.first_child(), topMenu);
|
||||
CreateMenu (modMenu, L"ModManagerMenu", L"MOD MANAGER", toInsertItems, L"TopMenu");
|
||||
pugi::xpath_query topMenuQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']");
|
||||
pugi::xml_node topMenu = doc.select_node (topMenuQuery).node ();
|
||||
topMenu.parent ().insert_copy_after (modMenu.first_child (), topMenu);
|
||||
}
|
||||
|
||||
if (!registeredModifies.empty()) {
|
||||
if (!registeredModifies.empty ()) {
|
||||
for (RegisteredModify *modify : registeredModifies) {
|
||||
pugi::xpath_query modifyQuery = pugi::xpath_query(modify->query.c_str());
|
||||
pugi::xpath_query modifyQuery = pugi::xpath_query (modify->query.c_str ());
|
||||
try {
|
||||
pugi::xml_node modifyNode = doc.select_node(modifyQuery).node();
|
||||
pugi::xml_node modifyNode = doc.select_node (modifyQuery).node ();
|
||||
if (modifyNode) {
|
||||
modify->nodeModify(modifyNode);
|
||||
modify->registerInit();
|
||||
modify->nodeModify (modifyNode);
|
||||
modify->registerInit ();
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
std::wcerr << "[TestMode Error] failed to find node by xpath: " << modify->query << std::endl;
|
||||
}
|
||||
} catch (std::exception &e) { LogMessage (LOG_LEVEL_ERROR, L"Failed to find node by xpath: " + modify->query); }
|
||||
}
|
||||
}
|
||||
|
||||
doc.save_file(modFileName.c_str());
|
||||
modded = modFileName;
|
||||
doc.save_file (modFileName.c_str ());
|
||||
modded = modFileName;
|
||||
fileName = modFileName;
|
||||
}
|
||||
} else modded = fileName;
|
||||
} else fileName = modded;
|
||||
}
|
||||
|
||||
std::wcout << "TestModeLibrary load: " << fileName << std::endl;
|
||||
|
||||
originalTestModeSetMenuHook.call<void> (testModeLibrary, fileName.c_str());
|
||||
LogMessage (LOG_LEVEL_DEBUG, L"TestModeLibrary load: " + fileName);
|
||||
originalTestModeSetMenuHook.call<void> (testModeLibrary, fileName.c_str ());
|
||||
}
|
||||
|
||||
void
|
||||
CommonModify () {
|
||||
// Default off Close time
|
||||
TestMode::RegisterModify(
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='CloseTimeSettingMenu']/layout[@type='Center']/select-item[@id='ScheduleTypeItem']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"default").set_value(L"0"); }, [&](){}
|
||||
);
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"default").set_value (L"0"); }, [&] () {});
|
||||
}
|
||||
|
||||
void
|
||||
LocalizationCHT () {
|
||||
TestMode::RegisterModify(
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='TopMenu']/layout[@type='Center']/menu-item[@menu='ModManagerMenu']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"模組管理"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"模組管理"); }, [] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Header']/text-item",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"模組管理"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"模組管理"); }, [] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModFreezeTimer']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"凍結計時"); node.attribute(L"replace-text").set_value(L"0:關閉, 1:開啓"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"凍結計時");
|
||||
node.attribute (L"replace-text").set_value (L"0:關閉, 1:開啓");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo024']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"鬼滅之刃模式"); node.attribute(L"replace-text").set_value(L"0:黙認, 1:啓用, 2:僅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"鬼滅之刃模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:黙認, 1:啓用, 2:僅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo025']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"航海王模式"); node.attribute(L"replace-text").set_value(L"0:黙認, 1:啓用, 2:僅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"航海王模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:黙認, 1:啓用, 2:僅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo026']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"AI粗品模式"); node.attribute(L"replace-text").set_value(L"0:黙認, 1:啓用, 2:僅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"AI粗品模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:黙認, 1:啓用, 2:僅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeAprilFool001']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"青春之達人模式"); node.attribute(L"replace-text").set_value(L"0:黙認, 1:啓用, 2:僅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"青春之達人模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:黙認, 1:啓用, 2:僅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/menu-item[@menu='TopMenu']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"離開"); }, [](){}
|
||||
);
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"離開"); }, [] () {});
|
||||
}
|
||||
|
||||
void
|
||||
LocalizationCHS () {
|
||||
TestMode::RegisterModify(
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='TopMenu']/layout[@type='Center']/menu-item[@menu='ModManagerMenu']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"模组管理"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"模组管理"); }, [] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Header']/text-item",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"模组管理"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"模组管理"); }, [] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModFreezeTimer']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"冻结计时"); node.attribute(L"replace-text").set_value(L"0:禁用, 1:启用"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"冻结计时");
|
||||
node.attribute (L"replace-text").set_value (L"0:禁用, 1:启用");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo024']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"鬼灭之刃模式"); node.attribute(L"replace-text").set_value(L"0:默认, 1:启用, 2:仅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"鬼灭之刃模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:默认, 1:启用, 2:仅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo025']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"航海王模式"); node.attribute(L"replace-text").set_value(L"0:默认, 1:启用, 2:仅刷卡"); }, [](){}
|
||||
);
|
||||
TestMode::RegisterModify(
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"航海王模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:默认, 1:启用, 2:仅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeCollabo026']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"AI粗品模式"); node.attribute(L"replace-text").set_value(L"0:默认, 1:启用, 2:仅刷卡"); }, [](){}
|
||||
);
|
||||
[&] (pugi::xml_node &node) {
|
||||
node.attribute (L"label").set_value (L"AI粗品模式");
|
||||
node.attribute (L"replace-text").set_value (L"0:默认, 1:启用, 2:仅刷卡");
|
||||
},
|
||||
[] () {});
|
||||
// TestMode::RegisterModify(
|
||||
// L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/select-item[@id='ModModeAprilFool001']",
|
||||
// [&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"青春之达人模式"); node.attribute(L"replace-text").set_value(L"0:默认, 1:启用, 2:仅刷卡"); }, [](){}
|
||||
// [&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"青春之达人模式"); node.attribute(L"replace-text").set_value(L"0:默认,
|
||||
// 1:启用, 2:仅刷卡"); }, [](){}
|
||||
// );
|
||||
TestMode::RegisterModify(
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='ModManagerMenu']/layout[@type='Center']/menu-item[@menu='TopMenu']",
|
||||
[&](pugi::xml_node &node) { node.attribute(L"label").set_value(L"离开"); }, [](){}
|
||||
);
|
||||
[&] (pugi::xml_node &node) { node.attribute (L"label").set_value (L"离开"); }, [] () {});
|
||||
}
|
||||
|
||||
void
|
||||
Init () {
|
||||
LogMessage (LOG_LEVEL_DEBUG, "Init TestMode patches");
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
|
||||
|
||||
u64 testModeSetMenuAddress = PROC_ADDRESS_OFFSET ("TestModeLibrary.dll", 0x99D0);
|
||||
switch (gameVersion) {
|
||||
case GameVersion::UNKNOWN: break;
|
||||
case GameVersion::JPN00: break;
|
||||
case GameVersion::JPN08: break;
|
||||
case GameVersion::JPN39: {
|
||||
if (config_ptr) {
|
||||
auto patches = openConfigSection (config_ptr.get (), "patches");
|
||||
if (patches) {
|
||||
auto jpn39 = openConfigSection (patches, "jpn39");
|
||||
if (jpn39) {
|
||||
chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
|
||||
}
|
||||
}
|
||||
case GameVersion::UNKNOWN: break;
|
||||
case GameVersion::JPN00: break;
|
||||
case GameVersion::JPN08: break;
|
||||
case GameVersion::JPN39: {
|
||||
if (config_ptr) {
|
||||
auto patches = openConfigSection (config_ptr.get (), "patches");
|
||||
if (patches) {
|
||||
auto jpn39 = openConfigSection (patches, "jpn39");
|
||||
if (jpn39) chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
|
||||
}
|
||||
if (chsPatch) LocalizationCHT();
|
||||
} break;
|
||||
case GameVersion::CHN00: break;
|
||||
}
|
||||
if (chsPatch) LocalizationCHT ();
|
||||
} break;
|
||||
case GameVersion::CHN00: break;
|
||||
}
|
||||
|
||||
CommonModify ();
|
||||
@@ -300,34 +322,36 @@ SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode) {
|
||||
}
|
||||
|
||||
int
|
||||
ReadTestModeValue (const wchar_t* itemId) {
|
||||
ReadTestModeValue (const wchar_t *itemId) {
|
||||
if (appAccessor) {
|
||||
u64 testModeMain = refTestMode (appAccessor);
|
||||
if (testModeMain) {
|
||||
int value = 0;
|
||||
u64* reader = *(u64**)(testModeMain + 16);
|
||||
(*(void (__fastcall **)(u64*, const wchar_t *, int *))(*reader + 256))(reader, itemId, &value);
|
||||
int value = 0;
|
||||
u64 *reader = *(u64 **)(testModeMain + 16);
|
||||
(*(void (__fastcall **) (u64 *, const wchar_t *, int *)) (*reader + 256)) (reader, itemId, &value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
std::wcerr << "Read TestMode(" << itemId << ") failed!" << std::endl;
|
||||
LogMessage (LOG_LEVEL_ERROR, (std::wstring (L"Read TestMode(") + itemId + L") failed!").c_str ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring item, const std::function<void()> &initMethod) {
|
||||
registeredItems.push_back(new RegisteredItem(item, initMethod));
|
||||
RegisterItem (const std::wstring item, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, L"Register Item " + item);
|
||||
registeredItems.push_back (new RegisteredItem (item, initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterModify (const std::wstring query, const std::function<void(pugi::xml_node &)> &nodeModify, const std::function<void()> &initMethod) {
|
||||
registeredModifies.push_back(new RegisteredModify(query, nodeModify, initMethod));
|
||||
RegisterModify (const std::wstring query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LOG_LEVEL_DEBUG, L"Register Modify " + query);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
Append (pugi::xml_node &node, const wchar_t *attr, const std::wstring append) {
|
||||
pugi::xml_attribute attribute = node.attribute (attr);
|
||||
std::wstring attrValue = std::wstring(attribute.value ()) + append;
|
||||
std::wstring attrValue = std::wstring (attribute.value ()) + append;
|
||||
attribute.set_value (attrValue.c_str ());
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
extern std::string chassisId;
|
||||
|
||||
namespace patches::CHN00 {
|
||||
|
||||
int language = 0;
|
||||
u8 *haspBuffer;
|
||||
HOOK (i32, HaspDecrypt, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_decrypt")) { return 0; }
|
||||
HOOK (i32, HaspEncrypt, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_encrypt")) { return 0; }
|
||||
@@ -35,38 +35,42 @@ lua_pushtrue (i64 a1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
HOOK (i64, AvailableMode_Dani_AI, ASLR (0x1401AC550), i64 a1) { return lua_pushtrue (a1); }
|
||||
HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402BFF70), i64 *, i64 a2) { return lua_pushtrue (a2); }
|
||||
HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402BC9B0), i64 a1) { return lua_pushtrue (a1); }
|
||||
|
||||
int language = 0;
|
||||
const char *
|
||||
languageStr () {
|
||||
switch (language) {
|
||||
case 1: return "en_us";
|
||||
case 2: return "cn_tw";
|
||||
case 3: return "kor";
|
||||
case 4: return "cn_cn";
|
||||
default: return "jpn";
|
||||
}
|
||||
HOOK (i64, AvailableMode_Dani_AI, ASLR (0x1401AC550), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Dani_AI was called");
|
||||
return lua_pushtrue (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402BFF70), i64 *, i64 a2) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo025 was called");
|
||||
return lua_pushtrue (a2);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402BC9B0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo026 was called");
|
||||
return lua_pushtrue (a1);
|
||||
}
|
||||
|
||||
HOOK (i64, GetLanguage, ASLR (0x140023720), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetLanguage was called");
|
||||
auto result = originalGetLanguage.call<i64> (a1);
|
||||
language = *((u32 *)result);
|
||||
return result;
|
||||
}
|
||||
HOOK (i64, GetRegionLanguage, ASLR (0x1401AC300), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetRegionLanguage was called");
|
||||
lua_settop (a1, 0);
|
||||
lua_pushstring (a1, (u64)languageStr ());
|
||||
lua_pushstring (a1, (u64)languageStr (language));
|
||||
return 1;
|
||||
}
|
||||
HOOK (i64, GetCabinetLanguage, ASLR (0x1401AF270), i64, i64 a2) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetCabinetLanguage was called");
|
||||
lua_settop (a2, 0);
|
||||
lua_pushstring (a2, (u64)languageStr ());
|
||||
lua_pushstring (a2, (u64)languageStr (language));
|
||||
return 1;
|
||||
}
|
||||
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; }
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AMFWTerminate was called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const i32 datatableBufferSize = 1024 * 1024 * 12;
|
||||
safetyhook::Allocation datatableBuffer1;
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
#include "../patches.h"
|
||||
#include <safetyhook.hpp>
|
||||
|
||||
extern u64 song_data_size;
|
||||
extern void *song_data;
|
||||
|
||||
#define RDX_MOV 0x48, 0xBA
|
||||
#define R8_MOV 0x49, 0xB8
|
||||
#define GENERATE_MOV(instruction, location) \
|
||||
instruction, (u8)(u64)(location), (u8)((u64)(location) >> 8), (u8)((u64)(location) >> 16), (u8)((u64)(location) >> 24), \
|
||||
(u8)((u64)(location) >> 32), (u8)((u64)(location) >> 40), (u8)((u64)(location) >> 48), (u8)((u64)(location) >> 56)
|
||||
|
||||
namespace patches::JPN00 {
|
||||
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; }
|
||||
|
||||
+99
-147
@@ -4,11 +4,14 @@
|
||||
#include <safetyhook.hpp>
|
||||
|
||||
namespace patches::JPN39 {
|
||||
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; }
|
||||
int language = 0;
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AMFWTerminate was called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) {
|
||||
// printf ("garmc curl_easy_setopt\n");
|
||||
LogMessage (LOG_LEVEL_HOOKS, "Garmc curl_easy_setopt was called");
|
||||
originalcurl_easy_setopt.call<i64> (a1, 64, 0, 0, 0);
|
||||
originalcurl_easy_setopt.call<i64> (a1, 81, 0, 0, 0);
|
||||
return originalcurl_easy_setopt.call<i64> (a1, a2, a3, a4, a5);
|
||||
@@ -41,9 +44,10 @@ lua_pushbool (i64 a1, bool val) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
u64 appAccessor = 0;
|
||||
u64 appAccessor = 0;
|
||||
u64 componentAccessor = 0;
|
||||
HOOK (i64, DeviceCheck, ASLR(0x140464FC0), i64 a1, i64 a2, i64 a3) {
|
||||
HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "DeviceCheck was called");
|
||||
TestMode::SetupAccessor (a3, RefTestModeMain);
|
||||
componentAccessor = a2;
|
||||
return originalDeviceCheck.call<i64> (a1, a2, a3);
|
||||
@@ -53,55 +57,53 @@ int
|
||||
GetUserStatus () {
|
||||
if (appAccessor) {
|
||||
u64 playDataManager = RefPlayDataManager (appAccessor);
|
||||
if (playDataManager) return GetUserCount(playDataManager);
|
||||
if (playDataManager) return GetUserCount (playDataManager);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo024 was called");
|
||||
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo024.call<i64> (a1);
|
||||
int status = TestMode::ReadTestModeValue (L"ModModeCollabo024");
|
||||
if (status == 1 && GetUserStatus () == 1) {
|
||||
return lua_pushbool (a1, true);
|
||||
}
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo024.call<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo025 was called");
|
||||
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo025.call<i64> (a1);
|
||||
int status = TestMode::ReadTestModeValue (L"ModModeCollabo025");
|
||||
if (status == 1 && GetUserStatus () == 1) {
|
||||
return lua_pushbool (a1, true);
|
||||
}
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo025.call<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo026 was called");
|
||||
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo026.call<i64> (a1);
|
||||
int status = TestMode::ReadTestModeValue (L"ModModeCollabo026");
|
||||
if (status == 1 && GetUserStatus () == 1) {
|
||||
return lua_pushbool (a1, true);
|
||||
}
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo026.call<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_AprilFool001 was called");
|
||||
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_AprilFool001.call<i64> (a1);
|
||||
int status = TestMode::ReadTestModeValue (L"ModModeAprilFool001");
|
||||
if (status == 1) {
|
||||
return lua_pushbool (a1, true);
|
||||
}
|
||||
if (status == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_AprilFool001.call<i64> (a1);
|
||||
}
|
||||
i64 __fastcall lua_freeze_timer (i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "lua_freeze_timer was called");
|
||||
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return lua_pushbool (a1, true);
|
||||
if (tournamentMode == 1) return lua_pushbool (a1, true);
|
||||
int status = TestMode::ReadTestModeValue (L"ModFreezeTimer");
|
||||
if (status == 1) return lua_pushbool (a1, true);
|
||||
return lua_pushbool (a1, false);
|
||||
}
|
||||
MID_HOOK (FreezeTimer, ASLR (0x14019FF51), SafetyHookContext &ctx) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "FreezeTimer was called");
|
||||
auto a1 = ctx.rdi;
|
||||
int v9 = (int)(ctx.rax + 1);
|
||||
lua_pushcclosure (a1, reinterpret_cast<i64> (&lua_freeze_timer), v9);
|
||||
@@ -156,110 +158,53 @@ ExecuteSendResultData () {
|
||||
);
|
||||
}
|
||||
|
||||
bool sendFlag = false;
|
||||
#define SCENE_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \
|
||||
if ( \
|
||||
TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && \
|
||||
TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4 \
|
||||
) { original##functionName.call (a1, a2, a3); return; } \
|
||||
sendFlag = true; \
|
||||
original##functionName.call (a1, a2, a3); \
|
||||
ExecuteSendResultData (); \
|
||||
}
|
||||
|
||||
SCENE_RESULT_HOOK (SceneResultInitialize_Enso, ASLR (0x140411FD0));
|
||||
SCENE_RESULT_HOOK (SceneResultInitialize_AI, ASLR (0x140411FD0));
|
||||
SCENE_RESULT_HOOK (SceneResultInitialize_Collabo025, ASLR (0x140411FD0));
|
||||
SCENE_RESULT_HOOK (SceneResultInitialize_Collabo026, ASLR (0x140411FD0));
|
||||
SCENE_RESULT_HOOK (SceneResultInitialize_AprilFool, ASLR (0x140411FD0));
|
||||
|
||||
#define SEND_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1) { \
|
||||
if ( \
|
||||
TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && \
|
||||
TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4 \
|
||||
) { original##functionName.call (a1); return; } \
|
||||
if (sendFlag) { \
|
||||
sendFlag = false; \
|
||||
original##functionName.call (a1); \
|
||||
} \
|
||||
}
|
||||
|
||||
SEND_RESULT_HOOK (SendResultData_Enso, ASLR (0x1401817B0));
|
||||
SEND_RESULT_HOOK (SendResultData_AI, ASLR (0x1401755E0));
|
||||
SEND_RESULT_HOOK (SendResultData_Collabo025_026, ASLR (0x140179A00));
|
||||
SEND_RESULT_HOOK (SendResultData_AprilFool, ASLR (0x140177800));
|
||||
|
||||
#define CHANGE_RESULT_SIZE_HOOK(functionName, location, target) \
|
||||
MID_HOOK (functionName, location, SafetyHookContext &ctx) { \
|
||||
if ( \
|
||||
TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && \
|
||||
TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4 \
|
||||
) { return; } \
|
||||
i64 instance = RefPlayDataManager (*(i64 *)ctx.r12); \
|
||||
u32 currentStageCount = *(u32 *)(instance + 8); \
|
||||
ctx.target &= 0xFFFFFFFF00000000; \
|
||||
ctx.target |= currentStageCount; \
|
||||
}
|
||||
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Enso, ASLR (0x140180074), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AI, ASLR (0x140173774), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Collabo025_026, ASLR (0x140178244), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AprilFool, ASLR (0x140176044), rax);
|
||||
|
||||
#define CHANGE_RESULT_INDEX_HOOK(functionName, location, target, offset, skip) \
|
||||
MID_HOOK (functionName, location, SafetyHookContext &ctx) { \
|
||||
if ( \
|
||||
TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && \
|
||||
TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4 \
|
||||
) { return; } \
|
||||
i64 instance = RefPlayDataManager (*(i64 *)ctx.r12); \
|
||||
u32 currentStageCount = *(u32 *)(instance + 8); \
|
||||
ctx.target &= 0xFFFFFFFF00000000; \
|
||||
ctx.target |= currentStageCount - 1; \
|
||||
*(u32 *)(ctx.rsp + offset) = currentStageCount - 1; \
|
||||
ctx.rip += skip; \
|
||||
}
|
||||
|
||||
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Enso, ASLR (0x14018074B), rax, 0x34, 0x07);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AI, ASLR (0x140173EDD), r13, 0x24, 0x08);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Collabo025_026, ASLR (0x1401789AD), r13, 0x24, 0x08);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AprilFool, ASLR (0x140176716), rax, 0x34, 0x06);
|
||||
|
||||
int language = 0;
|
||||
const char *
|
||||
languageStr () {
|
||||
switch (language) {
|
||||
case 1: return "en_us";
|
||||
case 2: return "cn_tw";
|
||||
case 3: return "kor";
|
||||
case 4: return "cn_cn";
|
||||
default: return "jpn";
|
||||
}
|
||||
}
|
||||
HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetLanguage was called");
|
||||
auto result = originalGetLanguage.call<i64> (a1);
|
||||
language = *((u32 *)result);
|
||||
return result;
|
||||
}
|
||||
HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetRegionLanguage was called");
|
||||
lua_settop (a1, 0);
|
||||
lua_pushstring (a1, languageStr ());
|
||||
lua_pushstring (a1, languageStr (language));
|
||||
return 1;
|
||||
}
|
||||
HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GetCabinetLanguage was called");
|
||||
lua_settop (a2, 0);
|
||||
lua_pushstring (a2, languageStr ());
|
||||
lua_pushstring (a2, languageStr (language));
|
||||
return 1;
|
||||
}
|
||||
|
||||
MID_HOOK (ChangeLanguageType, ASLR (0x1400B2016), SafetyHookContext &ctx) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "ChangeLanguageType was called");
|
||||
int *pFontType = (int *)ctx.rax;
|
||||
if (*pFontType == 4) *pFontType = 2;
|
||||
}
|
||||
|
||||
MID_HOOK (CountLockedCrown, ASLR (0x1403F2A25), SafetyHookContext &ctx) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "CountLockedCrown was called");
|
||||
ctx.r15 |= 1;
|
||||
}
|
||||
|
||||
@@ -312,6 +257,7 @@ check_voice_tail (std::string bankName, uint8_t *pBinfBlock, std::map<std::strin
|
||||
}
|
||||
|
||||
MID_HOOK (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "GenNus3bankId was called");
|
||||
std::lock_guard<std::mutex> lock (nus3bankMtx);
|
||||
if ((uint8_t **)(ctx.rcx + 8) != nullptr) {
|
||||
uint8_t *pNus3bankFile = *((uint8_t **)(ctx.rcx + 8));
|
||||
@@ -337,6 +283,7 @@ FixToneName (std::string bankName, std::string toneName) {
|
||||
|
||||
size_t commonSize = 0;
|
||||
HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "PlaySound was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
std::string bankName (lua_tolstring (a1, -3, &commonSize));
|
||||
if (bankName[0] == 'v') {
|
||||
@@ -348,6 +295,7 @@ HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) {
|
||||
}
|
||||
|
||||
HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundMulti was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
std::string bankName ((char *)lua_tolstring (a1, -3, &commonSize));
|
||||
if (bankName[0] == 'v') {
|
||||
@@ -369,6 +317,7 @@ FixToneNameEnso (u64 *Src, std::string &bankName) {
|
||||
}
|
||||
|
||||
HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundEnso was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
std::string bankName = a1[3] > 0x10 ? std::string (*((char **)a1)) : std::string ((char *)a1);
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
|
||||
@@ -377,6 +326,7 @@ HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
|
||||
}
|
||||
|
||||
HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundSpecial was called");
|
||||
if (enableSwitchVoice && language != 0) {
|
||||
std::string bankName = a1[3] > 0x10 ? std::string (*((char **)a1)) : std::string ((char *)a1);
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
|
||||
@@ -386,6 +336,7 @@ HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
|
||||
|
||||
int loaded_fail_count = 0;
|
||||
HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "LoadedBankAll was called");
|
||||
originalLoadedBankAll.call<i64> (a1);
|
||||
auto result = lua_toboolean (a1, -1);
|
||||
lua_settop (a1, 0);
|
||||
@@ -404,27 +355,29 @@ HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) {
|
||||
|
||||
float soundRate = 1.0F;
|
||||
HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "SetMasterVolumeSpeaker was called");
|
||||
soundRate = a1 <= 100 ? 1.0F : a1 / 100.0;
|
||||
return originalSetMasterVolumeSpeaker.call<i32> (a1 > 100 ? 100 : a1);
|
||||
}
|
||||
|
||||
HOOK (u64, NuscBusVolume, ASLR (0x1407B1C30), u64 a1, u64 a2, float a3) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "NuscBusVolume was called");
|
||||
return originalNuscBusVolume.call<u64> (a1, a2, a3 * soundRate);
|
||||
}
|
||||
|
||||
std::string* fontName = nullptr;
|
||||
std::string *fontName = nullptr;
|
||||
HOOK (u8, SetupFontInfo, ASLR (0x14049D820), u64 a1, u64 a2, size_t a3, u64 a4) {
|
||||
LogMessage (LOG_LEVEL_HOOKS, "SetupFontInfo was called");
|
||||
if (fontName != nullptr) delete fontName;
|
||||
fontName = new std::string(((char*)a1) + 120);
|
||||
fontName = new std::string (((char *)a1) + 120);
|
||||
return originalSetupFontInfo.call<u8> (a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
HOOK (u32, ReadFontInfoInt, ASLR (0x14049EAC0), u64 a1, u64 a2) {
|
||||
std::string attribute((char*)a2);
|
||||
LogMessage (LOG_LEVEL_HOOKS, "ReadFontInfoInt was called");
|
||||
std::string attribute ((char *)a2);
|
||||
u32 result = originalReadFontInfoInt.call<u32> (a1, a2);
|
||||
if (fontName->starts_with("cn_") && attribute == "offsetV") {
|
||||
result += 1;
|
||||
}
|
||||
if (fontName->starts_with ("cn_") && attribute == "offsetV") result += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -457,13 +410,12 @@ ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *ne
|
||||
|
||||
void
|
||||
Init () {
|
||||
i32 xRes = 1920;
|
||||
i32 yRes = 1080;
|
||||
bool vsync = false;
|
||||
bool unlockSongs = true;
|
||||
bool fixLanguage = false;
|
||||
bool chsPatch = false;
|
||||
|
||||
i32 xRes = 1920;
|
||||
i32 yRes = 1080;
|
||||
bool vsync = false;
|
||||
bool unlockSongs = true;
|
||||
bool fixLanguage = false;
|
||||
bool chsPatch = false;
|
||||
bool useLayeredfs = false;
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||
@@ -474,8 +426,8 @@ Init () {
|
||||
unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
|
||||
auto jpn39 = openConfigSection (patches, "jpn39");
|
||||
if (jpn39) {
|
||||
fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage);
|
||||
chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
|
||||
fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage);
|
||||
chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,55 +507,55 @@ Init () {
|
||||
}
|
||||
|
||||
// Freeze Timer
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"FREEZE TIMER\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" group=\"Setting\" id=\"ModFreezeTimer\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() { INSTALL_MID_HOOK (FreezeTimer); }
|
||||
);
|
||||
TestMode::RegisterItem (L"<select-item label=\"FREEZE TIMER\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModFreezeTimer\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () { INSTALL_MID_HOOK (FreezeTimer); });
|
||||
// Mode Unlock
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"KIMETSU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo024\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() { INSTALL_HOOK (AvailableMode_Collabo024); }
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"ONE PIECE MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo025\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() { INSTALL_HOOK (AvailableMode_Collabo025); }
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"AI SOSHINA MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo026\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() { INSTALL_HOOK (AvailableMode_Collabo026); }
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"AOHARU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeAprilFool001\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() { INSTALL_HOOK (AvailableMode_AprilFool001); }
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
L"<select-item label=\"INSTANT RESULT\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" group=\"Setting\" id=\"ModInstantResult\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (SceneResultInitialize_Enso);
|
||||
INSTALL_HOOK (SceneResultInitialize_AI);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo025);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo026);
|
||||
INSTALL_HOOK (SceneResultInitialize_AprilFool);
|
||||
INSTALL_HOOK (SendResultData_Enso);
|
||||
INSTALL_HOOK (SendResultData_AI);
|
||||
INSTALL_HOOK (SendResultData_Collabo025_026);
|
||||
INSTALL_HOOK (SendResultData_AprilFool);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Enso);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_AI);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Collabo025_026);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_AprilFool);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_Enso);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_AI);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_Collabo025_026);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_AprilFool);
|
||||
}
|
||||
);
|
||||
TestMode::RegisterItem (L"<select-item label=\"KIMETSU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo024\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () { INSTALL_HOOK (AvailableMode_Collabo024); });
|
||||
TestMode::RegisterItem (L"<select-item label=\"ONE PIECE MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo025\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () { INSTALL_HOOK (AvailableMode_Collabo025); });
|
||||
TestMode::RegisterItem (L"<select-item label=\"AI SOSHINA MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo026\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () { INSTALL_HOOK (AvailableMode_Collabo026); });
|
||||
TestMode::RegisterItem (L"<select-item label=\"AOHARU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeAprilFool001\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () { INSTALL_HOOK (AvailableMode_AprilFool001); });
|
||||
TestMode::RegisterItem (L"<select-item label=\"INSTANT RESULT\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModInstantResult\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] () {
|
||||
INSTALL_HOOK (SceneResultInitialize_Enso);
|
||||
INSTALL_HOOK (SceneResultInitialize_AI);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo025);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo026);
|
||||
INSTALL_HOOK (SceneResultInitialize_AprilFool);
|
||||
INSTALL_HOOK (SendResultData_Enso);
|
||||
INSTALL_HOOK (SendResultData_AI);
|
||||
INSTALL_HOOK (SendResultData_Collabo025_026);
|
||||
INSTALL_HOOK (SendResultData_AprilFool);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Enso);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_AI);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Collabo025_026);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_AprilFool);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_Enso);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_AI);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_Collabo025_026);
|
||||
INSTALL_MID_HOOK (ChangeResultDataIndex_AprilFool);
|
||||
});
|
||||
// Unlimit Volume
|
||||
TestMode::RegisterModify(
|
||||
TestMode::RegisterModify (
|
||||
L"/root/menu[@id='SoundTestMenu']/layout[@type='Center']/select-item[@id='OutputLevelSpeakerItem']",
|
||||
[&](pugi::xml_node &node) { TestMode::Append(node, L"label", L"*"); node.attribute(L"max").set_value(L"300"); node.attribute(L"delta").set_value(L"1"); },
|
||||
[&]() { INSTALL_HOOK (SetMasterVolumeSpeaker); INSTALL_HOOK (NuscBusVolume); }
|
||||
);
|
||||
[&] (pugi::xml_node &node) {
|
||||
TestMode::Append (node, L"label", L"*");
|
||||
node.attribute (L"max").set_value (L"300");
|
||||
node.attribute (L"delta").set_value (L"1");
|
||||
},
|
||||
[&] () {
|
||||
INSTALL_HOOK (SetMasterVolumeSpeaker);
|
||||
INSTALL_HOOK (NuscBusVolume);
|
||||
});
|
||||
// Instant Result
|
||||
// TestMode::RegisterModify(
|
||||
// L"/root/menu[@id='GameOptionsMenu']/layout[@type='Center']/select-item[@id='NumberOfStageItem']",
|
||||
@@ -636,10 +588,10 @@ Init () {
|
||||
INSTALL_HOOK (ReadFontInfoInt);
|
||||
}
|
||||
|
||||
LayeredFs::RegisterBefore([=](const std::string originalFileName, const std::string currentFileName) -> std::string {
|
||||
LayeredFs::RegisterBefore ([=] (const std::string originalFileName, const std::string currentFileName) -> std::string {
|
||||
if (currentFileName.find ("\\lumen\\") == std::string::npos) return "";
|
||||
std::string fileName = currentFileName;
|
||||
fileName = replace(fileName, "\\lumen\\", "\\lumen_cn\\");
|
||||
fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\");
|
||||
if (std::filesystem::exists (fileName)) return fileName;
|
||||
else return currentFileName;
|
||||
});
|
||||
|
||||
+13
-12
@@ -330,7 +330,7 @@ void
|
||||
SetConfigValue (toml_table_t *table, const char *key, Keybindings *keybind) {
|
||||
toml_array_t *array = toml_array_in (table, key);
|
||||
if (!array) {
|
||||
printWarning ("%s (%s): Cannot find array\n", __func__, key);
|
||||
LogMessage (LOG_LEVEL_WARN, (std::string (key) + ": Cannot find array").c_str ());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -395,16 +395,16 @@ InitializePoll (HWND windowHandle) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
|
||||
hasRumble = false;
|
||||
} else {
|
||||
printError ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): "
|
||||
"%s\n",
|
||||
SDL_GetError ());
|
||||
LogMessage (LOG_LEVEL_ERROR,
|
||||
(std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
|
||||
+ SDL_GetError ())
|
||||
.c_str ());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
|
||||
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
printError ("%s (): Cannot read gamecontrollerdb.txt\n", __func__);
|
||||
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) LogMessage (LOG_LEVEL_ERROR, "Cannot read gamecontrollerdb.txt");
|
||||
SDL_GameControllerEventState (SDL_ENABLE);
|
||||
SDL_JoystickEventState (SDL_ENABLE);
|
||||
|
||||
@@ -413,15 +413,15 @@ InitializePoll (HWND windowHandle) {
|
||||
|
||||
SDL_GameController *controller = SDL_GameControllerOpen (i);
|
||||
if (!controller) {
|
||||
printWarning ("Could not open gamecontroller %s: %s\n", SDL_GameControllerNameForIndex (i), SDL_GetError ());
|
||||
LogMessage (LOG_LEVEL_WARN,
|
||||
(std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ()).c_str ());
|
||||
continue;
|
||||
}
|
||||
controllers[i] = controller;
|
||||
}
|
||||
|
||||
window = SDL_CreateWindowFrom (windowHandle);
|
||||
if (window == NULL) printError ("SDL_CreateWindowFrom (windowHandle): %s\n", SDL_GetError ());
|
||||
|
||||
if (window == NULL) LogMessage (LOG_LEVEL_ERROR, (std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()).c_str ());
|
||||
atexit (DisposePoll);
|
||||
|
||||
return hasRumble;
|
||||
@@ -454,8 +454,9 @@ UpdatePoll (HWND windowHandle) {
|
||||
|
||||
controller = SDL_GameControllerOpen (event.cdevice.which);
|
||||
if (!controller) {
|
||||
printError ("%s (): Could not open gamecontroller %s: %s\n", __func__, SDL_GameControllerNameForIndex (event.cdevice.which),
|
||||
SDL_GetError ());
|
||||
LogMessage (LOG_LEVEL_ERROR, (std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
|
||||
+ ": " + SDL_GetError ())
|
||||
.c_str ());
|
||||
continue;
|
||||
}
|
||||
controllers[event.cdevice.which] = controller;
|
||||
@@ -548,7 +549,7 @@ StringToConfigEnum (const char *value) {
|
||||
return rval;
|
||||
}
|
||||
|
||||
printError ("%s (%s): Unknown value\n", __func__, value);
|
||||
LogMessage (LOG_LEVEL_ERROR, (std::string (value) + ": Unknown value").c_str ());
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user