1
0
mirror of synced 2024-11-28 01:10:55 +01:00

Switch compiler to MSVC (#16)

* Initial working cmake version
Code style changes according to CLion suggestions
Changed logging to use template instead of macros
---------
Co-authored-by: asesidaa <1061472754@qq.com>

* Reformat everything, updated readme for MSVC
* Warnings annoy me deeply
* Update artifact export
* Simplifying file hierarchy
Build result will now be in dist
This commit is contained in:
Farewell_ 2024-11-27 21:07:17 +01:00 committed by GitHub
parent b5d9488df6
commit 91a9f9ad25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 1448 additions and 1341 deletions

View File

@ -11,6 +11,7 @@ AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: True
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLambdasOnASingleLine: All
AlwaysBreakTemplateDeclarations: Yes
SpaceAfterTemplateKeyword: True
SpacesInAngles: Never

View File

@ -1,3 +1,5 @@
[*]
indent_style = tab
charset = utf-8
end_of_line = crlf
indent_style = space
indent_size = 4

View File

@ -1,21 +1,22 @@
name: Build and upload artifact
on: [ push, pull_request ]
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Install depends
run: sudo apt-get install -y mingw-w64 ninja-build nasm; pip3 install meson
- name: Upgrade gcc
run: npx xpm init && npx xpm install @xpack-dev-tools/mingw-w64-gcc@latest --verbose
- name: Make
run: export PATH=$GITHUB_WORKSPACE/xpacks/.bin:$PATH && make setup dist-no-7z
- uses: actions/upload-artifact@v3
with:
name: dist
path: out/
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Configure CMake
run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build --config Release --target bnusio
- uses: actions/upload-artifact@v4
with:
name: TaikoArcadeLoader
path: dist/
compression-level: 9

136
.gitignore vendored
View File

@ -1,4 +1,136 @@
# Build and Compiled folder
build/
# Vscode specific
.vscode
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
*.dll
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
CMakeUserPresets.json
# Leftovers from the old build system
xpacks/
compile_commands.json
package.json
@ -13,6 +145,4 @@ subprojects/stb
subprojects/zlib
subprojects/pugixml-1.14
libtomcrypt-1.18.2
dist.7z
.vscode
out/
dist.7z

234
CMakeLists.txt Normal file
View File

@ -0,0 +1,234 @@
cmake_minimum_required(VERSION 3.25)
project(TaikoArcadeLoader VERSION 1.0.0 LANGUAGES C CXX)
# Set C and C++ standards
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Set warning level
if(MSVC)
add_compile_options(/W3)
# Set the source file encoding to UTF-8
add_compile_options(/utf-8)
else()
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# Add project definitions
add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS)
# Include FetchContent module
include(FetchContent)
# Fetch tomlc99 (no built-in CMake support)
FetchContent_Declare(
tomlc99
GIT_REPOSITORY https://github.com/cktan/tomlc99.git
GIT_TAG master
)
FetchContent_GetProperties(tomlc99)
if(NOT tomlc99_POPULATED)
FetchContent_MakeAvailable(tomlc99)
add_library(tomlc99 STATIC ${tomlc99_SOURCE_DIR}/toml.c)
target_include_directories(tomlc99 PUBLIC ${tomlc99_SOURCE_DIR})
endif()
# Fetch stb (header-only library, no built-in CMake support)
FetchContent_Declare(
stb
GIT_REPOSITORY https://github.com/nothings/stb.git
GIT_TAG master
)
FetchContent_GetProperties(stb)
if(NOT stb_POPULATED)
FetchContent_MakeAvailable(stb)
add_library(stb INTERFACE)
target_include_directories(stb INTERFACE ${stb_SOURCE_DIR})
endif()
# Fetch zxing-cpp
FetchContent_Declare(
zxing_cpp
URL https://github.com/zxing-cpp/zxing-cpp/archive/refs/tags/v2.2.1.zip
)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(zxing_cpp)
# Fetch zlib
FetchContent_Declare(
zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf
)
FetchContent_MakeAvailable(zlib)
# Fetch libtomcrypt
FetchContent_Declare(
libtomcrypt
GIT_REPOSITORY https://github.com/libtom/libtomcrypt.git
GIT_TAG 124e020437715b0d2647ed12632fa10e2cfe9234 # v1.18.2 does not have cmake
)
set(BUILD_SHARED OFF CACHE BOOL "" FORCE)
set(WITH_LTM OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(libtomcrypt)
# Fetch pugixml
FetchContent_Declare(
pugixml
URL https://github.com/zeux/pugixml/archive/v1.14.tar.gz
)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(PUGIXML_WCHAR_MODE ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(pugixml)
# Fetch safetyhook
FetchContent_Declare(
safetyhook
GIT_REPOSITORY https://github.com/cursey/safetyhook.git
GIT_TAG v0.4.1
)
set(SAFETYHOOK_FETCH_ZYDIS ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(safetyhook)
# Fetch SDL2
FetchContent_Declare(
SDL2
URL https://github.com/libsdl-org/SDL/releases/download/release-2.26.5/SDL2-2.26.5.tar.gz
)
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
set(SDL_STATIC ON CACHE BOOL "" FORCE)
set(SDL_TEST OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(SDL2)
# Fetch xxHash
FetchContent_Declare(
xxhash
URL https://github.com/Cyan4973/xxHash/archive/v0.8.2.tar.gz
SOURCE_SUBDIR cmake_unofficial
)
set(XXH_BUILD_SHARED OFF CACHE BOOL "" FORCE)
set(XXH_BUILD_STATIC ON CACHE BOOL "" FORCE)
set(XXH_BUILD_XXHSUM OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(xxhash)
# Fetch Minhook
FetchContent_Declare(
minhook
GIT_REPOSITORY https://github.com/TsudaKageyu/minhook.git
GIT_TAG d862245d98fecd56dd7b1ca2f2e5185b75ecc780
)
FetchContent_MakeAvailable(minhook)
FetchContent_Declare(
magic_enum
GIT_REPOSITORY https://github.com/Neargye/magic_enum.git
GIT_TAG v0.9.7
)
FetchContent_MakeAvailable(magic_enum)
FetchContent_Declare(
plog
GIT_REPOSITORY https://github.com/SergiusTheBest/plog.git
GIT_TAG 1.1.10
)
FetchContent_MakeAvailable(plog)
# Source files
set(SOURCES
src/dllmain.cpp
src/helpers.cpp
src/logger.cpp
src/poll.cpp
src/bnusio.cpp
src/patches/amauth.cpp
src/patches/dxgi.cpp
src/patches/fpslimiter.cpp
src/patches/audio.cpp
src/patches/qr.cpp
src/patches/layeredfs.cpp
src/patches/testmode.cpp
src/patches/versions/JPN00.cpp
src/patches/versions/JPN08.cpp
src/patches/versions/JPN39.cpp
src/patches/versions/CHN00.cpp
)
# Create the library
add_library(bnusio SHARED ${SOURCES})
# Remove 'lib' prefix from the library name
set_target_properties(bnusio PROPERTIES PREFIX "")
# Include directories
target_include_directories(bnusio PRIVATE
src
${tomlc99_SOURCE_DIR}
${SDL2_SOURCE_DIR}/include
${xxhash_SOURCE_DIR}
${zlib_SOURCE_DIR}
${libtomcrypt_SOURCE_DIR}/src/headers
${minhook_SOURCE_DIR}/include
${magic_enum_SOURCE_DIR}
${plog_SOURCE_DIR}/include
)
# Compiler definitions
target_compile_definitions(bnusio PRIVATE
_WIN32_WINNT=_WIN32_WINNT_WIN10
)
# Link libraries
target_link_libraries(bnusio PRIVATE
tomlc99
SDL2-static
xxhash
zlibstatic
libtomcrypt
safetyhook
ZXing::ZXing
pugixml
stb
ws2_32
ntdll
minhook
magic_enum
plog
)
# Add link options
# if(MSVC)
# target_link_options(bnusio PRIVATE /FORCE:MULTIPLE)
# else()
# target_link_options(bnusio PRIVATE -Wl,--allow-multiple-definition)
# endif()
# Set runtime library to static
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
# Define the .def file
set(DEF_FILE "${CMAKE_CURRENT_SOURCE_DIR}/exports.def")
if (MSVC)
# Add the .def file to the target properties
set_target_properties(bnusio PROPERTIES LINK_FLAGS "/DEF:${DEF_FILE}")
endif()
# Set a default target
add_custom_target(default ALL DEPENDS bnusio)
## Copy the build output to the Out folder
set(OUT_DIR "${CMAKE_SOURCE_DIR}/dist")
set(DLL_SOURCE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/bnusio.dll")
add_custom_command(
TARGET bnusio POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${DLL_SOURCE_PATH}"
"${OUT_DIR}/bnusio.dll"
COMMENT "Copying bnusio.dll to dist directory"
)

View File

@ -1,26 +0,0 @@
default: dist-no-7z
all:
@meson compile -C build
@strip build/bnusio.dll
setup:
@meson setup build --cross cross-mingw-64.txt
clean-setup:
@meson setup --wipe build --cross cross-mingw-64.txt
clean:
@rm -rf out
@rm -rf build
@rm -f dist.7z
@cd subprojects && find . -maxdepth 1 ! -name packagefiles -type d -not -path '.' -exec rm -rf {} +
dist-no-7z: all
@mkdir -p out/
@cp build/bnusio.dll out/
@cp -r dist/* out/
dist: dist-no-7z
@cd out && 7z a -t7z ../dist.7z .
@rm -rf out

View File

@ -1,23 +1,31 @@
### Guide for making additional plugins
# Guide for making additional plugins
Plugins are just libraries with certain exported functions that go in the plugins folder.
```c++
void Init()
```
Runs on bngrw_Init, may be a bit late for some things but should generally allow functions which would cause loader locks to run fine if a bit late.
```c++
void Exit()
```
Runs on bnusio_Close, dispose of any data here.
```c++
void Update()
```
Runs once per frame.
```c++
void WaitTouch(i32 (*callback) (i32, i32, u8[168], u64), u64 data)
```
Runs on bngrw_reqWaitTouch. Call the callback like so when you wish to have a card scanned.
```c++
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 };
memcpy (cardData + 0x2C, chipId, 33);
@ -28,5 +36,6 @@ callback(0, 0, cardData, data);
```c++
void CardInsert()
```
Runs when user presses CARD_INSERT, causes TAL to not insert a card if any plugins have this present
void BeforeCardInsert()

View File

@ -111,22 +111,24 @@ Enhanced original option:
* Louder volume (Speaker Volume is now up to 300%, **WARNING: May damage your speakers**)
## Building
## Building Manually
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:
To compile TaikoArcadeLoader, you'll need to install [MSVC](https://aka.ms/vs/17/release/vs_BuildTools.exe).
Loading this project in cliON or vscode with the cmake tools addon should then allow you to build the project.
If you want to build yourself, here are some instructions on how to do this from a cmd shell.
Clone this repository, open *cmd* and run the following commands:
```bash
apt install -y npm mingw-w64 ninja-build nasm 7zip cmake python3-pip
pip3 install meson
# Load the MSVC environment (Change this to your actual vcvarsall.bat path)
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
npm install n -g && n latest && npm install --global xpm@latest
npx xpm init && npx xpm install @xpack-dev-tools/mingw-w64-gcc@latest
# Configure the build folder (this is only needed the first time)
cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
# make sure you're in the TaikoArcadeLoader folder before running this
export PATH=`pwd`/xpacks/.bin:$PATH
make clean-setup
# Build TaikoArcadeLoader
cmake --build build --config Release
```
Once that's done, run `make` to build TAL.
The output will be written in the `out` folder.
The compiled build of TaikoArcadeLoader will be written in the `dist` folder.

View File

@ -1,11 +0,0 @@
[binaries]
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

47
exports.def Normal file
View File

@ -0,0 +1,47 @@
LIBRARY "bnusio"
EXPORTS
bnusio_Open
bnusio_Close
bnusio_Communication
bnusio_IsConnected
bnusio_ResetIoBoard
bnusio_GetStatusU16
bnusio_GetStatusU8
bnusio_GetRegisterU16
bnusio_GetRegisterU8
bnusio_GetBuffer
bnusio_SetRegisterU16
bnusio_SetRegisterU8
bnusio_SetBuffer
bnusio_GetSystemError
bnusio_SetSystemError
bnusio_ClearSram
bnusio_GetExpansionMode
bnusio_SetExpansionMode
bnusio_IsWideUsio
bnusio_GetSwIn64
bnusio_GetGout
bnusio_SetGout
bnusio_GetEncoder
bnusio_GetCoinLock
bnusio_SetCoinLock
bnusio_GetCDOut
bnusio_SetCDOut
bnusio_GetHopOut
bnusio_SetHopOut
bnusio_SetPLCounter
bnusio_GetIoBoardName
bnusio_SetHopperRequest
bnusio_SetHopperLimit
bnusio_SramRead
bnusio_SramWrite
bnusio_GetCoinError
bnusio_GetServiceError
bnusio_DecCoin
bnusio_DecService
bnusio_ResetCoin
bnusio_GetFirmwareVersion
bnusio_GetSwIn
bnusio_GetAnalogIn
bnusio_GetCoin
bnusio_GetService

View File

@ -1,101 +0,0 @@
project('TaikoArcadeLoader', 'c', 'cpp', version: '1.0.0', default_options : ['c_std=c11', 'cpp_std=c++23'])
warning_level = 3
debug = true
optimization = 3
b_lto = true
b_pgo = 'use'
cmake = import('cmake')
opt_var = cmake.subproject_options()
opt_var.set_override_option('cpp_std', 'c++23')
cpp = meson.get_compiler('cpp')
add_project_arguments(
cpp.get_supported_arguments(
'-D_WIN32_WINNT=_WIN32_WINNT_WIN10',
),
language: 'cpp',
)
add_project_link_arguments(
cpp.get_supported_arguments(
'-static',
#'-s',
'-lws2_32',
'-lssp',
'-lntdll',
),
language: 'cpp',
)
minhook = subproject('minhook')
tomlc99 = subproject('tomlc99')
sdl2 = subproject('sdl2', default_options: ['default_library=static', 'test=false', 'use_render=disabled'])
xxhash = subproject('xxhash', default_options: ['default_library=static', 'cli=false'])
opt_var.add_cmake_defines({'SAFETYHOOK_FETCH_ZYDIS': true})
safetyhook_proj = cmake.subproject('safetyhook', options: opt_var)
safetyhook_dep = safetyhook_proj.dependency('safetyhook')
zydis_dep = safetyhook_proj.dependency('Zydis')
stb = subproject('stb')
opt_var.add_cmake_defines({'BUILD_EXAMPLES': false})
zxing_proj = cmake.subproject('zxing', options: opt_var)
zxing_dep = zxing_proj.dependency('ZXing')
zlib_proj = subproject('zlib')
zlib_dep = zlib_proj.get_variable('zlib_dep')
libtomcrypt = subproject('libtomcrypt')
libtomcrypt_dep = libtomcrypt.get_variable('tomcrypt_dep')
opt_var = cmake.subproject_options()
opt_var.set_override_option('cpp_std', 'c++23')
opt_var.add_cmake_defines({'PUGIXML_WCHAR_MODE': true})
pugixml = cmake.subproject('pugixml', options: opt_var)
pugixml_dep = pugixml.get_variable('pugixml_static_dep')
library(
'bnusio',
link_with: [
minhook.get_variable('minhook_lib'),
tomlc99.get_variable('tomlc99_lib'),
sdl2.get_variable('sdl2'),
xxhash.get_variable('xxhash'),
zlib_proj.get_variable('zlib_lib'),
libtomcrypt.get_variable('tomcryptlib'),
],
link_args : '-Wl,--allow-multiple-definition',
include_directories: [
'src',
minhook.get_variable('minhook_inc'),
tomlc99.get_variable('tomlc99_inc'),
sdl2.get_variable('core_inc'),
xxhash.get_variable('inc'),
zlib_proj.get_variable('zlib_inc'),
libtomcrypt.get_variable('core_inc'),
],
dependencies: [
stb.get_variable('stb_dep'),
zxing_dep,
safetyhook_dep,
zydis_dep,
zlib_dep,
libtomcrypt_dep,
pugixml_dep,
],
sources : [
'src/dllmain.cpp',
'src/helpers.cpp',
'src/logger.cpp',
'src/poll.cpp',
'src/bnusio.cpp',
'src/patches/amauth.cpp',
'src/patches/dxgi.cpp',
'src/patches/fpslimiter.cpp',
'src/patches/audio.cpp',
'src/patches/qr.cpp',
'src/patches/layeredfs.cpp',
'src/patches/testmode.cpp',
'src/patches/versions/JPN00.cpp',
'src/patches/versions/JPN08.cpp',
'src/patches/versions/JPN39.cpp',
'src/patches/versions/CHN00.cpp',
],
name_prefix: ''
)

View File

@ -1,3 +1,4 @@
#include <queue>
#include "constants.h"
#include "helpers.h"
#include "patches/patches.h"
@ -106,11 +107,11 @@ bnusio_GetFirmwareVersion () {
u32
bnusio_GetSwIn () {
u32 sw = 0;
sw |= (u32)testEnabled << 7;
sw |= (u32)IsButtonDown (DEBUG_ENTER) << 9;
sw |= (u32)IsButtonDown (DEBUG_DOWN) << 12;
sw |= (u32)IsButtonDown (DEBUG_UP) << 13;
sw |= (u32)IsButtonDown (SERVICE) << 14;
sw |= static_cast<u32> (testEnabled) << 7;
sw |= static_cast<u32> (IsButtonDown (DEBUG_ENTER)) << 9;
sw |= static_cast<u32> (IsButtonDown (DEBUG_DOWN)) << 12;
sw |= static_cast<u32> (IsButtonDown (DEBUG_UP)) << 13;
sw |= static_cast<u32> (IsButtonDown (SERVICE)) << 14;
return sw;
}
@ -132,20 +133,17 @@ SDLAxis analogBindings[] = {
};
u16
bnusio_GetAnalogIn (u8 which) {
u16 analogValue;
bnusio_GetAnalogIn (const u8 which) {
if (analogInput) {
analogValue = (u16)(32768 * ControllerAxisIsDown (analogBindings[which]));
if (analogValue > 100) return analogValue;
if (const u16 analogValue = static_cast<u16> (32768 * ControllerAxisIsDown (analogBindings[which])); analogValue > 100) return analogValue;
return 0;
}
auto button = analogButtons[which];
const auto button = analogButtons[which];
if (which == 0) {
if (buttonWaitPeriodP1 > 0) buttonWaitPeriodP1--;
if (buttonWaitPeriodP2 > 0) buttonWaitPeriodP2--;
}
bool isP1 = which / 4 == 0;
if ((isP1 && !buttonQueueP1.empty ()) || (!isP1 && !buttonQueueP2.empty ())) {
if (const bool isP1 = which / 4 == 0; (isP1 && !buttonQueueP1.empty ()) || (!isP1 && !buttonQueueP2.empty ())) {
if ((isP1 && buttonQueueP1.front () == which && buttonWaitPeriodP1 == 0)
|| (!isP1 && buttonQueueP2.front () == which && buttonWaitPeriodP2 == 0)) {
if (isP1) {
@ -156,7 +154,7 @@ bnusio_GetAnalogIn (u8 which) {
buttonWaitPeriodP2 = drumWaitPeriod;
}
u16 hitValue = !valueStates[which] ? 50 : 51;
const u16 hitValue = !valueStates[which] ? 50 : 51;
valueStates[which] = !valueStates[which];
return (hitValue << 15) / 100 + 1;
}
@ -176,7 +174,7 @@ bnusio_GetAnalogIn (u8 which) {
if (isP1) buttonWaitPeriodP1 = drumWaitPeriod;
else buttonWaitPeriodP2 = drumWaitPeriod;
u16 hitValue = !valueStates[which] ? 50 : 51;
const u16 hitValue = !valueStates[which] ? 50 : 51;
valueStates[which] = !valueStates[which];
return (hitValue << 15) / 100 + 1;
} else {
@ -189,16 +187,16 @@ u16 __fastcall bnusio_GetService (i32 a1) { return service_count; }
}
void
InspectWaitTouch (i32 a1, i32 a2, u8 _cardData[168], u64 _touchData) {
InspectWaitTouch (const i32 a1, const i32 a2, u8 _cardData[168], const u64 _touchData) {
if (AreAllBytesZero (_cardData, 0x00, 168)) // This happens when you enter test mode.
return touchCallback (a1, a2, _cardData, _touchData);
bool valid = !AreAllBytesZero (_cardData, 0x50, 21);
const bool valid = !AreAllBytesZero (_cardData, 0x50, 21);
if (valid) {
LogMessage (LOG_LEVEL_DEBUG, "Card is valid");
LogMessage (LogLevel::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");
LogMessage (LogLevel::DEBUG, "Card is usually not supported");
}
std::ostringstream oss;
@ -207,7 +205,7 @@ InspectWaitTouch (i32 a1, i32 a2, u8 _cardData[168], u64 _touchData) {
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 ());
LogMessage (LogLevel::DEBUG, "A1: %d, A2: %d, Card data: \n%s", a1, a2, oss.str ().c_str ());
if (touchCallback) return valid ? touchCallback (a1, a2, _cardData, _touchData) : touchCallback (0, 0, _cardData, _touchData);
}
@ -278,76 +276,73 @@ HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { re
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, callbackAttach callback, i32 *_attachData) {
LogMessage (LOG_LEVEL_DEBUG, "BngRwAttach");
LogMessage (LogLevel::DEBUG, "BngRwAttach");
// This is way too fucking jank
attachCallback = callback;
attachData = _attachData;
return 1;
}
HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, callbackTouch _callback, u64 _touchData) {
LogMessage (LOG_LEVEL_DEBUG, "BngRwReqWaitTouch");
LogMessage (LogLevel::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);
}
for (const auto plugin : plugins)
if (const FARPROC touchEvent = GetProcAddress (plugin, "WaitTouch"))
reinterpret_cast<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 (a1, a2, a3, InspectWaitTouch, _touchData);
}
// This is called when we use an original card reader and acceptInvalidCards is set to true
return originalbngrw_ReqWaitTouch (a1, a2, a3, InspectWaitTouch, _touchData);
}
void
Init () {
SetKeyboardButtons ();
auto configPath = std::filesystem::current_path () / "config.toml";
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
toml_table_t *config = config_ptr.get ();
auto controller = openConfigSection (config, "controller");
if (controller) {
drumWaitPeriod = readConfigInt (controller, "wait_period", drumWaitPeriod);
const toml_table_t *config = config_ptr.get ();
if (const auto controller = openConfigSection (config, "controller")) {
drumWaitPeriod = (u16)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.");
if (analogInput) LogMessage (LogLevel::WARN, "Using analog input mode. All the keyboard drum inputs have been disabled.");
}
}
auto keyconfigPath = std::filesystem::current_path () / "keyconfig.toml";
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> keyconfig_ptr (openConfig (keyconfigPath), toml_free);
if (keyconfig_ptr) {
toml_table_t *keyconfig = keyconfig_ptr.get ();
SetConfigValue (keyconfig, "EXIT", &EXIT);
const auto keyConfigPath = std::filesystem::current_path () / "keyconfig.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> keyConfig_ptr (openConfig (keyConfigPath), toml_free);
if (keyConfig_ptr) {
const toml_table_t *keyConfig = keyConfig_ptr.get ();
SetConfigValue (keyConfig, "EXIT", &EXIT);
SetConfigValue (keyconfig, "TEST", &TEST);
SetConfigValue (keyconfig, "SERVICE", &SERVICE);
SetConfigValue (keyconfig, "DEBUG_UP", &DEBUG_UP);
SetConfigValue (keyconfig, "DEBUG_DOWN", &DEBUG_DOWN);
SetConfigValue (keyconfig, "DEBUG_ENTER", &DEBUG_ENTER);
SetConfigValue (keyConfig, "TEST", &TEST);
SetConfigValue (keyConfig, "SERVICE", &SERVICE);
SetConfigValue (keyConfig, "DEBUG_UP", &DEBUG_UP);
SetConfigValue (keyConfig, "DEBUG_DOWN", &DEBUG_DOWN);
SetConfigValue (keyConfig, "DEBUG_ENTER", &DEBUG_ENTER);
SetConfigValue (keyconfig, "COIN_ADD", &COIN_ADD);
SetConfigValue (keyconfig, "CARD_INSERT_1", &CARD_INSERT_1);
SetConfigValue (keyconfig, "CARD_INSERT_2", &CARD_INSERT_2);
SetConfigValue (keyconfig, "QR_DATA_READ", &QR_DATA_READ);
SetConfigValue (keyconfig, "QR_IMAGE_READ", &QR_IMAGE_READ);
SetConfigValue (keyConfig, "COIN_ADD", &COIN_ADD);
SetConfigValue (keyConfig, "CARD_INSERT_1", &CARD_INSERT_1);
SetConfigValue (keyConfig, "CARD_INSERT_2", &CARD_INSERT_2);
SetConfigValue (keyConfig, "QR_DATA_READ", &QR_DATA_READ);
SetConfigValue (keyConfig, "QR_IMAGE_READ", &QR_IMAGE_READ);
SetConfigValue (keyconfig, "P1_LEFT_BLUE", &P1_LEFT_BLUE);
SetConfigValue (keyconfig, "P1_LEFT_RED", &P1_LEFT_RED);
SetConfigValue (keyconfig, "P1_RIGHT_RED", &P1_RIGHT_RED);
SetConfigValue (keyconfig, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE);
SetConfigValue (keyconfig, "P2_LEFT_BLUE", &P2_LEFT_BLUE);
SetConfigValue (keyconfig, "P2_LEFT_RED", &P2_LEFT_RED);
SetConfigValue (keyconfig, "P2_RIGHT_RED", &P2_RIGHT_RED);
SetConfigValue (keyconfig, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE);
SetConfigValue (keyConfig, "P1_LEFT_BLUE", &P1_LEFT_BLUE);
SetConfigValue (keyConfig, "P1_LEFT_RED", &P1_LEFT_RED);
SetConfigValue (keyConfig, "P1_RIGHT_RED", &P1_RIGHT_RED);
SetConfigValue (keyConfig, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE);
SetConfigValue (keyConfig, "P2_LEFT_BLUE", &P2_LEFT_BLUE);
SetConfigValue (keyConfig, "P2_LEFT_RED", &P2_LEFT_RED);
SetConfigValue (keyConfig, "P2_RIGHT_RED", &P2_RIGHT_RED);
SetConfigValue (keyConfig, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE);
}
if (!emulateUsio && !std::filesystem::exists (std::filesystem::current_path () / "bnusio_original.dll")) {
emulateUsio = true;
LogMessage (LOG_LEVEL_ERROR, "bnusio_original.dll not found! usio emulation enabled");
LogMessage (LogLevel::ERROR, "bnusio_original.dll not found! usio emulation enabled");
}
if (!emulateUsio) {
@ -397,7 +392,7 @@ Init () {
INSTALL_HOOK_DIRECT (bnusio_DecService, bnusio_DecService_Original);
INSTALL_HOOK_DIRECT (bnusio_ResetCoin, bnusio_ResetCoin_Original);
LogMessage (LOG_LEVEL_WARN, "USIO emulation disabled");
LogMessage (LogLevel::WARN, "USIO emulation disabled");
}
if (emulateCardReader) {
@ -423,9 +418,9 @@ Init () {
INSTALL_HOOK (bngrw_Attach);
INSTALL_HOOK (bngrw_DevReset);
} else {
LogMessage (LOG_LEVEL_WARN, "Card reader emulation disabled");
LogMessage (LogLevel::WARN, "Card reader emulation disabled");
if (acceptInvalidCards) {
LogMessage (LOG_LEVEL_WARN, "Original reader will accept invalid cards!");
LogMessage (LogLevel::WARN, "Original reader will accept invalid cards!");
INSTALL_HOOK (bngrw_ReqWaitTouch);
}
}
@ -437,15 +432,13 @@ Update () {
windowHandle = FindWindowA ("nuFoundation.Window", nullptr);
InitializePoll (windowHandle);
if (autoIme) {
currentLayout = GetKeyboardLayout (0);
auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE);
currentLayout = GetKeyboardLayout (0);
const auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE);
ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS);
}
for (auto plugin : plugins) {
auto initEvent = GetProcAddress (plugin, "Init");
if (initEvent) initEvent ();
}
for (const auto plugin : plugins)
if (const auto initEvent = GetProcAddress (plugin, "Init")) initEvent ();
inited = true;
}
@ -456,9 +449,9 @@ Update () {
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
if (IsButtonTapped (EXIT)) ExitProcess (0);
if (waitingForTouch) {
bool hasInserted = false;
if (IsButtonTapped (CARD_INSERT_1) || IsButtonTapped (CARD_INSERT_2)) {
bool p1 = IsButtonTapped (CARD_INSERT_1);
bool hasInserted = false;
const 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,
@ -469,12 +462,12 @@ Update () {
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) {
for (const auto plugin : plugins) {
FARPROC insertEvent = GetProcAddress (plugin, p1 ? "BeforeCard1Insert" : "BeforeCard2Insert");
if (insertEvent) ((event *)insertEvent) ();
if (insertEvent) reinterpret_cast<event *> (insertEvent) ();
insertEvent = GetProcAddress (plugin, p1 ? "Card1Insert" : "Card2Insert");
if (insertEvent) {
((event *)insertEvent) ();
reinterpret_cast<event *> (insertEvent) ();
hasInserted = true;
waitingForTouch = false;
break;
@ -482,7 +475,7 @@ Update () {
}
if (!hasInserted) {
LogMessage (LOG_LEVEL_INFO, "Inserting card for player %d: %s", p1 ? 1 : 2, p1 ? accessCode1 : accessCode2);
LogMessage (LogLevel::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);
@ -491,10 +484,8 @@ Update () {
}
}
for (auto plugin : plugins) {
auto updateEvent = GetProcAddress (plugin, "Update");
if (updateEvent) updateEvent ();
}
for (const auto plugin : plugins)
if (const auto updateEvent = GetProcAddress (plugin, "Update")) updateEvent ();
patches::Qr::Update ();
@ -504,10 +495,8 @@ Update () {
void
Close () {
if (autoIme) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS);
for (auto plugin : plugins) {
FARPROC exitEvent = GetProcAddress (plugin, "Exit");
if (exitEvent) ((event *)exitEvent) ();
}
for (const auto plugin : plugins)
if (const FARPROC exitEvent = GetProcAddress (plugin, "Exit")) reinterpret_cast<event *> (exitEvent) ();
CleanupLogger ();
}

View File

@ -1,3 +1,4 @@
#pragma once
namespace bnusio {
void Init ();
void Update ();

View File

@ -5,7 +5,7 @@
#include "poll.h"
#include "logger.h"
GameVersion gameVersion = GameVersion::UNKNOWN;
auto gameVersion = GameVersion::UNKNOWN;
std::vector<HMODULE> plugins;
u64 song_data_size = 1024 * 1024 * 64;
void *song_data;
@ -25,7 +25,6 @@ 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;
@ -39,7 +38,7 @@ HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return
HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) { ExitProcess (0); }
HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
i32 X, i32 Y, i32 nWidth, i32 nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) {
if (lpWindowName != NULL) {
if (lpWindowName != nullptr) {
if (wcscmp (lpWindowName, L"Taiko") == 0) {
if (windowed) dwStyle = WS_TILEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME;
@ -88,7 +87,7 @@ void
GetGameVersion () {
wchar_t w_path[MAX_PATH];
GetModuleFileNameW (nullptr, w_path, MAX_PATH);
std::filesystem::path path (w_path);
const std::filesystem::path path (w_path);
if (!std::filesystem::exists (path) || !path.has_filename ()) {
MessageBoxA (nullptr, "Failed to find executable", nullptr, MB_OK);
@ -102,13 +101,13 @@ GetGameVersion () {
}
stream.seekg (0, std::ifstream::end);
size_t length = stream.tellg ();
const size_t length = stream.tellg ();
stream.seekg (0, std::ifstream::beg);
char *buf = (char *)calloc (length + 1, sizeof (char));
const auto buf = static_cast<char *> (calloc (length + 1, sizeof (char)));
stream.read (buf, length);
gameVersion = (GameVersion)XXH64 (buf, length, 0);
gameVersion = static_cast<GameVersion> (XXH64 (buf, length, 0));
stream.close ();
free (buf);
@ -124,44 +123,43 @@ 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));
LogMessage (LogLevel::INFO, "Creating card.ini");
constexpr char hexCharacterTable[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char buf[64] = {0};
srand ((unsigned int)time (nullptr));
std::generate (buf, buf + 20, [&] () { return hexCharacterTable[rand () % 10]; });
std::generate_n (buf, 20, [&] () { return hexCharacterTable[rand () % 10]; });
WritePrivateProfileStringA ("card", "accessCode1", buf, ".\\card.ini");
std::generate (buf, buf + 32, [&] () { return hexCharacterTable[rand () % 16]; });
std::generate_n (buf, 32, [&] () { return hexCharacterTable[rand () % 16]; });
WritePrivateProfileStringA ("card", "chipId1", buf, ".\\card.ini");
std::generate (buf, buf + 20, [&] () { return hexCharacterTable[rand () % 10]; });
std::generate_n (buf, 20, [&] () { return hexCharacterTable[rand () % 10]; });
WritePrivateProfileStringA ("card", "accessCode2", buf, ".\\card.ini");
std::generate (buf, buf + 32, [&] () { return hexCharacterTable[rand () % 16]; });
std::generate_n (buf, 32, [&] () { return hexCharacterTable[rand () % 16]; });
WritePrivateProfileStringA ("card", "chipId2", buf, ".\\card.ini");
}
BOOL
DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
// This is bad, dont do this
// I/O in DllMain can easily cause a deadlock
// Init logger for loading config
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
LogMessage (LOG_LEVEL_INFO, "Loading config...");
LogMessage (LogLevel::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);
std::string version = "auto";
const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
toml_table_t *config = config_ptr.get ();
auto amauth = openConfigSection (config, "amauth");
if (amauth) {
server = readConfigString (amauth, "server", server);
port = readConfigString (amauth, "port", port);
chassisId = readConfigString (amauth, "chassis_id", chassisId);
shopId = readConfigString (amauth, "shop_id", shopId);
gameVerNum = readConfigString (amauth, "game_ver", gameVerNum);
countryCode = readConfigString (amauth, "country_code", countryCode);
const toml_table_t *config = config_ptr.get ();
if (const auto amauthConfig = openConfigSection (config, "amauth")) {
server = readConfigString (amauthConfig, "server", server);
port = readConfigString (amauthConfig, "port", port);
chassisId = readConfigString (amauthConfig, "chassis_id", chassisId);
shopId = readConfigString (amauthConfig, "shop_id", shopId);
gameVerNum = readConfigString (amauthConfig, "game_ver", gameVerNum);
countryCode = readConfigString (amauthConfig, "country_code", countryCode);
std::strcat (fullAddress, server.c_str ());
if (port != "") {
@ -172,25 +170,20 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
std::strcat (placeId, countryCode.c_str ());
std::strcat (placeId, "0FF0");
}
auto patches = openConfigSection (config, "patches");
if (patches) version = readConfigString (patches, "version", version);
auto emulation = openConfigSection (config, "emulation");
if (emulation) {
if (const auto patches = openConfigSection (config, "patches")) version = readConfigString (patches, "version", version);
if (const auto emulation = openConfigSection (config, "emulation")) {
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);
auto keyboard = openConfigSection (config, "keyboard");
if (keyboard) {
if (const auto graphics = openConfigSection (config, "graphics")) windowed = readConfigBool (graphics, "windowed", windowed);
if (const auto keyboard = openConfigSection (config, "keyboard")) {
autoIme = readConfigBool (keyboard, "auto_ime", autoIme);
jpLayout = readConfigBool (keyboard, "jp_layout", jpLayout);
}
auto logging = openConfigSection (config, "logging");
if (logging) {
if (const auto logging = openConfigSection (config, "logging")) {
logLevelStr = readConfigString (logging, "log_level", logLevelStr);
logToFile = readConfigBool (logging, "log_to_file", logToFile);
}
@ -198,7 +191,7 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
// Update the logger with the level read from config file.
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
LogMessage (LOG_LEVEL_INFO, "Application started.");
LogMessage (LogLevel::INFO, "Application started.");
if (version == "auto") {
GetGameVersion ();
@ -211,25 +204,22 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
} else if (version == "CHN00") {
gameVersion = GameVersion::CHN00;
} else {
LogMessage (LOG_LEVEL_ERROR, "GameVersion is UNKNOWN!");
LogMessage (LogLevel::ERROR, "GameVersion is UNKNOWN!");
MessageBoxA (nullptr, "Unknown patch version", nullptr, MB_OK);
ExitProcess (0);
}
LogMessage (LOG_LEVEL_INFO, "GameVersion is %s", GameVersionToString (gameVersion));
LogMessage (LogLevel::INFO, "GameVersion is %s", GameVersionToString (gameVersion));
auto pluginPath = std::filesystem::current_path () / "plugins";
if (std::filesystem::exists (pluginPath)) {
if (const auto pluginPath = std::filesystem::current_path () / "plugins"; std::filesystem::exists (pluginPath)) {
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) {
LogMessage (LOG_LEVEL_ERROR, L"Failed to load plugin " + shortName);
auto name = entry.path ().wstring ();
auto shortName = entry.path ().filename ().wstring ();
if (HMODULE hModule = LoadLibraryW (name.c_str ()); !hModule) {
LogMessage (LogLevel::ERROR, L"Failed to load plugin " + shortName);
} else {
plugins.push_back (hModule);
LogMessage (LOG_LEVEL_INFO, L"Loaded plugin " + shortName);
LogMessage (LogLevel::INFO, L"Loaded plugin " + shortName);
}
}
}
@ -241,7 +231,7 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
GetPrivateProfileStringA ("card", "accessCode2", accessCode2, accessCode2, 21, ".\\card.ini");
GetPrivateProfileStringA ("card", "chipId2", chipId2, chipId2, 33, ".\\card.ini");
LogMessage (LOG_LEVEL_WARN, "Loading patches, please wait...");
LogMessage (LogLevel::WARN, "Loading patches, please wait...");
INSTALL_HOOK (ShowMouse);
INSTALL_HOOK (ExitWindows);

View File

@ -1,114 +1,114 @@
#include <codecvt>
#include "helpers.h"
#include <windows.h>
static void
toml_myfree (void *p) {
if (p) {
char *pp = (char *)p;
const char *pp = static_cast<char *> (p);
delete[] pp;
}
}
toml_table_t *
openConfig (std::filesystem::path path) {
if (!std::filesystem::exists (path) || !path.has_filename ()) {
LogMessage (LOG_LEVEL_WARN, (std::string (path.string ()) + ": file does not exist").c_str ());
return 0;
openConfig (const std::filesystem::path &path) {
if (!exists (path) || !path.has_filename ()) {
LogMessage (LogLevel::WARN, std::string (path.string ()) + ": file does not exist");
return nullptr;
}
std::ifstream stream (path);
if (!stream.is_open ()) {
LogMessage (LOG_LEVEL_WARN, ("Could not open " + std::string (path.string ())).c_str ());
return 0;
LogMessage (LogLevel::WARN, ("Could not open " + std::string (path.string ())).c_str ());
return nullptr;
}
stream.seekg (0, stream.end);
size_t length = stream.tellg ();
const size_t length = stream.tellg ();
stream.seekg (0, stream.beg);
char *buf = (char *)calloc (length + 1, sizeof (char));
const auto buf = static_cast<char *> (calloc (length + 1, sizeof (char)));
stream.read (buf, length);
char errorbuf[200];
toml_table_t *config = toml_parse (buf, errorbuf, 200);
char errorBuffer[200];
toml_table_t *config = toml_parse (buf, errorBuffer, 200);
stream.close ();
free (buf);
if (!config) {
LogMessage (LOG_LEVEL_WARN, (path.string () + ": " + errorbuf).c_str ());
return 0;
LogMessage (LogLevel::WARN, (path.string () + ": " + errorBuffer).c_str ());
return nullptr;
}
return config;
}
toml_table_t *
openConfigSection (toml_table_t *config, const std::string &sectionName) {
openConfigSection (const toml_table_t *config, const std::string &sectionName) {
toml_table_t *section = toml_table_in (config, sectionName.c_str ());
if (!section) {
LogMessage (LOG_LEVEL_ERROR, ("Cannot find section " + sectionName).c_str ());
return 0;
LogMessage (LogLevel::ERROR, ("Cannot find section " + sectionName).c_str ());
return nullptr;
}
return section;
}
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) {
LogMessage (LOG_LEVEL_WARN, ("Could not find Boolean named " + key).c_str ());
readConfigBool (const toml_table_t *table, const std::string &key, const bool notFoundValue) {
const auto [ok, u] = toml_bool_in (table, key.c_str ());
if (!ok) {
LogMessage (LogLevel::WARN, ("Could not find Boolean named " + key).c_str ());
return notFoundValue;
}
return (bool)data.u.b;
return static_cast<bool> (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) {
LogMessage (LOG_LEVEL_WARN, ("Could not find Int named " + key).c_str ());
i64
readConfigInt (const toml_table_t *table, const std::string &key, const i64 notFoundValue) {
const auto [ok, u] = toml_int_in (table, key.c_str ());
if (!ok) {
LogMessage (LogLevel::WARN, ("Could not find Int named " + key).c_str ());
return notFoundValue;
}
return data.u.i;
return u.i;
}
const std::string
readConfigString (toml_table_t *table, const std::string &key, const std::string &notFoundValue) {
toml_datum_t data = toml_string_in (table, key.c_str ());
if (!data.ok) {
LogMessage (LOG_LEVEL_WARN, ("Could not find String named " + key).c_str ());
std::string
readConfigString (const toml_table_t *table, const std::string &key, const std::string &notFoundValue) {
const auto [ok, u] = toml_string_in (table, key.c_str ());
if (!ok) {
LogMessage (LogLevel::WARN, ("Could not find String named " + key).c_str ());
return notFoundValue;
}
std::string str = data.u.s;
toml_myfree (data.u.s);
std::string str = u.s;
toml_myfree (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 ());
std::vector<i64>
readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector<i64> notFoundValue) {
const toml_array_t *array = toml_array_in (table, key.c_str ());
if (!array) {
LogMessage (LOG_LEVEL_WARN, ("Could not find int Array named " + key).c_str ());
LogMessage (LogLevel::WARN, ("Could not find int Array named " + key).c_str ());
return notFoundValue;
}
std::vector<int64_t> datas;
std::vector<i64> ret;
for (int i = 0;; i++) {
toml_datum_t data = toml_int_at (array, i);
if (!data.ok) break;
datas.push_back (data.u.i);
auto [ok, u] = toml_int_at (array, i);
if (!ok) break;
ret.push_back (u.i);
}
return datas;
return ret;
}
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 ();
replace (const std::wstring &orignStr, const std::wstring &oldStr, const std::wstring &newStr) {
size_t pos = 0;
std::wstring tempStr = orignStr;
const std::wstring::size_type newStrLen = newStr.length ();
const std::wstring::size_type oldStrLen = oldStr.length ();
while (true) {
pos = tempStr.find (oldStr, pos);
if (pos == std::wstring::npos) break;
@ -121,11 +121,11 @@ 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 ();
replace (const std::string &orignStr, const std::string &oldStr, const std::string &newStr) {
size_t pos = 0;
std::string tempStr = orignStr;
const std::string::size_type newStrLen = newStr.length ();
const std::string::size_type oldStrLen = oldStr.length ();
while (true) {
pos = tempStr.find (oldStr, pos);
if (pos == std::string::npos) break;
@ -138,7 +138,7 @@ replace (const std::string orignStr, const std::string oldStr, const std::string
}
const char *
GameVersionToString (GameVersion version) {
GameVersionToString (const GameVersion version) {
switch (version) {
case GameVersion::JPN00: return "JPN00";
case GameVersion::JPN08: return "JPN08";
@ -149,7 +149,7 @@ GameVersionToString (GameVersion version) {
}
const char *
languageStr (int language) {
languageStr (const int language) {
switch (language) {
case 1: return "en_us";
case 2: return "cn_tw";
@ -161,12 +161,24 @@ languageStr (int language) {
std::string
ConvertWideToUtf8 (const std::wstring &wstr) {
std::wstring_convert<std::codecvt_utf8<wchar_t> > converter;
return converter.to_bytes (wstr);
if (wstr.empty ()) return {};
// Determine the size of the resulting UTF-8 string
const int utf8Size = WideCharToMultiByte (CP_UTF8, 0, wstr.c_str (), -1, nullptr, 0, nullptr, nullptr);
if (utf8Size <= 0) {
LogMessage (LogLevel::ERROR, "Failed to convert wide string to UTF-8");
return {};
}
// Allocate buffer and perform the conversion
std::string utf8Str (utf8Size, '\0'); // -1 to exclude null terminator
WideCharToMultiByte (CP_UTF8, 0, wstr.c_str (), -1, data (utf8Str), utf8Size, nullptr, nullptr);
return utf8Str;
}
bool
AreAllBytesZero (const uint8_t *array, size_t offset, size_t length) {
AreAllBytesZero (const u8 *array, const size_t offset, const size_t length) {
for (size_t i = 0; i < length; ++i)
if (array[offset + i] != 0x00) return false;
return true;

View File

@ -1,16 +1,20 @@
#pragma once
#include <windows.h>
#include <bits/stdc++.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <map>
#include <mutex>
#include <iostream>
#include <fstream>
#include <string>
#include <safetyhook.hpp>
#include <MinHook.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <toml.h>
#include <windows.h>
// ReSharper disable once CppUnusedIncludeDirective
#include <MinHook.h>
#include "constants.h"
#include "logger.h"
@ -39,20 +43,20 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
#define HOOK(returnType, functionName, location, ...) \
typedef returnType (*functionName) (__VA_ARGS__); \
functionName original##functionName = NULL; \
functionName original##functionName = nullptr; \
void *where##functionName = (void *)(location); \
returnType implOf##functionName (__VA_ARGS__)
#define HOOK_DYNAMIC(returnType, functionName, ...) \
typedef returnType (*functionName) (__VA_ARGS__); \
functionName original##functionName = NULL; \
void *where##functionName = NULL; \
functionName original##functionName = nullptr; \
void *where##functionName = nullptr; \
returnType implOf##functionName (__VA_ARGS__)
#define VTABLE_HOOK(returnType, className, functionName, ...) \
typedef returnType (*className##functionName) (className * This, __VA_ARGS__); \
className##functionName original##className##functionName = NULL; \
void *where##className##functionName = NULL; \
className##functionName original##className##functionName = nullptr; \
void *where##className##functionName = nullptr; \
returnType implOf##className##functionName (className *This, __VA_ARGS__)
#define MID_HOOK(functionName, location, ...) \
@ -68,7 +72,7 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
#define INSTALL_HOOK(functionName) \
{ \
LogMessage (LOG_LEVEL_DEBUG, (std::string ("Installing hook for ") + #functionName).c_str ()); \
LogMessage (LogLevel::DEBUG, std::string ("Installing hook for ") + #functionName); \
MH_Initialize (); \
MH_CreateHook ((void *)where##functionName, (void *)implOf##functionName, (void **)(&original##functionName)); \
MH_EnableHook ((void *)where##functionName); \
@ -80,12 +84,12 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
INSTALL_HOOK (functionName); \
}
#define INSTALL_HOOK_DIRECT(location, locationOfHook) \
{ \
LogMessage (LOG_LEVEL_DEBUG, (std::string ("Installing direct hook for ") + #location).c_str ()); \
MH_Initialize (); \
MH_CreateHook ((void *)(location), (void *)(locationOfHook), NULL); \
MH_EnableHook ((void *)(location)); \
#define INSTALL_HOOK_DIRECT(location, locationOfHook) \
{ \
LogMessage (LogLevel::DEBUG, std::string ("Installing direct hook for ") + #location); \
MH_Initialize (); \
MH_CreateHook ((void *)(location), (void *)(locationOfHook), NULL); \
MH_EnableHook ((void *)(location)); \
}
#define INSTALL_VTABLE_HOOK(className, object, functionName, functionIndex) \
@ -94,16 +98,16 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
INSTALL_HOOK (className##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(functionName) \
{ \
LogMessage (LogLevel::DEBUG, std::string ("Installing mid hook for ") + #functionName); \
midHook##functionName = safetyhook::create_mid (where##functionName, implOf##functionName); \
}
#define INSTALL_MID_HOOK_DYNAMIC(functionName, location) \
{ mapOf##functionName[location] = safetyhook::create_mid (location, implOf##functionName); }
bool sendFlag = false;
inline 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) { \
@ -171,7 +175,7 @@ bool sendFlag = false;
DWORD oldProtect; \
VirtualProtect ((void *)(location), (size_t)(count), PAGE_EXECUTE_READWRITE, &oldProtect); \
for (size_t i = 0; i < (size_t)(count); i++) \
*((uint8_t *)(location) + i) = 0x90; \
*((u8 *)(location) + i) = 0x90; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
}
@ -180,22 +184,21 @@ bool sendFlag = false;
DWORD oldProtect; \
VirtualProtect ((void *)(location), (size_t)(count), PAGE_EXECUTE_READWRITE, &oldProtect); \
for (size_t i = 0; i < (size_t)(count); i++) \
*((uint8_t *)(location) + i) = 0x00; \
*((u8 *)(location) + i) = 0x00; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
}
#define COUNTOFARR(arr) sizeof (arr) / sizeof (arr[0])
#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 &sectionName);
bool readConfigBool (toml_table_t *table, const std::string &key, bool notFoundValue);
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 &notFoundValue);
std::vector<int64_t> readConfigIntArray (toml_table_t *table, const std::string &key, std::vector<int64_t> notFoundValue);
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);
toml_table_t *openConfig (const std::filesystem::path &path);
toml_table_t *openConfigSection (const toml_table_t *config, const std::string &sectionName);
bool readConfigBool (const toml_table_t *table, const std::string &key, bool notFoundValue);
i64 readConfigInt (const toml_table_t *table, const std::string &key, i64 notFoundValue);
std::string readConfigString (const toml_table_t *table, const std::string &key, const std::string &notFoundValue);
std::vector<i64> readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector<i64> notFoundValue);
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);
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);
bool AreAllBytesZero (const u8 *array, size_t offset, size_t length);

View File

@ -15,50 +15,56 @@
*/
#include "logger.h"
#include "helpers.h"
#include <time.h>
#include <stdlib.h>
#include <string.h>
static Logger *loggerInstance = NULL;
void *consoleHandle = 0;
static Logger *loggerInstance = nullptr;
void *consoleHandle = nullptr;
std::mutex logMutex; // Mutex for thread-safe logging
char timeStr[64];
time_t rawtime;
struct tm *timeinfo;
time_t rawTime;
tm *timeInfo;
SYSTEMTIME systemTime;
/*static std::unique_ptr<plog::RollingFileAppender<plog::TxtFormatter>> fileAppender;
static std::unique_ptr<plog::ConsoleAppender<plog::TxtFormatter>> consoleAppender;*/
void
InitializeLogger (LogLevel level, bool logToFile) {
InitializeLogger (const LogLevel level, const bool logToFile) {
if (loggerInstance == nullptr) {
loggerInstance = (Logger *)malloc (sizeof (Logger));
if (consoleHandle == 0) consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE);
loggerInstance = static_cast<Logger *> (malloc (sizeof (Logger)));
if (consoleHandle == nullptr) 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.");
if (!loggerInstance->logFile) LogMessage (LogLevel::WARN, std::string ("Failed to open TaikoArcadeLoader.log for writing."));
} else loggerInstance->logFile = nullptr; // No file logging
/*consoleAppender = std::make_unique<plog::ConsoleAppender<plog::TxtFormatter>> ();
auto& init = plog::init (plog::verbose, consoleAppender.get ());
if (logToFile) {
fileAppender = std::make_unique<plog::RollingFileAppender<plog::TxtFormatter>> ("TaikoArcadeLoader.log", 1000000, 3);
init.addAppender (fileAppender.get ());
}*/
}
void
LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const std::string format, ...) {
LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *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);
std::lock_guard 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
int requiredSize = vsnprintf (nullptr, 0, format, args) + 1; // +1 for null terminator
std::unique_ptr<char[]> buffer (new char[requiredSize]); // Allocate buffer dynamically
vsnprintf (buffer.get (), requiredSize, format, args); // Format the string
std::string formattedMessage (buffer.get ()); // Convert to std::string
va_end (args);
// Determine log type string
@ -67,10 +73,10 @@ LogMessageHandler (const char *function, const char *codeFile, int codeLine, Log
// Get current time and milliseconds
SYSTEMTIME systemTime;
GetSystemTime (&systemTime);
time_t rawtime = time (nullptr);
struct tm *timeinfo = localtime (&rawtime);
time_t rawTime = time (nullptr);
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;
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;
@ -78,34 +84,34 @@ LogMessageHandler (const char *function, const char *codeFile, int codeLine, Log
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
std::cout << "[" << timeStamp.str () << "] "; // Timestamp
SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color
std::cout << logType; // Level
SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color
std::cout << logMessage << std::endl; // Log message
std::cout.flush (); // Flush to ensure immediate writing
if (loggerInstance->logFile) {
if (loggerInstance->logFile != nullptr) {
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
LogMessageHandler (const char *function, const char *codeFile, const int codeLine, const LogLevel messageLevel, const wchar_t *format, ...) {
const 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
LogMessageHandler (function, codeFile, codeLine, messageLevel, utf8Message.c_str (), args); // Delegate to the original handler
va_end (args);
}
void
CleanupLogger () {
if (loggerInstance != NULL) {
if (loggerInstance != nullptr) {
if (loggerInstance->logFile) fclose (loggerInstance->logFile);
free (loggerInstance);
loggerInstance = NULL;
loggerInstance = nullptr;
}
}

View File

@ -1,10 +1,25 @@
#ifndef LOGGER_H
#define LOGGER_H
#pragma once
#include <stdio.h>
#include <string>
#include "helpers.h"
#include <ctime>
#include <sstream>
#include <iomanip>
#include <source_location>
#include <string_view>
#include <wincon.h>
#include <magic_enum/magic_enum.hpp>
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;
enum class LogLevel {
NONE = 0,
#ifdef ERROR
#undef ERROR
ERROR,
#endif
WARN,
INFO,
DEBUG,
HOOKS
};
/**
* Logger Struct Used to Store Logging Preferences and State
@ -17,49 +32,74 @@ typedef struct {
/* 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, ...);
void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *format, ...);
void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const wchar_t *format, ...);
/* *
* Logs a message with file and line information, if the log level permits.
*
* Use template magic to replace macros and get proper typing support...
*/
template <typename... Args>
struct LogMessage {
LogMessage (const LogLevel level, const std::string_view format, Args &&...ts,
const std::source_location &loc = std::source_location::current ()) {
LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data (), std::forward<Args> (ts)...);
}
LogMessage (const LogLevel level, const std::wstring_view format, Args &&...ts,
const std::source_location &loc = std::source_location::current ()) {
LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data (), std::forward<Args> (ts)...);
}
};
template <>
struct LogMessage<void> {
LogMessage (const LogLevel level, const std::string_view format, const std::source_location &loc = std::source_location::current ()) {
LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ());
}
LogMessage (const LogLevel level, const std::wstring_view format, const std::source_location &loc = std::source_location::current ()) {
LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ());
}
};
LogMessage (LogLevel level, std::string_view format) -> LogMessage<void>;
LogMessage (LogLevel level, std::wstring_view format) -> LogMessage<void>;
template <typename... Args>
LogMessage (LogLevel level, std::string_view format, Args &&...ts) -> LogMessage<Args...>;
template <typename... Args>
LogMessage (LogLevel level, std::wstring_view format, Args &&...ts) -> LogMessage<Args...>;
/* Converts a string to a LogLevel type. */
LogLevel
inline 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;
const auto level = magic_enum::enum_cast<LogLevel> (logLevelStr);
return level.value_or (LogLevel::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: ";
}
inline std::string
GetLogLevelString (const LogLevel messageLevel) {
const auto level = magic_enum::enum_name (messageLevel);
return std::string (level) + ": ";
}
int
GetLogLevelColor (LogLevel messageLevel) {
inline int
GetLogLevelColor (const 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;
case LogLevel::DEBUG: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; // Pale Blue
case LogLevel::INFO: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // Pale Green
case LogLevel::WARN: return FOREGROUND_RED | FOREGROUND_GREEN; // Bright Yellow
case LogLevel::ERROR: return FOREGROUND_RED; // Bright RED
case LogLevel::HOOKS: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; // Pale Purple
default: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
}
/* Cleans up the logger, closing files if necessary. */
void CleanupLogger ();
#endif /* LOGGER_H */

View File

@ -1,15 +1,8 @@
#include <winsock2.h>
#include "helpers.h"
#include <bits/stdc++.h>
#include <format>
#include <MinHook.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <toml.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
/*
@ -29,9 +22,9 @@ namespace patches::AmAuth {
char server_ip[16];
const GUID IID_CAuth{0x045A5150, 0xD2B3, 0x4590, {0xA3, 0x8B, 0xC1, 0x15, 0x86, 0x78, 0xE1, 0xAC}};
constexpr GUID IID_CAuth{0x045A5150, 0xD2B3, 0x4590, {0xA3, 0x8B, 0xC1, 0x15, 0x86, 0x78, 0xE1, 0xAC}};
const GUID IID_CAuthFactory{0x4603BB03, 0x058D, 0x43D9, {0xB9, 0x6F, 0x63, 0x9B, 0xE9, 0x08, 0xC1, 0xED}};
constexpr GUID IID_CAuthFactory{0x4603BB03, 0x058D, 0x43D9, {0xB9, 0x6F, 0x63, 0x9B, 0xE9, 0x08, 0xC1, 0xED}};
typedef struct amcus_network_state {
char mode[16];
@ -44,11 +37,11 @@ typedef struct amcus_network_state {
char gateway[16];
char primary_dns[16];
int hop_count;
uint32_t line_type;
uint32_t line_status;
uint32_t content_router_status;
uint32_t shop_router_status;
uint32_t hop_status;
u32 line_type;
u32 line_status;
u32 content_router_status;
u32 shop_router_status;
u32 hop_status;
} amcus_network_state_t;
typedef struct amcus_auth_server_resp {
@ -84,57 +77,58 @@ struct allnet_state {};
/* Memory Size: 144 */
struct mucha_state {
/* Offset: 0 */ /* ENUM32 */ uint32_t state;
/* Offset: 4 */ /* ENUM32 */ uint32_t error;
/* Offset: 8 */ int32_t auth_state;
/* Offset: 12 */ int32_t auth_count;
/* Offset: 16 */ int32_t state_dlexec;
/* Offset: 20 */ int32_t state_dlstep;
/* Offset: 24 */ int32_t state_dllan;
/* Offset: 28 */ int32_t state_dlwan;
/* Offset: 32 */ int32_t state_io;
/* Offset: 36 */ int16_t cacfg_ver_major;
/* Offset: 38 */ int16_t cacfg_ver_minor;
/* Offset: 40 */ int16_t app_ver_major;
/* Offset: 42 */ int16_t app_ver_minor;
/* Offset: 44 */ int16_t dl_ver_major;
/* Offset: 46 */ int16_t dl_ver_minor;
/* Offset: 48 */ int32_t dl_ver_total;
/* Offset: 52 */ int32_t dl_ver_done;
/* Offset: 56 */ int64_t dl_total;
/* Offset: 64 */ int64_t dl_done;
/* Offset: 72 */ int64_t dl_pc_done;
/* Offset: 80 */ int64_t dl_io_total;
/* Offset: 88 */ int64_t dl_io_done;
/* Offset: 96 */ int32_t dl_check_complete;
/* Offset: 100 */ int32_t token_consumed;
/* Offset: 104 */ int32_t token_charged;
/* Offset: 108 */ int32_t token_unit;
/* Offset: 112 */ int32_t token_lower;
/* Offset: 116 */ int32_t token_upper;
/* Offset: 120 */ int32_t token_added;
/* Offset: 124 */ int32_t token_month_lower;
/* Offset: 128 */ int32_t token_month_upper;
/* Offset: 132 */ int32_t is_forced_boot;
/* Offset: 136 */ int32_t Member88;
/* Offset: 140 */ int32_t unknown_a;
/* Offset: 144 */ int32_t unknown_b;
/* Offset: 0 */ /* ENUM32 */ u32 state;
/* Offset: 4 */ /* ENUM32 */ u32 error;
/* Offset: 8 */ i32 auth_state;
/* Offset: 12 */ i32 auth_count;
/* Offset: 16 */ i32 state_dlexec;
/* Offset: 20 */ i32 state_dlstep;
/* Offset: 24 */ i32 state_dllan;
/* Offset: 28 */ i32 state_dlwan;
/* Offset: 32 */ i32 state_io;
/* Offset: 36 */ i16 cacfg_ver_major;
/* Offset: 38 */ i16 cacfg_ver_minor;
/* Offset: 40 */ i16 app_ver_major;
/* Offset: 42 */ i16 app_ver_minor;
/* Offset: 44 */ i16 dl_ver_major;
/* Offset: 46 */ i16 dl_ver_minor;
/* Offset: 48 */ i32 dl_ver_total;
/* Offset: 52 */ i32 dl_ver_done;
/* Offset: 56 */ i64 dl_total;
/* Offset: 64 */ i64 dl_done;
/* Offset: 72 */ i64 dl_pc_done;
/* Offset: 80 */ i64 dl_io_total;
/* Offset: 88 */ i64 dl_io_done;
/* Offset: 96 */ i32 dl_check_complete;
/* Offset: 100 */ i32 token_consumed;
/* Offset: 104 */ i32 token_charged;
/* Offset: 108 */ i32 token_unit;
/* Offset: 112 */ i32 token_lower;
/* Offset: 116 */ i32 token_upper;
/* Offset: 120 */ i32 token_added;
/* Offset: 124 */ i32 token_month_lower;
/* Offset: 128 */ i32 token_month_upper;
/* Offset: 132 */ i32 is_forced_boot;
/* Offset: 136 */ i32 Member88;
/* Offset: 140 */ i32 unknown_a;
/* Offset: 144 */ i32 unknown_b;
};
/* Memory Size: 208 */
typedef struct amcus_state {
/* Offset: 0 */ /* ENUM32 */ uint32_t allnet_state;
/* Offset: 4 */ /* ENUM32 */ uint32_t allnet_error;
/* Offset: 8 */ int32_t allnet_auth_state;
/* Offset: 12 */ int32_t allnet_auth_count;
/* Offset: 16 */ int32_t allnet_last_error;
/* Offset: 24 */ struct mucha_state mucha_state;
/* Offset: 176 */ int64_t clock_status;
/* Offset: 184 */ int64_t name_resolution_timeout;
/* Offset: 192 */ /* ENUM32 */ uint32_t auth_type;
/* Offset: 196 */ /* ENUM32 */ uint32_t cab_mode;
/* Offset: 200 */ /* ENUM32 */ uint32_t state;
/* Offset: 204 */ /* ENUM32 */ uint32_t err;
/* Offset: 0 */ /* ENUM32 */ u32 allnet_state;
/* Offset: 4 */ /* ENUM32 */ u32 allnet_error;
/* Offset: 8 */ i32 allnet_auth_state;
/* Offset: 12 */ i32 allnet_auth_count;
/* Offset: 16 */ i32 allnet_last_error;
/* Offset: 24 */
mucha_state mucha_state;
/* Offset: 176 */ i64 clock_status;
/* Offset: 184 */ i64 name_resolution_timeout;
/* Offset: 192 */ /* ENUM32 */ u32 auth_type;
/* Offset: 196 */ /* ENUM32 */ u32 cab_mode;
/* Offset: 200 */ /* ENUM32 */ u32 state;
/* Offset: 204 */ /* ENUM32 */ u32 err;
} amcus_state_t;
typedef struct mucha_boardauth_resp {
@ -266,22 +260,21 @@ enum daemon_mode {
class CAuth : public IUnknown {
public:
STDMETHODIMP
QueryInterface (REFIID riid, LPVOID *ppvObj) {
QueryInterface (REFIID riid, LPVOID *ppvObj) override {
wchar_t *iid_str;
StringFromCLSID (riid, &iid_str);
[[maybe_unused]] auto _ = StringFromCLSID (riid, &iid_str);
if (riid == IID_IUnknown || riid == IID_CAuth) {
*ppvObj = this;
this->AddRef ();
return 0;
} else {
*ppvObj = 0;
return E_NOINTERFACE;
}
*ppvObj = nullptr;
return E_NOINTERFACE;
}
STDMETHODIMP_ (ULONG) AddRef () { return this->refCount++; }
STDMETHODIMP_ (ULONG) Release () {
STDMETHODIMP_ (ULONG) AddRef () override { return this->refCount++; }
STDMETHODIMP_ (ULONG) Release () override {
this->refCount--;
if (this->refCount <= 0) {
// delete this;
@ -290,25 +283,25 @@ public:
return this->refCount;
}
virtual int64_t Unk3 (uint32_t a1) { return 1; }
virtual i64 Unk3 (u32 a1) { return 1; }
virtual int64_t Unk4 () { return 1; }
virtual i64 Unk4 () { return 1; }
virtual int32_t Unk5 () { return 0; }
virtual i32 Unk5 () { return 0; }
virtual int64_t Unk6 () { return 1; }
virtual i64 Unk6 () { return 1; }
virtual int32_t Unk7 () { return 0; }
virtual i32 Unk7 () { return 0; }
virtual int32_t Unk8 () { return 0; }
virtual i32 Unk8 () { return 0; }
virtual int32_t IAuth_GetUpdaterState (amcus_state_t *arr) {
virtual i32 IAuth_GetUpdaterState (amcus_state_t *arr) {
memset (arr, 0, sizeof (*arr));
// Convert gameVerNum from string to double
double ver_d = std::stod (gameVerNum.c_str ());
const double ver_d = std::stod (gameVerNum.c_str ());
int ver_top = (int)ver_d;
int ver_btm = (int)(ver_d * 100);
const int ver_top = static_cast<int> (ver_d);
int ver_btm = static_cast<int> (ver_d * 100);
if (ver_top != 0) ver_btm %= (ver_top * 100);
@ -338,7 +331,7 @@ public:
arr->cab_mode = DAEMON_MODE_STANDALONE;
arr->state = DAEMON_IDLE;
/*memset(a1, 0, sizeof(int32_t) * 0x31);
/*memset(a1, 0, sizeof(i32) * 0x31);
a1[0] = 15;
a1[2] = 2;
a1[3] = 1;
@ -358,7 +351,7 @@ public:
return 0;
}
virtual int32_t IAuth_GetCabinetConfig (amcus_network_state_t *state) {
virtual i32 IAuth_GetCabinetConfig (amcus_network_state_t *state) {
memset (state, 0, sizeof (*state));
strcpy_s (state->mode, "STANDALONE");
strcpy_s (state->pcbid, "ABLN1080001");
@ -379,7 +372,7 @@ public:
return 0;
}
virtual int32_t IAuth_GetVersionInfo (amcus_version_info_t *version) {
virtual i32 IAuth_GetVersionInfo (amcus_version_info_t *version) {
memset (version, 0, sizeof (*version));
strcpy_s (version->game_rev, "1");
strcpy_s (version->auth_type, "ALL.NET");
@ -393,11 +386,11 @@ public:
return 0;
}
virtual int32_t Unk12 () { return 1; }
virtual i32 Unk12 () { return 1; }
virtual int32_t Unk13 () { return 1; }
virtual i32 Unk13 () { return 1; }
virtual int32_t IAuth_GetAuthServerResp (amcus_auth_server_resp_t *resp) {
virtual i32 IAuth_GetAuthServerResp (amcus_auth_server_resp_t *resp) {
memset (resp, 0, sizeof (*resp));
strcpy_s (resp->uri, fullAddress);
strcpy_s (resp->host, fullAddress);
@ -419,13 +412,13 @@ public:
return 0;
}
virtual int32_t Unk15 () { return 0; }
virtual i32 Unk15 () { return 0; }
virtual int32_t Unk16 () { return 0; }
virtual i32 Unk16 () { return 0; }
virtual int32_t Unk17 () { return 0; }
virtual i32 Unk17 () { return 0; }
virtual int32_t IAuth_GetMuchaAuthResponse (mucha_boardauth_resp_t *arr) {
virtual i32 IAuth_GetMuchaAuthResponse (mucha_boardauth_resp_t *arr) {
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 ());
@ -460,94 +453,91 @@ public:
return 0;
}
virtual int32_t Unk19 (uint8_t *a1) {
virtual i32 Unk19 (u8 *a1) {
memset (a1, 0, 0x38);
a1[0] = 1;
return 1;
}
virtual int32_t Unk20 () { return 0; }
virtual i32 Unk20 () { return 0; }
virtual int32_t Unk21 () { return 1; }
virtual i32 Unk21 () { return 1; }
virtual int32_t Unk22 () { return 0; }
virtual i32 Unk22 () { return 0; }
virtual int32_t Unk23 () { return 0; }
virtual i32 Unk23 () { return 0; }
virtual int32_t Unk24 () { return 0; }
virtual i32 Unk24 () { return 0; }
virtual int32_t Unk25 () { return 1; }
virtual i32 Unk25 () { return 1; }
virtual int32_t Unk26 () { return 0; }
virtual i32 Unk26 () { return 0; }
virtual int32_t Unk27 () { return 1; }
virtual i32 Unk27 () { return 1; }
virtual int32_t Unk28 () { return 0; }
virtual i32 Unk28 () { return 0; }
virtual int32_t Unk29 () { return 0; }
virtual i32 Unk29 () { return 0; }
virtual int32_t Unk30 () { return 0; }
virtual i32 Unk30 () { return 0; }
virtual int32_t PrintDebugInfo () { return 0; }
virtual i32 PrintDebugInfo () { return 0; }
virtual int32_t Unk32 (void *a1) { return 0; }
virtual i32 Unk32 (void *a1) { return 0; }
virtual void Unk33 () {}
public:
CAuth () {}
virtual ~CAuth () {}
private:
int32_t refCount = 0;
i32 refCount = 0;
};
class CAuthFactory final : public IClassFactory {
public:
virtual ~CAuthFactory () = default;
STDMETHODIMP
QueryInterface (REFIID riid, LPVOID *ppvObj) {
QueryInterface (REFIID riid, LPVOID *ppvObj) override {
wchar_t *iid_str;
StringFromCLSID (riid, &iid_str);
[[maybe_unused]] auto _ = StringFromCLSID (riid, &iid_str);
if (riid == IID_IUnknown || riid == IID_IClassFactory || riid == IID_CAuthFactory) {
*ppvObj = this;
return 0;
} else {
*ppvObj = 0;
return E_NOINTERFACE;
}
*ppvObj = nullptr;
return E_NOINTERFACE;
}
STDMETHODIMP_ (ULONG) AddRef () { return 2; }
STDMETHODIMP_ (ULONG) Release () { return 1; }
STDMETHODIMP_ (ULONG) AddRef () override { return 2; }
STDMETHODIMP_ (ULONG) Release () override { return 1; }
virtual HRESULT CreateInstance (IUnknown *outer, REFIID riid, void **object) {
HRESULT CreateInstance (IUnknown *outer, REFIID riid, void **object) override {
if (outer != nullptr) return CLASS_E_NOAGGREGATION;
CAuth *auth = new CAuth ();
const auto auth = new CAuth ();
return auth->QueryInterface (riid, object);
}
virtual HRESULT LockServer (int32_t lock) { return 0; }
HRESULT LockServer (i32 lock) override { return 0; }
};
static HRESULT (STDAPICALLTYPE *g_origCoCreateInstance) (const IID *const rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, const IID *const riid,
LPVOID *ppv);
static HRESULT (STDAPICALLTYPE *g_origCoCreateInstance) (const IID *rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, const IID *riid, LPVOID *ppv);
static HRESULT STDAPICALLTYPE
CoCreateInstanceHook (const IID *const rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, const IID *const riid, LPVOID *ppv) {
CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const DWORD dwClsContext, const IID *const riid, LPVOID *ppv) {
HRESULT result;
LPOLESTR clsidStr = nullptr;
LPOLESTR iidStr = nullptr;
StringFromIID (*rclsid, &clsidStr);
StringFromIID (*riid, &iidStr);
LPOLESTR clsidStr = nullptr;
LPOLESTR iidStr = nullptr;
[[maybe_unused]] auto _ = StringFromIID (*rclsid, &clsidStr);
_ = StringFromIID (*riid, &iidStr);
if (IsEqualGUID (*rclsid, IID_CAuthFactory) && IsEqualGUID (*riid, IID_CAuth)) {
auto cauth = new CAuth ();
result = cauth->QueryInterface (*riid, ppv);
const auto cauth = new CAuth ();
result = cauth->QueryInterface (*riid, ppv);
} else {
result = g_origCoCreateInstance (rclsid, pUnkOuter, dwClsContext, riid, ppv);
}
@ -559,18 +549,18 @@ CoCreateInstanceHook (const IID *const rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsC
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init AmAuth patches");
LogMessage (LogLevel::INFO, "Init AmAuth patches");
MH_Initialize ();
MH_CreateHookApi (L"ole32.dll", "CoCreateInstance", (LPVOID)CoCreateInstanceHook,
(void **)&g_origCoCreateInstance); // NOLINT(clang-diagnostic-microsoft-cast)
MH_CreateHookApi (L"ole32.dll", "CoCreateInstance", reinterpret_cast<LPVOID> (CoCreateInstanceHook),
reinterpret_cast<void **> (&g_origCoCreateInstance));
MH_EnableHook (nullptr);
struct addrinfo *res = 0;
getaddrinfo (server.c_str (), "", 0, &res);
for (struct addrinfo *i = res; i != 0; i = i->ai_next) {
addrinfo *res = nullptr;
getaddrinfo (server.c_str (), "", nullptr, &res);
for (const addrinfo *i = res; i != nullptr; i = i->ai_next) {
if (res->ai_addr->sa_family != AF_INET) continue;
struct sockaddr_in *p = (struct sockaddr_in *)res->ai_addr;
const sockaddr_in *p = reinterpret_cast<struct sockaddr_in *> (res->ai_addr);
inet_ntop (AF_INET, &p->sin_addr, server_ip, 0x10);
break;
}

View File

@ -7,14 +7,14 @@ extern GameVersion gameVersion;
namespace patches::Audio {
typedef struct nusc_init_config {
uint32_t sample_rate;
uint32_t buffer_size;
uint32_t device_mode;
uint32_t channel_count;
u32 sample_rate;
u32 buffer_size;
u32 device_mode;
u32 channel_count;
const char *asio_driver_name;
bool wasapi_disable_com;
bool wasapi_exclusive;
uint32_t wasapi_exclusive_buffer_size;
u32 wasapi_exclusive_buffer_size;
void *wasapi_audioses;
} nusc_init_config_t;
@ -23,17 +23,17 @@ 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 ());
LogMessage (LogLevel::INFO, (std::string ("Device mode is ") + (asio ? "ASIO" : (wasapiShared ? "wasapi shared" : "wasapi exclusive"))).c_str ());
if (asio) LogMessage (LogLevel::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;
return originalNUSCDeviceInit (a1, a2, a3, a4);
}
HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
auto result = originalLoadASIODriver (a1, a2);
const auto result = originalLoadASIODriver (a1, a2);
if (!result) {
LogMessage (LOG_LEVEL_ERROR, (std::string ("Failed to load ASIO driver ") + asioDriver).c_str ());
LogMessage (LogLevel::ERROR, (std::string ("Failed to load ASIO driver ") + asioDriver).c_str ());
MessageBoxA (nullptr, "Failed to load ASIO driver", nullptr, MB_OK);
ExitProcess (0);
}
@ -42,12 +42,12 @@ HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init Audio patches");
LogMessage (LogLevel::INFO, "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);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
auto audio = openConfigSection (config_ptr.get (), "audio");
const auto audio = openConfigSection (config_ptr.get (), "audio");
if (audio) {
wasapiShared = readConfigBool (audio, "wasapi_shared", wasapiShared);
asio = readConfigBool (audio, "asio", asio);

View File

@ -10,7 +10,6 @@
#include "dxgi1_5.h"
#include "dxgi1_6.h"
#include "helpers.h"
#include <MinHook.h>
#include "bnusio.h"
#include "patches.h"
@ -75,11 +74,11 @@ HookVtableFunction (T *functionPtr, T target) {
static HRESULT STDMETHODCALLTYPE
CreateSwapChainWrap (IDXGIFactory *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain) {
HRESULT hr = g_oldCreateSwapChain (This, pDevice, pDesc, ppSwapChain);
const HRESULT hr = g_oldCreateSwapChain (This, pDevice, pDesc, ppSwapChain);
if (*ppSwapChain) {
if (FpsLimiterEnable) {
auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
g_oldPresentWrap = (old2) ? old2 : g_oldPresentWrap;
}
}
@ -88,13 +87,13 @@ CreateSwapChainWrap (IDXGIFactory *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC
}
static HRESULT STDMETHODCALLTYPE
CreateSwapChainForHwndWrap (IDXGIFactory2 *This, IUnknown *pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1 *pDesc,
CreateSwapChainForHwndWrap (IDXGIFactory2 *This, IUnknown *pDevice, const HWND hWnd, const DXGI_SWAP_CHAIN_DESC1 *pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, IDXGIOutput *pRestrictToOutput, IDXGISwapChain1 **ppSwapChain) {
HRESULT hr = g_oldCreateSwapChainForHwnd (This, pDevice, hWnd, pDesc, NULL, pRestrictToOutput, ppSwapChain);
const HRESULT hr = g_oldCreateSwapChainForHwnd (This, pDevice, hWnd, pDesc, nullptr, pRestrictToOutput, ppSwapChain);
if (*ppSwapChain) {
if (FpsLimiterEnable) {
auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, Present1Wrap);
const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, Present1Wrap);
g_oldPresent1Wrap = (old2) ? old2 : g_oldPresent1Wrap;
}
}
@ -103,7 +102,7 @@ CreateSwapChainForHwndWrap (IDXGIFactory2 *This, IUnknown *pDevice, HWND hWnd, c
}
static HRESULT STDMETHODCALLTYPE
PresentWrap (IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT Flags) {
PresentWrap (IDXGISwapChain *pSwapChain, const UINT SyncInterval, const UINT Flags) {
if (FpsLimiterEnable) patches::FpsLimiter::Update ();
bnusio::Update ();
@ -112,7 +111,7 @@ PresentWrap (IDXGISwapChain *pSwapChain, UINT SyncInterval, UINT Flags) {
}
static HRESULT STDMETHODCALLTYPE
Present1Wrap (IDXGISwapChain1 *pSwapChain, UINT SyncInterval, UINT Flags) {
Present1Wrap (IDXGISwapChain1 *pSwapChain, const UINT SyncInterval, const UINT Flags) {
if (FpsLimiterEnable) patches::FpsLimiter::Update ();
bnusio::Update ();
@ -122,11 +121,11 @@ Present1Wrap (IDXGISwapChain1 *pSwapChain, UINT SyncInterval, UINT Flags) {
static HRESULT STDMETHODCALLTYPE
CreateSwapChain2Wrap (IDXGIFactory2 *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DESC *pDesc, IDXGISwapChain **ppSwapChain) {
HRESULT hr = g_oldCreateSwapChain2 (This, pDevice, pDesc, ppSwapChain);
const HRESULT hr = g_oldCreateSwapChain2 (This, pDevice, pDesc, ppSwapChain);
if (*ppSwapChain) {
if (FpsLimiterEnable) {
auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
g_oldPresentWrap = (old2) ? old2 : g_oldPresentWrap;
}
}
@ -135,13 +134,13 @@ CreateSwapChain2Wrap (IDXGIFactory2 *This, IUnknown *pDevice, DXGI_SWAP_CHAIN_DE
}
static HRESULT WINAPI
CreateDXGIFactory2Wrap (UINT Flags, REFIID riid, void **ppFactory) {
HRESULT hr = g_origCreateDXGIFactory2 (Flags, riid, ppFactory);
CreateDXGIFactory2Wrap (const UINT Flags, REFIID riid, void **ppFactory) {
const HRESULT hr = g_origCreateDXGIFactory2 (Flags, riid, ppFactory);
if (SUCCEEDED (hr)) {
IDXGIFactory2 *factory = (IDXGIFactory2 *)*ppFactory;
const IDXGIFactory2 *factory = static_cast<IDXGIFactory2 *> (*ppFactory);
auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChain, CreateSwapChain2Wrap);
const auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChain, CreateSwapChain2Wrap);
g_oldCreateSwapChain2 = (old) ? old : g_oldCreateSwapChain2;
}
@ -150,7 +149,7 @@ CreateDXGIFactory2Wrap (UINT Flags, REFIID riid, void **ppFactory) {
static HRESULT WINAPI
CreateDXGIFactoryWrap (REFIID riid, _COM_Outptr_ void **ppFactory) {
HRESULT hr = g_origCreateDXGIFactory (riid, ppFactory);
const HRESULT hr = g_origCreateDXGIFactory (riid, ppFactory);
if (SUCCEEDED (hr)) {
int factoryType = 0;
@ -164,16 +163,16 @@ CreateDXGIFactoryWrap (REFIID riid, _COM_Outptr_ void **ppFactory) {
else if (IsEqualIID (riid, IID_IDXGIFactory7)) factoryType = 7;
if (factoryType >= 0) {
IDXGIFactory *factory = (IDXGIFactory *)*ppFactory;
const IDXGIFactory *factory = static_cast<IDXGIFactory *> (*ppFactory);
auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChain, CreateSwapChainWrap);
const auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChain, CreateSwapChainWrap);
g_oldCreateSwapChain = (old) ? old : g_oldCreateSwapChain;
}
if (factoryType >= 2) {
IDXGIFactory2 *factory = (IDXGIFactory2 *)*ppFactory;
const IDXGIFactory2 *factory = static_cast<IDXGIFactory2 *> (*ppFactory);
auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChainForHwnd, CreateSwapChainForHwndWrap);
const auto old = HookVtableFunction (&factory->lpVtbl->CreateSwapChainForHwnd, CreateSwapChainForHwndWrap);
g_oldCreateSwapChainForHwnd = (old) ? old : g_oldCreateSwapChainForHwnd;
}
}
@ -182,16 +181,16 @@ CreateDXGIFactoryWrap (REFIID riid, _COM_Outptr_ void **ppFactory) {
}
static HRESULT WINAPI
D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags,
const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion,
D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, const D3D_DRIVER_TYPE DriverType, const HMODULE Software, const UINT Flags,
const D3D_FEATURE_LEVEL *pFeatureLevels, const UINT FeatureLevels, const UINT SDKVersion,
/*const*/ DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D11Device **ppDevice,
D3D_FEATURE_LEVEL *pFeatureLevel, ID3D11DeviceContext **ppImmediateContext) {
HRESULT hr = g_origD3D11CreateDeviceAndSwapChain (pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion,
pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
const HRESULT hr = g_origD3D11CreateDeviceAndSwapChain (pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion,
pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
if (ppSwapChain) {
if (FpsLimiterEnable) {
auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
const auto old2 = HookVtableFunction (&(*ppSwapChain)->lpVtbl->Present, PresentWrap);
g_oldPresentWrap = (old2) ? old2 : g_oldPresentWrap;
}
}
@ -201,25 +200,25 @@ D3D11CreateDeviceAndSwapChainWrap (IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE Drive
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init Dxgi patches");
LogMessage (LogLevel::INFO, "Init Dxgi patches");
i32 fpsLimit = 120;
auto configPath = std::filesystem::current_path () / "config.toml";
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) fpsLimit = readConfigInt (graphics, "fpslimit", fpsLimit);
const auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) fpsLimit = (i32)readConfigInt (graphics, "fpslimit", fpsLimit);
}
FpsLimiterEnable = fpsLimit > 0;
patches::FpsLimiter::Init ((float)fpsLimit);
patches::FpsLimiter::Init (static_cast<float> (fpsLimit));
MH_Initialize ();
MH_CreateHookApi (L"dxgi.dll", "CreateDXGIFactory", (LPVOID)CreateDXGIFactoryWrap, (void **)&g_origCreateDXGIFactory);
MH_CreateHookApi (L"dxgi.dll", "CreateDXGIFactory2", (LPVOID)CreateDXGIFactory2Wrap, (void **)&g_origCreateDXGIFactory2);
MH_CreateHookApi (L"d3d11.dll", "D3D11CreateDeviceAndSwapChain", (LPVOID)D3D11CreateDeviceAndSwapChainWrap,
(void **)&g_origD3D11CreateDeviceAndSwapChain);
MH_EnableHook (MH_ALL_HOOKS);
MH_EnableHook (nullptr);
}
} // namespace patches::Dxgi

View File

@ -15,8 +15,8 @@ static double t = 0.0;
static u32 i = 0;
void
Init (float fpsLimit) {
if (fpsLimit > 0) LogMessage (LOG_LEVEL_INFO, "Init Fps Limiter");
Init (const float fpsLimit) {
if (fpsLimit > 0) LogMessage (LogLevel::INFO, "Init Fps Limiter");
targetFrameTime = 1000.0 / fpsLimit;
}
@ -39,7 +39,7 @@ Update () {
bOnce2 = true;
QueryPerformanceFrequency (&PerformanceCount3);
i = 0;
t = 1000.0 / (double)PerformanceCount3.QuadPart;
t = 1000.0 / static_cast<double> (PerformanceCount3.QuadPart);
auto v = t * 2147483648.0;
if (60000.0 > v) {
while (true) {
@ -54,7 +54,7 @@ Update () {
break;
}
if (((double)((PerformanceCount2.QuadPart >> i) - PerformanceCount1.QuadPart) * t) >= targetFrameTime) break;
if ((static_cast<double> ((PerformanceCount2.QuadPart >> i) - PerformanceCount1.QuadPart) * t) >= targetFrameTime) break;
SleepEx (0, 1);
}

View File

@ -1,3 +1,4 @@
#include <functional>
#include "helpers.h"
#include <tomcrypt.h>
#include <zlib.h>
@ -19,8 +20,8 @@ public:
std::vector<RegisteredHandler *> beforeHandlers = {};
std::vector<RegisteredHandler *> afterHandlers = {};
uint32_t
CRC32C (uint32_t crc, const unsigned char *buf, size_t len) {
u32
CRC32C (u32 crc, const unsigned char *buf, size_t len) {
int k;
crc = ~crc;
@ -33,12 +34,12 @@ CRC32C (uint32_t crc, const unsigned char *buf, size_t len) {
}
bool
CheckCRC (const std::string &path, uint32_t crc) {
CheckCRC (const std::string &path, const u32 crc) {
if (std::filesystem::exists (path)) {
std::filesystem::path crc_path = path;
crc_path.replace_extension (".crc");
std::ifstream crc_file (crc_path, std::ios::binary);
std::string crc_content ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
const std::string crc_content ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
return std::stoul (crc_content) != crc;
}
return 1;
@ -46,21 +47,21 @@ CheckCRC (const std::string &path, uint32_t crc) {
void
CreateDirectories (const std::string &path) {
size_t pos = 0;
std::string delimiter = "\\";
size_t pos = 0;
const std::string delimiter = "\\";
std::string current_path;
while ((pos = path.find (delimiter, pos)) != std::string::npos) {
current_path = path.substr (0, pos++);
if (!current_path.empty () && !CreateDirectory (current_path.c_str (), NULL) && GetLastError () != ERROR_ALREADY_EXISTS)
if (!current_path.empty () && !CreateDirectory (current_path.c_str (), nullptr) && GetLastError () != ERROR_ALREADY_EXISTS)
throw std::runtime_error ("Error creating directory: " + current_path);
}
if (!path.empty () && !CreateDirectory (path.c_str (), NULL) && GetLastError () != ERROR_ALREADY_EXISTS)
if (!path.empty () && !CreateDirectory (path.c_str (), nullptr) && GetLastError () != ERROR_ALREADY_EXISTS)
throw std::runtime_error ("Error creating directory: " + path);
}
void
WriteFile (const std::string &filename, const std::vector<uint8_t> &data, uint32_t original_crc) {
WriteFile (const std::string &filename, const std::vector<u8> &data, u32 original_crc) {
std::string::size_type pos = filename.find_last_of ("\\");
if (pos != std::string::npos) {
std::string directory = filename.substr (0, pos);
@ -80,18 +81,18 @@ WriteFile (const std::string &filename, const std::vector<uint8_t> &data, uint32
std::vector<unsigned char>
GZip_Compress (const std::vector<unsigned char> &data) {
z_stream deflate_stream;
deflate_stream.zalloc = Z_NULL;
deflate_stream.zfree = Z_NULL;
deflate_stream.opaque = Z_NULL;
deflate_stream.avail_in = data.size ();
deflate_stream.zalloc = nullptr;
deflate_stream.zfree = nullptr;
deflate_stream.opaque = nullptr;
deflate_stream.avail_in = (uInt)data.size ();
deflate_stream.next_in = const_cast<Bytef *> (data.data ());
deflateInit2 (&deflate_stream, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
std::vector<unsigned char> compressed_data;
compressed_data.resize (deflateBound (&deflate_stream, data.size ()));
compressed_data.resize (deflateBound (&deflate_stream, (uLong)data.size ()));
deflate_stream.avail_out = compressed_data.size ();
deflate_stream.avail_out = (uInt)compressed_data.size ();
deflate_stream.next_out = compressed_data.data ();
deflate (&deflate_stream, Z_FINISH);
@ -102,52 +103,52 @@ GZip_Compress (const std::vector<unsigned char> &data) {
}
// Function to pad data according to PKCS7
std::vector<uint8_t>
Pad_Data (const std::vector<uint8_t> &data, size_t block_size) {
size_t padding = block_size - (data.size () % block_size);
std::vector<uint8_t> padded_data = data;
padded_data.insert (padded_data.end (), padding, static_cast<uint8_t> (padding));
std::vector<u8>
Pad_Data (const std::vector<u8> &data, const size_t block_size) {
const size_t padding = block_size - (data.size () % block_size);
std::vector<u8> padded_data = data;
padded_data.insert (padded_data.end (), padding, static_cast<u8> (padding));
return padded_data;
}
std::vector<uint8_t>
std::vector<u8>
Hex_To_Bytes (const std::string &hex) {
std::vector<uint8_t> bytes;
std::vector<u8> bytes;
for (size_t i = 0; i < hex.length (); i += 2) {
uint8_t byte = static_cast<uint8_t> (std::stoi (hex.substr (i, 2), nullptr, 16));
u8 byte = static_cast<u8> (std::stoi (hex.substr (i, 2), nullptr, 16));
bytes.push_back (byte);
}
return bytes;
}
std::vector<uint8_t>
std::vector<u8>
EncryptFile (const std::string &input_file, const std::string &hex_key) {
// Convert the key from hex to bytes
std::vector<uint8_t> key = Hex_To_Bytes (hex_key);
const std::vector<u8> key = Hex_To_Bytes (hex_key);
// Generate the 128 bits IV
std::vector<uint8_t> iv (16);
std::vector<u8> iv (16);
for (size_t i = 0; i < iv.size (); ++i)
iv[i] = static_cast<uint8_t> (i);
iv[i] = static_cast<u8> (i);
// Read the entire file into memory
std::ifstream file (input_file, std::ios::binary);
std::vector<uint8_t> data ((std::istreambuf_iterator<char> (file)), std::istreambuf_iterator<char> ());
const std::vector<u8> data ((std::istreambuf_iterator<char> (file)), std::istreambuf_iterator<char> ());
// Compress the data
std::vector<uint8_t> compressed_data = GZip_Compress (data);
const std::vector<u8> compressed_data = GZip_Compress (data);
// Pad the compressed data
std::vector<uint8_t> padded_data = Pad_Data (compressed_data, 16);
const std::vector<u8> padded_data = Pad_Data (compressed_data, 16);
// Encrypt the data
symmetric_CBC cbc;
if (cbc_start (find_cipher ("aes"), iv.data (), key.data (), key.size (), 0, &cbc) != CRYPT_OK)
if (cbc_start (find_cipher ("aes"), iv.data (), key.data (), (int)key.size (), 0, &cbc) != CRYPT_OK)
throw std::runtime_error ("Error initializing CBC");
std::vector<uint8_t> encrypted_data (padded_data.size ());
if (cbc_encrypt (padded_data.data (), encrypted_data.data (), padded_data.size (), &cbc) != CRYPT_OK)
std::vector<u8> encrypted_data (padded_data.size ());
if (cbc_encrypt (padded_data.data (), encrypted_data.data (), (unsigned long)padded_data.size (), &cbc) != CRYPT_OK)
throw std::runtime_error ("Error during encryption");
cbc_done (&cbc);
@ -169,8 +170,8 @@ IsFumenEncrypted (const std::string &filename) {
file.read (reinterpret_cast<char *> (buffer.data ()), buffer.size ());
// Check if the read bytes match the expected pattern
std::vector<unsigned char> expected_bytes = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const std::vector<unsigned char> expected_bytes = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
return buffer != expected_bytes;
}
@ -194,24 +195,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.
LogMessage (LOG_LEVEL_DEBUG, ("Redirecting " + std::filesystem::relative (path).string ()).c_str ());
LogMessage (LogLevel::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) {
LogMessage (LOG_LEVEL_DEBUG,
LogMessage (LogLevel::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 ());
std::vector<u8> crc_vector ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
u32 crc = CRC32C (0, crc_vector.data (), crc_vector.size ());
WriteFile (encPath, EncryptFile (newPath, fumenKey), crc); // And we save it
} else {
LogMessage (
LOG_LEVEL_ERROR,
LogLevel::ERROR,
("Missing or invalid fumen key: " + std::filesystem::relative (newPath).string () + " couldn't be encrypted.").c_str ());
encPath = path.string ();
}
} else LogMessage (LOG_LEVEL_DEBUG, ("Using cached file for: " + std::filesystem::relative (newPath).string ()).c_str ());
} else LogMessage (LogLevel::DEBUG, ("Using cached file for: " + std::filesystem::relative (newPath).string ()).c_str ());
return encPath;
}
}
@ -224,28 +225,28 @@ LayeredFsHandler (const std::string originalFileName, const std::string currentF
if (std::filesystem::exists (encPath)) {
std::ifstream crc_file (json_path, 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 ());
crcBool = CheckCRC (encPath, crc);
std::vector<u8> crc_vector ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
u32 crc = CRC32C (0, crc_vector.data (), crc_vector.size ());
crcBool = CheckCRC (encPath, crc);
}
if (!std::filesystem::exists (encPath) || crcBool) { // And if it hasn't been encrypted before
if (datatableKey.length () == 64) {
// Encrypt the file
LogMessage (LOG_LEVEL_DEBUG, ("Encrypting " + std::filesystem::relative (json_path).string ()).c_str ());
LogMessage (LogLevel::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 ());
std::vector<u8> crc_vector ((std::istreambuf_iterator<char> (crc_file)), std::istreambuf_iterator<char> ());
u32 crc = CRC32C (0, crc_vector.data (), crc_vector.size ());
WriteFile (encPath, EncryptFile (json_path.string (), datatableKey), crc); // And save it
} else {
LogMessage (
LOG_LEVEL_ERROR,
LogLevel::ERROR,
("Missing or invalid datatable key: " + std::filesystem::relative (newPath).string () + " couldn't be encrypted.").c_str ());
encPath = path.string ();
}
} else
// Otherwise use the already encrypted file.
LogMessage (LOG_LEVEL_DEBUG, ("Using cached file for: " + std::filesystem::relative (json_path).string ()).c_str ());
LogMessage (LogLevel::DEBUG, ("Using cached file for: " + std::filesystem::relative (json_path).string ()).c_str ());
return encPath;
}
}
@ -255,24 +256,24 @@ LayeredFsHandler (const std::string originalFileName, const std::string currentF
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 ());
const std::string originalFileName = std::string (lpFileName);
std::string currentFileName = originalFileName;
LogMessage (LogLevel::HOOKS, ("CreateFileA: " + originalFileName).c_str ());
if (!beforeHandlers.empty ()) {
for (auto handler : beforeHandlers) {
for (const auto handler : beforeHandlers) {
std::string result = handler->handlerMethod (originalFileName, currentFileName);
if (result != "") currentFileName = result;
}
}
if (useLayeredFs) {
std::string result = LayeredFsHandler (originalFileName, currentFileName);
const std::string result = LayeredFsHandler (originalFileName, currentFileName);
if (result != "") currentFileName = result;
}
if (!afterHandlers.empty ()) {
for (auto handler : afterHandlers) {
for (const auto handler : afterHandlers) {
std::string result = handler->handlerMethod (originalFileName, currentFileName);
if (result != "") currentFileName = result;
}
@ -311,12 +312,12 @@ HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPC
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init LayeredFs patches");
LogMessage (LogLevel::INFO, "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);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
auto layeredFs = openConfigSection (config_ptr.get (), "layeredfs");
const auto layeredFs = openConfigSection (config_ptr.get (), "layeredfs");
if (layeredFs) useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs);
}
register_cipher (&aes_desc);

View File

@ -1,6 +1,6 @@
#pragma once
#include <string>
#include <functional>
#include <pugiconfig.hpp>
#include <pugixml.hpp>
namespace patches {
@ -43,8 +43,8 @@ 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);
void Append (pugi::xml_node &node, const wchar_t *attr, const std::wstring append);
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 (const pugi::xml_node &node, const wchar_t *attr, const std::wstring& append);
} // namespace TestMode
} // namespace patches

View File

@ -2,10 +2,6 @@
#include "helpers.h"
#include "poll.h"
#include <ReadBarcode.h>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <vector>
#define STB_IMAGE_IMPLEMENTATION
#define STBI_WINDOWS_UTF8
@ -41,21 +37,21 @@ bool qrPluginRegistered = false;
HOOK_DYNAMIC (char, QrInit, i64) { return 1; }
HOOK_DYNAMIC (char, QrClose, i64) { return 1; }
HOOK_DYNAMIC (char, QrRead, i64 a1) {
*(DWORD *)(a1 + 40) = 1;
*(DWORD *)(a1 + 16) = 1;
*(BYTE *)(a1 + 112) = 0;
*reinterpret_cast<DWORD *> (a1 + 40) = 1;
*reinterpret_cast<DWORD *> (a1 + 16) = 1;
*reinterpret_cast<BYTE *> (a1 + 112) = 0;
return 1;
}
HOOK_DYNAMIC (i64, CallQrUnknown, i64) { return 1; }
HOOK_DYNAMIC (bool, Send1, i64 a1) {
*(BYTE *)(a1 + 88) = 1;
*(i64 *)(a1 + 32) = *(i64 *)(a1 + 24);
*(WORD *)(a1 + 89) = 0;
*reinterpret_cast<BYTE *> (a1 + 88) = 1;
*reinterpret_cast<i64 *> (a1 + 32) = *reinterpret_cast<i64 *> (a1 + 24);
*reinterpret_cast<WORD *> (a1 + 89) = 0;
return true;
}
HOOK_DYNAMIC (bool, Send2, i64 a1) {
*(WORD *)(a1 + 88) = 0;
*(BYTE *)(a1 + 90) = 0;
*reinterpret_cast<WORD *> (a1 + 88) = 0;
*reinterpret_cast<BYTE *> (a1 + 90) = 0;
return true;
}
HOOK_DYNAMIC (bool, Send3, i64, char) { return true; }
@ -76,34 +72,32 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
std::vector<i64> songNoes;
if (config_ptr) {
auto qr = openConfigSection (config_ptr.get (), "qr");
if (qr) {
auto data = openConfigSection (qr, "data");
if (data) {
if (auto qr = openConfigSection (config_ptr.get (), "qr")) {
if (auto data = openConfigSection (qr, "data")) {
serial = readConfigString (data, "serial", "");
type = readConfigInt (data, "type", 0);
type = (u16)readConfigInt (data, "type", 0);
songNoes = readConfigIntArray (data, "song_no", songNoes);
}
}
}
BYTE serial_length = (BYTE)serial.size ();
BYTE serial_length = static_cast<BYTE> (serial.size ());
std::vector<BYTE> byteBuffer = {0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, serial_length, 0x01, 0x00};
for (char c : serial)
byteBuffer.push_back ((BYTE)c);
byteBuffer.push_back (static_cast<BYTE> (c));
if (type == 5) {
std::vector<BYTE> folderData = {0xFF, 0xFF};
folderData.push_back (songNoes.size () * 2);
folderData.push_back (static_cast<u8> (songNoes.size ()) * 2);
folderData.push_back ((u8)(type & 0xFF));
folderData.push_back ((u8)((type >> 8) & 0xFF));
folderData.push_back (static_cast<u8> (type & 0xFF));
folderData.push_back (static_cast<u8> ((type >> 8) & 0xFF));
for (u16 songNo : songNoes) {
folderData.push_back ((u8)(songNo & 0xFF));
folderData.push_back ((u8)((songNo >> 8) & 0xFF));
for (i64 songNo : songNoes) {
folderData.push_back (static_cast<u8> (songNo & 0xFF));
folderData.push_back (static_cast<u8> ((songNo >> 8) & 0xFF));
}
for (auto c : folderData)
@ -116,7 +110,7 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
std::stringstream hexStream;
for (auto byteData : byteBuffer)
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 ());
LogMessage (LogLevel::INFO, ("Data dump: " + hexStream.str ()).c_str ());
memcpy (dest, byteBuffer.data (), byteBuffer.size ());
gState = State::Ready;
@ -125,14 +119,13 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
std::string imagePath = "";
if (config_ptr) {
auto qr = openConfigSection (config_ptr.get (), "qr");
if (qr) imagePath = readConfigString (qr, "image_path", "");
if (auto qr = openConfigSection (config_ptr.get (), "qr")) imagePath = readConfigString (qr, "image_path", "");
}
std::u8string u8PathStr (imagePath.begin (), imagePath.end ());
std::filesystem::path u8Path (u8PathStr);
if (!std::filesystem::is_regular_file (u8Path)) {
LogMessage (LOG_LEVEL_ERROR, ("Failed to open image: " + u8Path.string () + " (file not found)").c_str ());
LogMessage (LogLevel::ERROR, ("Failed to open image: " + u8Path.string () + " (file not found)").c_str ());
gState = State::Ready;
return 0;
}
@ -141,7 +134,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) {
LogMessage (LOG_LEVEL_ERROR, ("Failed to read image: " + u8Path.string () + " (" + stbi_failure_reason () + ")").c_str ());
LogMessage (LogLevel::ERROR, ("Failed to read image: " + u8Path.string () + " (" + stbi_failure_reason () + ")").c_str ());
gState = State::Ready;
return 0;
}
@ -149,7 +142,7 @@ 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 ()) {
LogMessage (LOG_LEVEL_ERROR, ("Failed to read QR: " + imagePath + " (" + ToString (result.error ()) + ")").c_str ());
LogMessage (LogLevel::ERROR, ("Failed to read QR: " + imagePath + " (" + ToString (result.error ()) + ")").c_str ());
gState = State::Ready;
return 0;
}
@ -163,18 +156,17 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
gState = State::Ready;
return dataSize;
} else if (gMode == Mode::Plugin) {
FARPROC getEvent = GetProcAddress (gPlugin, "GetQr");
if (getEvent) {
unsigned char plugin_data[length];
int buf_len = ((getQrEvent *)getEvent) (length, plugin_data);
if (FARPROC getEvent = GetProcAddress (gPlugin, "GetQr")) {
std::vector<unsigned char> plugin_data (length);
int buf_len = reinterpret_cast<getQrEvent *> (getEvent) (length, plugin_data.data ());
if (0 < buf_len && buf_len <= length) {
std::stringstream hexStream;
for (int i = 0; i < buf_len; i++)
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);
LogMessage (LogLevel::INFO, ("QR dump: " + hexStream.str ()).c_str ());
memcpy (dest, plugin_data.data (), buf_len);
} else {
LogMessage (LOG_LEVEL_ERROR, ("QR discard! Length invalid: " + std::to_string (buf_len) + ", valid range: 0~").c_str ());
LogMessage (LogLevel::ERROR, ("QR discard! Length invalid: " + std::to_string (buf_len) + ", valid range: 0~").c_str ());
}
gState = State::Ready;
return buf_len;
@ -184,10 +176,8 @@ HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
}
}
} else if (qrPluginRegistered) {
for (auto plugin : qrPlugins) {
FARPROC usingQrEvent = GetProcAddress (plugin, "UsingQr");
if (usingQrEvent) ((event *)usingQrEvent) ();
}
for (auto plugin : qrPlugins)
if (FARPROC usingQrEvent = GetProcAddress (plugin, "UsingQr")) ((event *)usingQrEvent) ();
}
return 0;
}
@ -216,8 +206,8 @@ Update () {
gState = State::CopyWait;
gMode = Mode::Image;
} else if (qrPluginRegistered) {
for (auto plugin : qrPlugins) {
FARPROC checkEvent = GetProcAddress (plugin, "CheckQr");
for (const auto plugin : qrPlugins) {
const FARPROC checkEvent = GetProcAddress (plugin, "CheckQr");
if (checkEvent && ((checkQrEvent *)checkEvent) ()) {
gState = State::CopyWait;
gMode = Mode::Plugin;
@ -231,28 +221,28 @@ Update () {
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init Qr patches");
LogMessage (LogLevel::INFO, "Init Qr patches");
if (!emulateQr) {
LogMessage (LOG_LEVEL_WARN, "QR emulation disabled");
LogMessage (LogLevel::WARN, "QR emulation disabled");
return;
}
for (auto plugin : plugins) {
FARPROC initEvent = GetProcAddress (plugin, "InitQr");
const FARPROC initEvent = GetProcAddress (plugin, "InitQr");
if (initEvent) ((initQrEvent *)initEvent) (gameVersion);
FARPROC usingQrEvent = GetProcAddress (plugin, "UsingQr");
const FARPROC usingQrEvent = GetProcAddress (plugin, "UsingQr");
if (usingQrEvent) qrPlugins.push_back (plugin);
}
if (qrPlugins.size () > 0) {
LogMessage (LOG_LEVEL_INFO, "QR plugin found!");
LogMessage (LogLevel::INFO, "QR plugin found!");
qrPluginRegistered = true;
}
SetConsoleOutputCP (CP_UTF8);
auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
const auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
switch (gameVersion) {
case GameVersion::JPN00: {
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1B3E0));
@ -267,8 +257,8 @@ Init () {
break;
}
case GameVersion::JPN08: {
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1BA00));
INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1BBD0));
INSTALL_HOOK_DYNAMIC (QrInit, reinterpret_cast<LPVOID> (amHandle + 0x1BA00));
INSTALL_HOOK_DYNAMIC (QrClose, reinterpret_cast<LPVOID> (amHandle + 0x1BBD0));
INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1BC20));
INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40));
INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1C220));

View File

@ -12,7 +12,7 @@ class RegisteredItem {
public:
std::wstring selectItem;
std::function<void ()> registerInit;
RegisteredItem (const std::wstring selectItem, const std::function<void ()> &initMethod) {
RegisteredItem (const std::wstring &selectItem, const std::function<void ()> &initMethod) {
this->selectItem = selectItem;
this->registerInit = initMethod;
}
@ -22,7 +22,7 @@ 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) {
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;
@ -39,7 +39,7 @@ 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);
LogMessage (LogLevel::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 ();
@ -62,10 +62,9 @@ CreateMenu (pugi::xml_document &menuMain, std::wstring menuId, std::wstring menu
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 LogMessage (LOG_LEVEL_ERROR, L"Failed to parse option line: " + item);
if (pugi::xml_document menuItem; menuItem.load_string (itemLine.c_str ())) menuCenter.append_copy (menuItem.first_child ().first_child ());
else LogMessage (LogLevel::ERROR, L"Failed to parse option line: " + item);
menuCenter.append_child (L"break-item");
}
menuCenter.append_child (L"break-item");
@ -83,9 +82,9 @@ CreateMenu (pugi::xml_document &menuMain, std::wstring menuId, std::wstring menu
std::wstring
ReadXMLFileSwitcher (std::wstring &fileName) {
std::size_t pos = fileName.rfind (L"/");
const std::size_t pos = fileName.rfind (L"/");
std::wstring base = fileName.substr (0, pos + 1);
std::wstring file = fileName.substr (pos + 1, fileName.size ());
const 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");
@ -97,21 +96,20 @@ ReadXMLFileSwitcher (std::wstring &fileName) {
}
HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) {
std::wstring originalFileName = std::wstring (lFileName);
auto 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 ())) {
LogMessage (LOG_LEVEL_ERROR, L"Loading DeviceInitialize structure failed! path: " + fileName);
if (pugi::xml_document doc; !doc.load_file (fileName.c_str ())) {
LogMessage (LogLevel::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']");
auto 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");
@ -119,7 +117,7 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
talItem.append_attribute (L"default") = L"1";
dongleItem.parent ().append_child (L"break-item");
doc.save_file (modFileName.c_str ());
[[maybe_unused]] auto ignored = doc.save_file (modFileName.c_str ());
moddedInitial = modFileName;
fileName = modFileName;
}
@ -128,16 +126,14 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
if (modded == L"") {
if (!registeredItems.empty () || !registeredModifies.empty ()) {
fileName = ReadXMLFileSwitcher (fileName);
pugi::xml_document doc;
if (!doc.load_file (fileName.c_str ())) {
LogMessage (LOG_LEVEL_ERROR, L"Loading TestMode structure failed! path: " + fileName);
if (pugi::xml_document doc; !doc.load_file (fileName.c_str ())) {
LogMessage (LogLevel::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
if (!registeredItems.empty ()) { auto 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 ();
@ -153,25 +149,23 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
item->registerInit ();
}
CreateMenu (modMenu, L"ModManagerMenu", L"MOD MANAGER", toInsertItems, L"TopMenu");
pugi::xpath_query topMenuQuery = pugi::xpath_query (L"/root/menu[@id='TopMenu']");
auto 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 ()) {
for (RegisteredModify *modify : registeredModifies) {
pugi::xpath_query modifyQuery = pugi::xpath_query (modify->query.c_str ());
for (RegisteredModify *modify : registeredModifies) { auto modifyQuery = pugi::xpath_query (modify->query.c_str ());
try {
pugi::xml_node modifyNode = doc.select_node (modifyQuery).node ();
if (modifyNode) {
if (pugi::xml_node modifyNode = doc.select_node (modifyQuery).node ()) {
modify->nodeModify (modifyNode);
modify->registerInit ();
}
} catch (std::exception &e) { LogMessage (LOG_LEVEL_ERROR, L"Failed to find node by xpath: " + modify->query); }
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: " + modify->query); }
}
}
doc.save_file (modFileName.c_str ());
[[maybe_unused]] auto _ = doc.save_file (modFileName.c_str ());
modded = modFileName;
fileName = modFileName;
}
@ -179,7 +173,7 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
} else fileName = modded;
}
LogMessage (LOG_LEVEL_DEBUG, L"TestModeLibrary load: " + fileName);
LogMessage (LogLevel::DEBUG, L"TestModeLibrary load: " + fileName);
originalTestModeSetMenuHook (testModeLibrary, fileName.c_str ());
}
@ -188,89 +182,89 @@ CommonModify () {
// Default off Close time
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"); }, [&] () {});
[&] (const pugi::xml_node &node) { node.attribute (L"default").set_value (L"0"); }, [&] () {});
}
void
LocalizationCHT () {
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"模組管理"); }, [] () {});
[&] (const 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"模組管理"); }, [] () {});
[&] (const 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) {
[&] (const 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) {
[&] (const 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) {
[&] (const 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) {
[&] (const 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) {
[&] (const 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"離開"); }, [] () {});
[&] (const pugi::xml_node &node) { node.attribute (L"label").set_value (L"離開"); }, [] () {});
}
void
LocalizationCHS () {
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"模组管理"); }, [] () {});
[&] (const 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"模组管理"); }, [] () {});
[&] (const 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) {
[&] (const 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) {
[&] (const 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) {
[&] (const 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) {
[&] (const pugi::xml_node &node) {
node.attribute (L"label").set_value (L"AI粗品模式");
node.attribute (L"replace-text").set_value (L"0:默认, 1:启用, 2:仅刷卡");
},
@ -282,27 +276,25 @@ LocalizationCHS () {
// );
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"离开"); }, [] () {});
[&] (const pugi::xml_node &node) { node.attribute (L"label").set_value (L"离开"); }, [] () {});
}
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init TestMode patches");
LogMessage (LogLevel::INFO, "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);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
u64 testModeSetMenuAddress = PROC_ADDRESS_OFFSET ("TestModeLibrary.dll", 0x99D0);
const 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);
if (const auto patches = openConfigSection (config_ptr.get (), "patches")) {
if (const auto jpn39 = openConfigSection (patches, "jpn39")) chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
}
}
if (chsPatch) LocalizationCHT ();
@ -316,7 +308,7 @@ Init () {
}
void
SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode) {
SetupAccessor (const u64 appAccessor, const RefTestModeMain refTestMode) {
patches::TestMode::appAccessor = appAccessor;
patches::TestMode::refTestMode = refTestMode;
}
@ -324,34 +316,33 @@ SetupAccessor (u64 appAccessor, RefTestModeMain refTestMode) {
int
ReadTestModeValue (const wchar_t *itemId) {
if (appAccessor) {
u64 testModeMain = refTestMode (appAccessor);
if (testModeMain) {
if (const u64 testModeMain = refTestMode (appAccessor)) {
int value = 0;
u64 *reader = *(u64 **)(testModeMain + 16);
(*(void (__fastcall **) (u64 *, const wchar_t *, int *)) (*reader + 256)) (reader, itemId, &value);
u64 *reader = *reinterpret_cast<u64 **> (testModeMain + 16);
(*reinterpret_cast<void (__fastcall **) (u64 *, const wchar_t *, int *)> (*reader + 256)) (reader, itemId, &value);
return value;
}
}
LogMessage (LOG_LEVEL_ERROR, (std::wstring (L"Read TestMode(") + itemId + L") failed!").c_str ());
LogMessage (LogLevel::ERROR, (std::wstring (L"Read TestMode(") + itemId + L") failed!").c_str ());
return -1;
}
void
RegisterItem (const std::wstring item, const std::function<void ()> &initMethod) {
LogMessage (LOG_LEVEL_DEBUG, L"Register Item " + item);
RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod) {
LogMessage (LogLevel::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) {
LogMessage (LOG_LEVEL_DEBUG, L"Register Modify " + query);
RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod) {
LogMessage (LogLevel::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) {
Append (const 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;
const std::wstring attrValue = std::wstring (attribute.value ()) + append;
attribute.set_value (attrValue.c_str ());
}
}

View File

@ -1,6 +1,5 @@
#include "helpers.h"
#include "../patches.h"
#include <safetyhook.hpp>
extern std::string chassisId;
@ -29,50 +28,50 @@ FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"
FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64);
i64
lua_pushtrue (i64 a1) {
lua_pushtrue (const i64 a1) {
lua_settop (a1, 0);
lua_pushboolean (a1, 1);
return 1;
}
HOOK (i64, AvailableMode_Dani_AI, ASLR (0x1401AC550), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Dani_AI was called");
LogMessage (LogLevel::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");
LogMessage (LogLevel::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");
LogMessage (LogLevel::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 (a1);
language = *((u32 *)result);
LogMessage (LogLevel::HOOKS, "GetLanguage was called");
const auto result = originalGetLanguage (a1);
language = *reinterpret_cast<u32 *> (result);
return result;
}
HOOK (i64, GetRegionLanguage, ASLR (0x1401AC300), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "GetRegionLanguage was called");
LogMessage (LogLevel::HOOKS, "GetRegionLanguage was called");
lua_settop (a1, 0);
lua_pushstring (a1, (u64)languageStr (language));
lua_pushstring (a1, reinterpret_cast<u64> (languageStr (language)));
return 1;
}
HOOK (i64, GetCabinetLanguage, ASLR (0x1401AF270), i64, i64 a2) {
LogMessage (LOG_LEVEL_HOOKS, "GetCabinetLanguage was called");
LogMessage (LogLevel::HOOKS, "GetCabinetLanguage was called");
lua_settop (a2, 0);
lua_pushstring (a2, (u64)languageStr (language));
lua_pushstring (a2, reinterpret_cast<u64> (languageStr (language)));
return 1;
}
HOOK_DYNAMIC (char, AMFWTerminate, i64) {
LogMessage (LOG_LEVEL_HOOKS, "AMFWTerminate was called");
LogMessage (LogLevel::HOOKS, "AMFWTerminate was called");
return 0;
}
const i32 datatableBufferSize = 1024 * 1024 * 12;
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
safetyhook::Allocation datatableBuffer1;
safetyhook::Allocation datatableBuffer2;
safetyhook::Allocation datatableBuffer3;
@ -82,26 +81,26 @@ const std::vector<uintptr_t> datatableBuffer3Addresses = {0x14009356F, 0x1400935
const std::vector<uintptr_t> memsetSizeAddresses = {0x140093416, 0x14009342A, 0x140093569};
void
AllocateStaticBufferNear (void *target_address, size_t size, safetyhook::Allocation *newBuffer) {
auto allocator = safetyhook::Allocator::global ();
std::vector desired_addresses = {(uint8_t *)target_address};
auto allocation_result = allocator->allocate_near (desired_addresses, size);
if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result);
AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) {
const auto allocator = safetyhook::Allocator::global ();
const std::vector desired_addresses = {static_cast<u8 *> (target_address)};
if (auto allocation_result = allocator->allocate_near (desired_addresses, size); allocation_result.has_value ())
*newBuffer = std::move (*allocation_result);
}
void
ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *newBufferAddress) {
for (auto bufferAddress : bufferAddresses) {
uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
intptr_t offset = (intptr_t)newBufferAddress - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, (i32)offset);
for (const auto bufferAddress : bufferAddresses) {
const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
const intptr_t offset = reinterpret_cast<intptr_t> (newBufferAddress) - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, static_cast<i32> (offset));
}
}
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init CHN00 patches");
LogMessage (LogLevel::INFO, "Init CHN00 patches");
i32 xRes = 1920;
i32 yRes = 1080;
bool vsync = false;
@ -111,9 +110,9 @@ Init () {
bool modeCollabo025 = false;
bool modeCollabo026 = false;
haspBuffer = (u8 *)malloc (0xD40);
haspBuffer = static_cast<u8 *> (malloc (0xD40));
memset (haspBuffer, 0, 0xD40);
strcpy ((char *)(haspBuffer + 0xD00), chassisId.c_str ());
strcpy (reinterpret_cast<char *> (haspBuffer + 0xD00), chassisId.c_str ());
u8 crc = 0;
for (int i = 0; i < 62; i++)
crc += haspBuffer[0xD00 + i];
@ -128,14 +127,12 @@ Init () {
INSTALL_HOOK (HaspGetInfo);
INSTALL_HOOK (HaspRead);
auto configPath = std::filesystem::current_path () / "config.toml";
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
auto patches = openConfigSection (config_ptr.get (), "patches");
if (patches) {
if (const auto patches = openConfigSection (config_ptr.get (), "patches")) {
unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
auto chn00 = openConfigSection (patches, "chn00");
if (chn00) {
if (const auto chn00 = openConfigSection (patches, "chn00")) {
fixLanguage = readConfigBool (chn00, "fix_language", fixLanguage);
demoMovie = readConfigBool (chn00, "demo_movie", demoMovie);
modeCollabo025 = readConfigBool (chn00, "mode_collabo025", modeCollabo025);
@ -143,12 +140,10 @@ Init () {
}
}
auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) {
auto res = openConfigSection (graphics, "res");
if (res) {
xRes = readConfigInt (res, "x", xRes);
yRes = readConfigInt (res, "y", yRes);
if (const auto graphics = openConfigSection (config_ptr.get (), "graphics")) {
if (const auto res = openConfigSection (graphics, "res")) {
xRes = (i32)readConfigInt (res, "x", xRes);
yRes = (i32)readConfigInt (res, "y", yRes);
}
vsync = readConfigBool (graphics, "vsync", vsync);
}
@ -182,7 +177,7 @@ Init () {
// Remove datatable size limit
{
for (auto address : memsetSizeAddresses)
for (const auto address : memsetSizeAddresses)
WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize);
auto bufferBase = MODULE_HANDLE - 0x03000000;
@ -213,8 +208,8 @@ Init () {
if (modeCollabo026) INSTALL_HOOK (AvailableMode_Collabo026);
// Disable live check
auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x25A00));
const auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x25A00));
// Move various files to current directory
WRITE_MEMORY (amHandle + 0xC652, u8, 0xEB); // CreditLogPathA

View File

@ -1,12 +1,11 @@
#include "helpers.h"
#include "../patches.h"
#include <safetyhook.hpp>
namespace patches::JPN00 {
HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; }
const i32 datatableBufferSize = 1024 * 1024 * 12;
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
safetyhook::Allocation datatableBuffer;
const std::vector<uintptr_t> datatableBufferAddresses
= {0x14005A418, 0x14005A445, 0x14005A778, 0x14005A7A5, 0x14005AD58, 0x14005AD85, 0x14005B1F2, 0x14005B221, 0x14005B438, 0x14005B465,
@ -18,43 +17,41 @@ const std::vector<uintptr_t> memsetSizeAddresses
0x14005CC4C, 0x14005D342, 0x14005D662, 0x14005D9CC, 0x14005E9FE, 0x14005EC12, 0x14005EEDE, 0x14005F152, 0x14005F476};
void
AllocateStaticBufferNear (void *target_address, size_t size, safetyhook::Allocation *newBuffer) {
auto allocator = safetyhook::Allocator::global ();
std::vector desired_addresses = {(uint8_t *)target_address};
auto allocation_result = allocator->allocate_near (desired_addresses, size);
if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result);
AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) {
const auto allocator = safetyhook::Allocator::global ();
const std::vector desired_addresses = {static_cast<u8 *> (target_address)};
if (auto allocation_result = allocator->allocate_near (desired_addresses, size); allocation_result.has_value ())
*newBuffer = std::move (*allocation_result);
}
void
ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *newBufferAddress) {
for (auto bufferAddress : bufferAddresses) {
uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
intptr_t offset = (intptr_t)newBufferAddress - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, (i32)offset);
for (const auto bufferAddress : bufferAddresses) {
const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
const intptr_t offset = reinterpret_cast<intptr_t> (newBufferAddress) - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, static_cast<i32> (offset));
}
}
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init JNP00 patches");
LogMessage (LogLevel::INFO, "Init JNP00 patches");
i32 xRes = 1920;
i32 yRes = 1080;
bool vsync = false;
bool unlockSongs = true;
auto configPath = std::filesystem::current_path () / "config.toml";
std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
const auto configPath = std::filesystem::current_path () / "config.toml";
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
if (config_ptr) {
auto patches = openConfigSection (config_ptr.get (), "patches");
if (patches) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
if (const auto patches = openConfigSection (config_ptr.get (), "patches"))
unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) {
auto res = openConfigSection (graphics, "res");
if (res) {
xRes = readConfigInt (res, "x", xRes);
yRes = readConfigInt (res, "y", yRes);
if (const auto graphics = openConfigSection (config_ptr.get (), "graphics")) {
if (const auto res = openConfigSection (graphics, "res")) {
xRes = (i32)readConfigInt (res, "x", xRes);
yRes = (i32)readConfigInt (res, "y", yRes);
}
vsync = readConfigBool (graphics, "vsync", vsync);
}
@ -80,18 +77,18 @@ Init () {
// Remove datatable size limit
{
for (auto address : memsetSizeAddresses)
for (const auto address : memsetSizeAddresses)
WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize);
auto bufferBase = MODULE_HANDLE - 0x01000000;
const auto bufferBase = MODULE_HANDLE - 0x01000000;
AllocateStaticBufferNear ((void *)bufferBase, datatableBufferSize, &datatableBuffer);
ReplaceLeaBufferAddress (datatableBufferAddresses, datatableBuffer.data ());
}
// Disable live check
auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x24B80));
const auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x24B80));
// Move various files to current directory
WRITE_MEMORY (amHandle + 0x1473F, u8, 0xEB); // CreditLogPathA

View File

@ -1,6 +1,5 @@
#include "helpers.h"
#include "../patches.h"
#include <safetyhook.hpp>
extern u64 song_data_size;
extern void *song_data;
@ -15,7 +14,7 @@ namespace patches::JPN08 {
HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; }
const i32 datatableBufferSize = 1024 * 1024 * 12;
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
safetyhook::Allocation datatableBuffer;
const std::vector<uintptr_t> datatableBufferAddresses
= {0x14006D9A6, 0x14006D9D3, 0x14006E048, 0x14006E075, 0x14006E3A8, 0x14006E3D5, 0x14006E988, 0x14006E9B5, 0x14006EE22, 0x14006EE51, 0x14006F068,
@ -29,26 +28,26 @@ const std::vector<uintptr_t> memsetSizeAddresses
0x14007336E, 0x1400735E2, 0x140073906, 0x140073E6D, 0x140074A87, 0x14007507C, 0x14007551E, 0x14007589C, 0x140075D82};
void
AllocateStaticBufferNear (void *target_address, size_t size, safetyhook::Allocation *newBuffer) {
auto allocator = safetyhook::Allocator::global ();
std::vector desired_addresses = {(uint8_t *)target_address};
auto allocation_result = allocator->allocate_near (desired_addresses, size);
if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result);
AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) {
const auto allocator = safetyhook::Allocator::global ();
const std::vector desired_addresses = {static_cast<u8 *> (target_address)};
if (auto allocation_result = allocator->allocate_near (desired_addresses, size); allocation_result.has_value ())
*newBuffer = std::move (*allocation_result);
}
void
ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *newBufferAddress) {
for (auto bufferAddress : bufferAddresses) {
uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
intptr_t offset = (intptr_t)newBufferAddress - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, (i32)offset);
for (const auto bufferAddress : bufferAddresses) {
const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
const intptr_t offset = reinterpret_cast<intptr_t> (newBufferAddress) - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, static_cast<i32> (offset));
}
}
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init JPN08 patches");
LogMessage (LogLevel::INFO, "Init JPN08 patches");
i32 xRes = 1920;
i32 yRes = 1080;
bool vsync = false;
@ -57,15 +56,12 @@ Init () {
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 patches = openConfigSection (config_ptr.get (), "patches");
if (patches) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
if (auto patches = openConfigSection (config_ptr.get (), "patches")) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) {
auto res = openConfigSection (graphics, "res");
if (res) {
xRes = readConfigInt (res, "x", xRes);
yRes = readConfigInt (res, "y", yRes);
if (auto graphics = openConfigSection (config_ptr.get (), "graphics")) {
if (auto res = openConfigSection (graphics, "res")) {
xRes = (i32)readConfigInt (res, "x", xRes);
yRes = (i32)readConfigInt (res, "y", yRes);
}
vsync = readConfigBool (graphics, "vsync", vsync);
}
@ -167,8 +163,8 @@ Init () {
}
// Disable live check
auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x35A00));
auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x35A00));
// Move various files to current directory
WRITE_MEMORY (amHandle + 0x148AF, u8, 0xEB); // CreditLogPathA

View File

@ -1,17 +1,16 @@
// ReSharper disable CppTooWideScopeInitStatement
#include "helpers.h"
#include "../patches.h"
#include <iostream>
#include <safetyhook.hpp>
namespace patches::JPN39 {
int language = 0;
HOOK_DYNAMIC (char, AMFWTerminate, i64) {
LogMessage (LOG_LEVEL_HOOKS, "AMFWTerminate was called");
LogMessage (LogLevel::HOOKS, "AMFWTerminate was called");
return 0;
}
HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) {
LogMessage (LOG_LEVEL_HOOKS, "Garmc curl_easy_setopt was called");
LogMessage (LogLevel::HOOKS, "Garmc curl_easy_setopt was called");
originalcurl_easy_setopt (a1, 64, 0, 0, 0);
originalcurl_easy_setopt (a1, 81, 0, 0, 0);
return originalcurl_easy_setopt (a1, a2, a3, a4, a5);
@ -38,7 +37,7 @@ FUNCTION_PTR (u64, RefPlayDataManager, ASLR (0x140024AC0), u64);
FUNCTION_PTR (i64, GetUserCount, ASLR (0x1403F1020), u64);
i64
lua_pushbool (i64 a1, bool val) {
lua_pushbool (const i64 a1, const bool val) {
lua_settop (a1, 0);
lua_pushboolean (a1, val);
return 1;
@ -47,65 +46,63 @@ lua_pushbool (i64 a1, bool val) {
u64 appAccessor = 0;
u64 componentAccessor = 0;
HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) {
LogMessage (LOG_LEVEL_HOOKS, "DeviceCheck was called");
LogMessage (LogLevel::HOOKS, "DeviceCheck was called");
TestMode::SetupAccessor (a3, RefTestModeMain);
componentAccessor = a2;
return originalDeviceCheck (a1, a2, a3);
}
int
i64
GetUserStatus () {
if (appAccessor) {
u64 playDataManager = RefPlayDataManager (appAccessor);
if (playDataManager) return GetUserCount (playDataManager);
if (const u64 playDataManager = RefPlayDataManager (appAccessor)) 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 (a1);
int status = TestMode::ReadTestModeValue (L"ModModeCollabo024");
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo024 was called");
if (const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); tournamentMode == 1) return originalAvailableMode_Collabo024 (a1);
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo024");
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
return originalAvailableMode_Collabo024 (a1);
}
HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo025 was called");
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo025 was called");
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
if (tournamentMode == 1) return originalAvailableMode_Collabo025 (a1);
int status = TestMode::ReadTestModeValue (L"ModModeCollabo025");
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo025");
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
return originalAvailableMode_Collabo025 (a1);
}
HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_Collabo026 was called");
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo026 was called");
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
if (tournamentMode == 1) return originalAvailableMode_Collabo026 (a1);
int status = TestMode::ReadTestModeValue (L"ModModeCollabo026");
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo026");
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
return originalAvailableMode_Collabo026 (a1);
}
HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "AvailableMode_AprilFool001 was called");
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
LogMessage (LogLevel::HOOKS, "AvailableMode_AprilFool001 was called");
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
if (tournamentMode == 1) return originalAvailableMode_AprilFool001 (a1);
int status = TestMode::ReadTestModeValue (L"ModModeAprilFool001");
const int status = TestMode::ReadTestModeValue (L"ModModeAprilFool001");
if (status == 1) return lua_pushbool (a1, true);
return originalAvailableMode_AprilFool001 (a1);
}
i64 __fastcall lua_freeze_timer (i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "lua_freeze_timer was called");
int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
i64 __fastcall lua_freeze_timer (const i64 a1) {
LogMessage (LogLevel::HOOKS, "lua_freeze_timer was called");
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
if (tournamentMode == 1) return lua_pushbool (a1, true);
int status = TestMode::ReadTestModeValue (L"ModFreezeTimer");
const 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);
LogMessage (LogLevel::HOOKS, "FreezeTimer was called");
const auto a1 = ctx.rdi;
const int v9 = static_cast<int> (ctx.rax + 1);
lua_pushcclosure (a1, reinterpret_cast<i64> (&lua_freeze_timer), v9);
ctx.rip = ASLR (0x14019FF65);
}
@ -179,32 +176,31 @@ CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Collabo025_026, ASLR (0x1401789A
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AprilFool, ASLR (0x140176716), rax, 0x34, 0x06);
HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "GetLanguage was called");
auto result = originalGetLanguage (a1);
language = *((u32 *)result);
LogMessage (LogLevel::HOOKS, "GetLanguage was called");
const auto result = originalGetLanguage (a1);
language = *reinterpret_cast<u32 *> (result);
return result;
}
HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "GetRegionLanguage was called");
LogMessage (LogLevel::HOOKS, "GetRegionLanguage was called");
lua_settop (a1, 0);
lua_pushstring (a1, languageStr (language));
return 1;
}
HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) {
LogMessage (LOG_LEVEL_HOOKS, "GetCabinetLanguage was called");
LogMessage (LogLevel::HOOKS, "GetCabinetLanguage was called");
lua_settop (a2, 0);
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;
LogMessage (LogLevel::HOOKS, "ChangeLanguageType was called");
if (const auto pFontType = reinterpret_cast<int *> (ctx.rax); *pFontType == 4) *pFontType = 2;
}
MID_HOOK (CountLockedCrown, ASLR (0x1403F2A25), SafetyHookContext &ctx) {
LogMessage (LOG_LEVEL_HOOKS, "CountLockedCrown was called");
LogMessage (LogLevel::HOOKS, "CountLockedCrown was called");
ctx.r15 |= 1;
}
@ -215,8 +211,8 @@ bool enableSwitchVoice = false;
std::mutex nus3bankMtx;
int
get_bank_id (std::string bankName) {
if (nus3bankMap.find (bankName) == nus3bankMap.end ()) {
get_bank_id (const std::string &bankName) {
if (!nus3bankMap.contains (bankName)) {
nus3bankMap[bankName] = nus3bankIdCounter;
nus3bankIdCounter++;
}
@ -224,49 +220,49 @@ get_bank_id (std::string bankName) {
}
void
check_voice_tail (std::string bankName, uint8_t *pBinfBlock, std::map<std::string, bool> &voiceExist, std::string tail) {
check_voice_tail (const std::string &bankName, u8 *pBinfBlock, std::map<std::string, bool> &voiceExist, const std::string &tail) {
// check if any voice_xxx.nus3bank has xxx_cn audio inside while loading
if (enableSwitchVoice && bankName.starts_with ("voice_")) {
int binfLength = *((int *)(pBinfBlock + 4));
uint8_t *pGrpBlock = pBinfBlock + 8 + binfLength;
int grpLength = *((int *)(pGrpBlock + 4));
uint8_t *pDtonBlock = pGrpBlock + 8 + grpLength;
int dtonLength = *((int *)(pDtonBlock + 4));
uint8_t *pToneBlock = pDtonBlock + 8 + dtonLength;
int toneSize = *((int *)(pToneBlock + 8));
uint8_t *pToneBase = pToneBlock + 12;
const int binfLength = *reinterpret_cast<int *> (pBinfBlock + 4);
u8 *pGrpBlock = pBinfBlock + 8 + binfLength;
const int grpLength = *reinterpret_cast<int *> (pGrpBlock + 4);
u8 *pDtonBlock = pGrpBlock + 8 + grpLength;
const int dtonLength = *reinterpret_cast<int *> (pDtonBlock + 4);
u8 *pToneBlock = pDtonBlock + 8 + dtonLength;
const int toneSize = *reinterpret_cast<int *> (pToneBlock + 8);
u8 *pToneBase = pToneBlock + 12;
for (int i = 0; i < toneSize; i++) {
if (*((int *)(pToneBase + i * 8 + 4)) <= 0x0C) continue; // skip empty space
uint8_t *currToneBase = pToneBase + *((int *)(pToneBase + i * 8));
int titleOffset = -1;
if (*reinterpret_cast<int *> (pToneBase + i * 8 + 4) <= 0x0C) continue; // skip empty space
u8 *currToneBase = pToneBase + *reinterpret_cast<int *> (pToneBase + i * 8);
int titleOffset = -1;
switch (*currToneBase) {
case 0xFF: titleOffset = 9; break; // audio mark
case 0x7F: titleOffset = 5; break; // randomizer mark
default: continue; // unknown mark skip
}
if (titleOffset > 0) {
std::string title ((char *)(currToneBase + titleOffset));
std::string title (reinterpret_cast<char *> (currToneBase + titleOffset));
if (title.ends_with (tail)) {
if (voiceExist.find (bankName) == voiceExist.end () || !voiceExist[bankName]) voiceExist[bankName] = true;
if (!voiceExist.contains (bankName) || !voiceExist[bankName]) voiceExist[bankName] = true;
return;
}
}
}
if (voiceExist.find (bankName) == voiceExist.end () || voiceExist[bankName]) voiceExist[bankName] = false;
if (!voiceExist.contains (bankName) || voiceExist[bankName]) voiceExist[bankName] = false;
}
}
MID_HOOK (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) {
LogMessage (LOG_LEVEL_HOOKS, "GenNus3bankId was called");
LogMessage (LogLevel::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));
if (reinterpret_cast<u8 **> (ctx.rcx + 8) != nullptr) {
u8 *pNus3bankFile = *reinterpret_cast<u8 **> (ctx.rcx + 8);
if (pNus3bankFile[0] == 'N' && pNus3bankFile[1] == 'U' && pNus3bankFile[2] == 'S' && pNus3bankFile[3] == '3') {
int tocLength = *((int *)(pNus3bankFile + 16));
uint8_t *pPropBlock = pNus3bankFile + 20 + tocLength;
int propLength = *((int *)(pPropBlock + 4));
uint8_t *pBinfBlock = pPropBlock + 8 + propLength;
std::string bankName ((char *)(pBinfBlock + 0x11));
const int tocLength = *reinterpret_cast<int *> (pNus3bankFile + 16);
u8 *pPropBlock = pNus3bankFile + 20 + tocLength;
const int propLength = *reinterpret_cast<int *> (pPropBlock + 4);
u8 *pBinfBlock = pPropBlock + 8 + propLength;
const std::string bankName (reinterpret_cast<char *> (pBinfBlock + 0x11));
check_voice_tail (bankName, pBinfBlock, voiceCnExist, "_cn");
ctx.rax = get_bank_id (bankName);
}
@ -274,18 +270,18 @@ MID_HOOK (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) {
}
std::string
FixToneName (std::string bankName, std::string toneName) {
FixToneName (const std::string &bankName, std::string toneName) {
if (language == 2 || language == 4) {
if (voiceCnExist.find (bankName) != voiceCnExist.end () && voiceCnExist[bankName]) return toneName + "_cn";
if (voiceCnExist.contains (bankName) && voiceCnExist[bankName]) return toneName + "_cn";
}
return toneName;
}
size_t commonSize = 0;
HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "PlaySound was called");
LogMessage (LogLevel::HOOKS, "PlaySound was called");
if (enableSwitchVoice && language != 0) {
std::string bankName (lua_tolstring (a1, -3, &commonSize));
const std::string bankName (lua_tolstring (a1, -3, &commonSize));
if (bankName[0] == 'v') {
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize)).c_str ());
lua_replace (a1, -3);
@ -295,9 +291,9 @@ HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) {
}
HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundMulti was called");
LogMessage (LogLevel::HOOKS, "PlaySoundMulti was called");
if (enableSwitchVoice && language != 0) {
std::string bankName ((char *)lua_tolstring (a1, -3, &commonSize));
const std::string bankName (const_cast<char *> (lua_tolstring (a1, -3, &commonSize)));
if (bankName[0] == 'v') {
lua_pushstring (a1, FixToneName (bankName, lua_tolstring (a1, -2, &commonSize)).c_str ());
lua_replace (a1, -3);
@ -309,26 +305,26 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
FUNCTION_PTR (u64 *, append_chars_to_basic_string, ASLR (0x140028DA0), u64 *, const char *, size_t);
u64 *
FixToneNameEnso (u64 *Src, std::string &bankName) {
FixToneNameEnso (u64 *Src, const std::string &bankName) {
if (language == 2 || language == 4) {
if (voiceCnExist.find (bankName) != voiceCnExist.end () && voiceCnExist[bankName]) Src = append_chars_to_basic_string (Src, "_cn", 3);
if (voiceCnExist.contains (bankName) && voiceCnExist[bankName]) Src = append_chars_to_basic_string (Src, "_cn", 3);
}
return Src;
}
HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundEnso was called");
LogMessage (LogLevel::HOOKS, "PlaySoundEnso was called");
if (enableSwitchVoice && language != 0) {
std::string bankName = a1[3] > 0x10 ? std::string (*((char **)a1)) : std::string ((char *)a1);
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
}
return originalPlaySoundEnso (a1, a2, a3);
}
HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
LogMessage (LOG_LEVEL_HOOKS, "PlaySoundSpecial was called");
LogMessage (LogLevel::HOOKS, "PlaySoundSpecial was called");
if (enableSwitchVoice && language != 0) {
std::string bankName = a1[3] > 0x10 ? std::string (*((char **)a1)) : std::string ((char *)a1);
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName);
}
return originalPlaySoundSpecial (a1, a2);
@ -336,9 +332,9 @@ 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");
LogMessage (LogLevel::HOOKS, "LoadedBankAll was called");
originalLoadedBankAll (a1);
auto result = lua_toboolean (a1, -1);
const auto result = lua_toboolean (a1, -1);
lua_settop (a1, 0);
if (result) {
loaded_fail_count = 0;
@ -355,33 +351,33 @@ 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;
LogMessage (LogLevel::HOOKS, "SetMasterVolumeSpeaker was called");
soundRate = (float)(a1 <= 100 ? 1.0F : a1 / 100.0);
return originalSetMasterVolumeSpeaker (a1 > 100 ? 100 : a1);
}
HOOK (u64, NuscBusVolume, ASLR (0x1407B1C30), u64 a1, u64 a2, float a3) {
LogMessage (LOG_LEVEL_HOOKS, "NuscBusVolume was called");
LogMessage (LogLevel::HOOKS, "NuscBusVolume was called");
return originalNuscBusVolume (a1, a2, a3 * soundRate);
}
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");
LogMessage (LogLevel::HOOKS, "SetupFontInfo was called");
if (fontName != nullptr) delete fontName;
fontName = new std::string (((char *)a1) + 120);
fontName = new std::string (reinterpret_cast<char *> (a1) + 120);
return originalSetupFontInfo (a1, a2, a3, a4);
}
HOOK (u32, ReadFontInfoInt, ASLR (0x14049EAC0), u64 a1, u64 a2) {
LogMessage (LOG_LEVEL_HOOKS, "ReadFontInfoInt was called");
std::string attribute ((char *)a2);
LogMessage (LogLevel::HOOKS, "ReadFontInfoInt was called");
const std::string attribute (reinterpret_cast<char *> (a2));
u32 result = originalReadFontInfoInt (a1, a2);
if (fontName->starts_with ("cn_") && attribute == "offsetV") result += 1;
return result;
}
const i32 datatableBufferSize = 1024 * 1024 * 12;
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
safetyhook::Allocation datatableBuffer1;
safetyhook::Allocation datatableBuffer2;
safetyhook::Allocation datatableBuffer3;
@ -391,26 +387,26 @@ const std::vector<uintptr_t> datatableBuffer3Addresses = {0x1400ABF7F, 0x1400ABF
const std::vector<uintptr_t> memsetSizeAddresses = {0x1400ABE26, 0x1400ABE3A, 0x1400ABF79};
void
AllocateStaticBufferNear (void *target_address, size_t size, safetyhook::Allocation *newBuffer) {
auto allocator = safetyhook::Allocator::global ();
std::vector desired_addresses = {(uint8_t *)target_address};
auto allocation_result = allocator->allocate_near (desired_addresses, size);
AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) {
const auto allocator = safetyhook::Allocator::global ();
const std::vector desired_addresses = {static_cast<u8 *> (target_address)};
auto allocation_result = allocator->allocate_near (desired_addresses, size);
if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result);
}
void
ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *newBufferAddress) {
for (auto bufferAddress : bufferAddresses) {
uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
intptr_t offset = (intptr_t)newBufferAddress - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, (i32)offset);
for (const auto bufferAddress : bufferAddresses) {
const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
const intptr_t offset = reinterpret_cast<intptr_t> (newBufferAddress) - lea_instruction_end;
WRITE_MEMORY (lea_instruction_dst, i32, static_cast<i32> (offset));
}
}
void
Init () {
LogMessage (LOG_LEVEL_INFO, "Init JPN39 patches");
LogMessage (LogLevel::INFO, "Init JPN39 patches");
i32 xRes = 1920;
i32 yRes = 1080;
bool vsync = false;
@ -422,28 +418,23 @@ Init () {
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 patches = openConfigSection (config_ptr.get (), "patches");
if (patches) {
if (auto patches = openConfigSection (config_ptr.get (), "patches")) {
unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs);
auto jpn39 = openConfigSection (patches, "jpn39");
if (jpn39) {
if (auto jpn39 = openConfigSection (patches, "jpn39")) {
fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage);
chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch);
}
}
auto graphics = openConfigSection (config_ptr.get (), "graphics");
if (graphics) {
auto res = openConfigSection (graphics, "res");
if (res) {
xRes = readConfigInt (res, "x", xRes);
yRes = readConfigInt (res, "y", yRes);
if (auto graphics = openConfigSection (config_ptr.get (), "graphics")) {
if (auto res = openConfigSection (graphics, "res")) {
xRes = (i32)readConfigInt (res, "x", xRes);
yRes = (i32)readConfigInt (res, "y", yRes);
}
vsync = readConfigBool (graphics, "vsync", vsync);
}
auto layeredfs = openConfigSection (config_ptr.get (), "layeredfs");
if (layeredfs) useLayeredfs = readConfigBool (layeredfs, "enabled", useLayeredfs);
if (auto layeredfs = openConfigSection (config_ptr.get (), "layeredfs")) useLayeredfs = readConfigBool (layeredfs, "enabled", useLayeredfs);
}
// Hook to get AppAccessor and ComponentAccessor
@ -548,7 +539,7 @@ Init () {
// Unlimit Volume
TestMode::RegisterModify (
L"/root/menu[@id='SoundTestMenu']/layout[@type='Center']/select-item[@id='OutputLevelSpeakerItem']",
[&] (pugi::xml_node &node) {
[&] (const 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");
@ -589,7 +580,7 @@ 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\\");
@ -620,8 +611,8 @@ Init () {
INSTALL_HOOK (LoadedBankAll);
// Disable live check
auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll");
INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x42DE0));
auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x42DE0));
// Move various files to current directory
WRITE_MEMORY (amHandle + 0x15252, u8, 0xEB); // CreditLogPathA
@ -634,7 +625,7 @@ Init () {
WRITE_NOP (amHandle + 0x42167, 0x05); // BackupDataPathB
// Redirect garmc requests
auto garmcHandle = (u64)GetModuleHandle ("garmc.dll");
INSTALL_HOOK_DYNAMIC (curl_easy_setopt, (void *)(garmcHandle + 0x1FBBB0));
auto garmcHandle = reinterpret_cast<u64> (GetModuleHandle ("garmc.dll"));
INSTALL_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast<void *> (garmcHandle + 0x1FBBB0));
}
} // namespace patches::JPN39

View File

@ -1,12 +1,10 @@
#include "poll.h"
#include "helpers.h"
#include <windows.h>
extern bool jpLayout;
struct KeyCodePair {
const char *string;
uint8_t keycode;
u8 keycode;
};
size_t ConfigKeyboardButtonsCount = 0;
KeyCodePair *ConfigKeyboardButtons = nullptr;
@ -321,61 +319,65 @@ SDL_GameController *controllers[255];
void
SetKeyboardButtons () {
ConfigKeyboardButtonsCount = jpLayout ? COUNTOFARR (ConfigKeyboardButtons_JP) : COUNTOFARR (ConfigKeyboardButtons_US);
ConfigKeyboardButtons = (KeyCodePair *)malloc (ConfigKeyboardButtonsCount * sizeof (KeyCodePair));
ConfigKeyboardButtonsCount = jpLayout ? std::size (ConfigKeyboardButtons_JP) : std::size (ConfigKeyboardButtons_US);
ConfigKeyboardButtons = static_cast<KeyCodePair *> (malloc (ConfigKeyboardButtonsCount * sizeof (KeyCodePair)));
memcpy (ConfigKeyboardButtons, jpLayout ? ConfigKeyboardButtons_JP : ConfigKeyboardButtons_US, ConfigKeyboardButtonsCount * sizeof (KeyCodePair));
}
void
SetConfigValue (toml_table_t *table, const char *key, Keybindings *keybind) {
toml_array_t *array = toml_array_in (table, key);
SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind) {
const toml_array_t *array = toml_array_in (table, key);
if (!array) {
LogMessage (LOG_LEVEL_WARN, (std::string (key) + ": Cannot find array").c_str ());
LogMessage (LogLevel::WARN, std::string (key) + ": Cannot find array");
return;
}
memset (keybind, 0, sizeof (*keybind));
for (size_t i = 0; i < COUNTOFARR (keybind->buttons); i++)
keybind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID;
memset (key_bind, 0, sizeof (*key_bind));
for (size_t i = 0; i < std::size (key_bind->buttons); i++)
key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID;
for (size_t i = 0;; i++) {
toml_datum_t bind = toml_string_at (array, i);
if (!bind.ok) break;
ConfigValue value = StringToConfigEnum (bind.u.s);
free (bind.u.s);
for (int idx = 0;; idx++) {
const auto [ok, u] = toml_string_at (array, idx);
if (!ok) break;
const ConfigValue value = StringToConfigEnum (u.s);
free (u.s);
switch (value.type) {
case keycode:
for (size_t i = 0; i < COUNTOFARR (keybind->keycodes); i++) {
if (keybind->keycodes[i] == 0) {
keybind->keycodes[i] = value.keycode;
case keycode: {
for (int i = 0; i < std::size (key_bind->keycodes); i++) {
if (key_bind->keycodes[i] == 0) {
key_bind->keycodes[i] = value.keycode;
break;
}
}
break;
case button:
for (size_t i = 0; i < COUNTOFARR (keybind->buttons); i++) {
if (keybind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
keybind->buttons[i] = value.button;
}
case button: {
for (int i = 0; i < std::size (key_bind->buttons); i++) {
if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
key_bind->buttons[i] = value.button;
break;
}
}
break;
case axis:
for (size_t i = 0; i < COUNTOFARR (keybind->axis); i++) {
if (keybind->axis[i] == 0) {
keybind->axis[i] = value.axis;
}
case axis: {
for (int i = 0; i < std::size (key_bind->axis); i++) {
if (key_bind->axis[i] == 0) {
key_bind->axis[i] = value.axis;
break;
}
}
case scroll:
for (size_t i = 0; i < COUNTOFARR (keybind->scroll); i++) {
if (keybind->scroll[i] == 0) {
keybind->scroll[i] = value.scroll;
}
case scroll: {
for (int i = 0; i < std::size (key_bind->scroll); i++) {
if (key_bind->scroll[i] == 0) {
key_bind->scroll[i] = value.scroll;
break;
}
}
break;
}
default: break;
}
}
@ -395,16 +397,15 @@ InitializePoll (HWND windowHandle) {
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
hasRumble = false;
} else {
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 ());
LogMessage (LogLevel::ERROR,
std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
+ SDL_GetError ());
return false;
}
}
auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) LogMessage (LOG_LEVEL_ERROR, "Cannot read gamecontrollerdb.txt");
const auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt");
SDL_GameControllerEventState (SDL_ENABLE);
SDL_JoystickEventState (SDL_ENABLE);
@ -413,15 +414,14 @@ InitializePoll (HWND windowHandle) {
SDL_GameController *controller = SDL_GameControllerOpen (i);
if (!controller) {
LogMessage (LOG_LEVEL_WARN,
(std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ()).c_str ());
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ());
continue;
}
controllers[i] = controller;
}
window = SDL_CreateWindowFrom (windowHandle);
if (window == NULL) LogMessage (LOG_LEVEL_ERROR, (std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()).c_str ());
if (window == nullptr) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ());
atexit (DisposePoll);
return hasRumble;
@ -429,14 +429,14 @@ InitializePoll (HWND windowHandle) {
void
UpdatePoll (HWND windowHandle) {
if (windowHandle == NULL || GetForegroundWindow () != windowHandle) return;
if (windowHandle == nullptr || GetForegroundWindow () != windowHandle) return;
memcpy (lastKeyboardState, currentKeyboardState, 255);
memcpy (lastControllerButtonsState, currentControllerButtonsState, 21);
lastMouseState = currentMouseState;
lastControllerAxisState = currentControllerAxisState;
for (uint8_t i = 0; i < 0xFF; i++)
for (u8 i = 0; i < 0xFF; i++)
currentKeyboardState[i] = GetAsyncKeyState (i) != 0;
currentMouseState.ScrolledUp = false;
@ -454,9 +454,8 @@ UpdatePoll (HWND windowHandle) {
controller = SDL_GameControllerOpen (event.cdevice.which);
if (!controller) {
LogMessage (LOG_LEVEL_ERROR, (std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
+ ": " + SDL_GetError ())
.c_str ());
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
+ ": " + SDL_GetError ());
continue;
}
controllers[event.cdevice.which] = controller;
@ -474,19 +473,23 @@ UpdatePoll (HWND windowHandle) {
case SDL_CONTROLLERAXISMOTION:
if (event.caxis.value > 1) {
switch (event.caxis.axis) {
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = (float)event.caxis.value / 32767; break;
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = static_cast<float> (event.caxis.value) / 32767; break;
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = static_cast<float> (event.caxis.value) / 32767; break;
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = static_cast<float> (event.caxis.value) / 32767; break;
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = static_cast<float> (event.caxis.value) / 32767; break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = static_cast<float> (event.caxis.value) / 32767; break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
currentControllerAxisState.RTriggerDown = static_cast<float> (event.caxis.value) / 32767;
break;
default: break;
}
} else if (event.caxis.value < -1) {
switch (event.caxis.axis) {
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftLeft = (float)event.caxis.value / -32768; break;
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftUp = (float)event.caxis.value / -32768; break;
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightLeft = (float)event.caxis.value / -32768; break;
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightUp = (float)event.caxis.value / -32768; break;
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftLeft = static_cast<float> (event.caxis.value) / -32768; break;
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftUp = static_cast<float> (event.caxis.value) / -32768; break;
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightLeft = static_cast<float> (event.caxis.value) / -32768; break;
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightUp = static_cast<float> (event.caxis.value) / -32768; break;
default: break;
}
} else {
switch (event.caxis.axis) {
@ -508,9 +511,11 @@ UpdatePoll (HWND windowHandle) {
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = 0; break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = 0; break;
default: break;
}
}
break;
default: break;
}
}
}
@ -523,104 +528,105 @@ DisposePoll () {
ConfigValue
StringToConfigEnum (const char *value) {
ConfigValue rval;
ConfigValue rval{};
for (size_t i = 0; i < ConfigKeyboardButtonsCount; ++i)
if (!strcmp (value, ConfigKeyboardButtons[i].string)) {
rval.type = keycode;
rval.keycode = ConfigKeyboardButtons[i].keycode;
return rval;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerButtons); ++i)
if (!strcmp (value, ConfigControllerButtons[i].string)) {
for (const auto &[string, button_] : ConfigControllerButtons)
if (!strcmp (value, string)) {
rval.type = button;
rval.button = ConfigControllerButtons[i].button;
rval.button = button_;
return rval;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerAXIS); ++i)
if (!strcmp (value, ConfigControllerAXIS[i].string)) {
for (const auto &[string, axis_] : ConfigControllerAXIS)
if (!strcmp (value, string)) {
rval.type = axis;
rval.axis = ConfigControllerAXIS[i].axis;
rval.axis = axis_;
return rval;
}
for (size_t i = 0; i < COUNTOFARR (ConfigMouseScroll); ++i)
if (!strcmp (value, ConfigMouseScroll[i].string)) {
for (auto &[string, scroll_] : ConfigMouseScroll)
if (!strcmp (value, string)) {
rval.type = scroll;
rval.scroll = ConfigMouseScroll[i].scroll;
rval.scroll = scroll_;
return rval;
}
LogMessage (LOG_LEVEL_ERROR, (std::string (value) + ": Unknown value").c_str ());
LogMessage (LogLevel::ERROR, std::string (value) + ": Unknown value");
return rval;
}
InternalButtonState
GetInternalButtonState (Keybindings bindings) {
GetInternalButtonState (const Keybindings &bindings) {
InternalButtonState buttons = {0};
for (size_t i = 0; i < ConfigKeyboardButtonsCount; i++) {
if (bindings.keycodes[i] == 0) continue;
if (KeyboardIsReleased (bindings.keycodes[i])) buttons.Released = 1;
if (KeyboardIsReleased (bindings.keycodes[i])) buttons.Released = true;
if (KeyboardIsDown (bindings.keycodes[i])) buttons.Down = 1;
if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = 1;
if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = true;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerButtons); i++) {
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = 1;
if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = true;
if (ControllerButtonIsDown (bindings.buttons[i])) buttons.Down = 1;
if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = 1;
if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = true;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerAXIS); i++) {
for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) {
if (bindings.axis[i] == 0) continue;
if (float val = ControllerAxisIsReleased (bindings.axis[i])) buttons.Released = val;
if (float val = ControllerAxisIsDown (bindings.axis[i])) buttons.Down = val;
if (float val = ControllerAxisIsTapped (bindings.axis[i])) buttons.Tapped = val;
if (const float val = ControllerAxisIsReleased (bindings.axis[i]))
buttons.Released = static_cast<bool> (val); // NOLINT(*-narrowing-conversions)
if (const float val = ControllerAxisIsDown (bindings.axis[i])) buttons.Down = val; // NOLINT(*-narrowing-conversions)
if (const float val = ControllerAxisIsTapped (bindings.axis[i])) buttons.Tapped = static_cast<bool> (val); // NOLINT(*-narrowing-conversions)
}
for (size_t i = 0; i < COUNTOFARR (ConfigMouseScroll); i++) {
if (bindings.scroll[i] == 0) continue;
if (GetMouseScrollIsReleased (bindings.scroll[i])) buttons.Released = 1;
if (GetMouseScrollIsDown (bindings.scroll[i])) buttons.Down = 1;
if (GetMouseScrollIsTapped (bindings.scroll[i])) buttons.Tapped = 1;
for (const auto i : bindings.scroll) {
if (i == 0) continue;
if (GetMouseScrollIsReleased (i)) buttons.Released = true;
if (GetMouseScrollIsDown (i)) buttons.Down = 1;
if (GetMouseScrollIsTapped (i)) buttons.Tapped = true;
}
return buttons;
}
void
SetRumble (int left, int right, int length) {
for (size_t i = 0; i < COUNTOFARR (controllers); i++) {
if (!controllers[i] || !SDL_GameControllerHasRumble (controllers[i])) continue;
SetRumble (const int left, const int right, const int length) {
for (auto &controller : controllers) {
if (!controller || !SDL_GameControllerHasRumble (controller)) continue;
SDL_GameControllerRumble (controllers[i], left, right, length);
SDL_GameControllerRumble (controller, left, right, length);
}
}
bool
KeyboardIsDown (uint8_t keycode) {
KeyboardIsDown (const u8 keycode) {
return currentKeyboardState[keycode];
}
bool
KeyboardIsUp (uint8_t keycode) {
KeyboardIsUp (const u8 keycode) {
return !KeyboardIsDown (keycode);
}
bool
KeyboardIsTapped (uint8_t keycode) {
KeyboardIsTapped (const u8 keycode) {
return KeyboardIsDown (keycode) && KeyboardWasUp (keycode);
}
bool
KeyboardIsReleased (uint8_t keycode) {
KeyboardIsReleased (const u8 keycode) {
return KeyboardIsUp (keycode) && KeyboardWasDown (keycode);
}
bool
KeyboardWasDown (uint8_t keycode) {
KeyboardWasDown (const u8 keycode) {
return lastKeyboardState[keycode];
}
bool
KeyboardWasUp (uint8_t keycode) {
KeyboardWasUp (const u8 keycode) {
return !KeyboardWasDown (keycode);
}
@ -637,7 +643,7 @@ POINT
GetLastMouseRelativePosition () { return lastMouseState.RelativePosition; }
void
SetMousePosition (POINT newPosition) {
SetMousePosition (const POINT newPosition) {
currentMouseState.Position = newPosition;
}
@ -662,55 +668,55 @@ GetWasMouseScrollDown () {
}
bool
GetMouseScrollIsReleased (Scroll scroll) {
GetMouseScrollIsReleased (const Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return !GetMouseScrollUp () && GetWasMouseScrollUp ();
else return !GetMouseScrollDown () && GetWasMouseScrollDown ();
}
bool
GetMouseScrollIsDown (Scroll scroll) {
GetMouseScrollIsDown (const Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
else return GetMouseScrollDown ();
}
bool
GetMouseScrollIsTapped (Scroll scroll) {
GetMouseScrollIsTapped (const Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp () && !GetWasMouseScrollUp ();
else return GetMouseScrollDown () && !GetWasMouseScrollDown ();
}
bool
ControllerButtonIsDown (SDL_GameControllerButton button) {
ControllerButtonIsDown (const SDL_GameControllerButton button) {
return currentControllerButtonsState[button];
}
bool
ControllerButtonIsUp (SDL_GameControllerButton button) {
ControllerButtonIsUp (const SDL_GameControllerButton button) {
return !ControllerButtonIsDown (button);
}
bool
ControllerButtonWasDown (SDL_GameControllerButton button) {
ControllerButtonWasDown (const SDL_GameControllerButton button) {
return lastControllerButtonsState[button];
}
bool
ControllerButtonWasUp (SDL_GameControllerButton button) {
ControllerButtonWasUp (const SDL_GameControllerButton button) {
return !ControllerButtonWasDown (button);
}
bool
ControllerButtonIsTapped (SDL_GameControllerButton button) {
ControllerButtonIsTapped (const SDL_GameControllerButton button) {
return ControllerButtonIsDown (button) && ControllerButtonWasUp (button);
}
bool
ControllerButtonIsReleased (SDL_GameControllerButton button) {
ControllerButtonIsReleased (const SDL_GameControllerButton button) {
return ControllerButtonIsUp (button) && ControllerButtonWasDown (button);
}
float
ControllerAxisIsDown (SDLAxis axis) {
ControllerAxisIsDown (const SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT: return currentControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT: return currentControllerAxisState.LeftRight;
@ -727,12 +733,12 @@ ControllerAxisIsDown (SDLAxis axis) {
}
bool
ControllerAxisIsUp (SDLAxis axis) {
return !ControllerAxisIsDown (axis);
ControllerAxisIsUp (const SDLAxis axis) {
return !static_cast<bool> (ControllerAxisIsDown (axis));
}
float
ControllerAxisWasDown (SDLAxis axis) {
ControllerAxisWasDown (const SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT: return lastControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT: return lastControllerAxisState.LeftRight;
@ -749,31 +755,31 @@ ControllerAxisWasDown (SDLAxis axis) {
}
bool
ControllerAxisWasUp (SDLAxis axis) {
return !ControllerAxisWasDown (axis);
ControllerAxisWasUp (const SDLAxis axis) {
return !static_cast<bool> (ControllerAxisWasDown (axis));
}
bool
ControllerAxisIsTapped (SDLAxis axis) {
return ControllerAxisIsDown (axis) && ControllerAxisWasUp (axis);
ControllerAxisIsTapped (const SDLAxis axis) {
return static_cast<bool> (ControllerAxisIsDown (axis)) && ControllerAxisWasUp (axis);
}
bool
ControllerAxisIsReleased (SDLAxis axis) {
return ControllerAxisIsUp (axis) && ControllerAxisWasDown (axis);
ControllerAxisIsReleased (const SDLAxis axis) {
return ControllerAxisIsUp (axis) && static_cast<bool> (ControllerAxisWasDown (axis));
}
bool
IsButtonTapped (Keybindings bindings) {
IsButtonTapped (const Keybindings &bindings) {
return GetInternalButtonState (bindings).Tapped;
}
bool
IsButtonReleased (Keybindings bindings) {
IsButtonReleased (const Keybindings &bindings) {
return GetInternalButtonState (bindings).Released;
}
float
IsButtonDown (Keybindings bindings) {
IsButtonDown (const Keybindings &bindings) {
return GetInternalButtonState (bindings).Down;
}

View File

@ -1,9 +1,6 @@
#pragma once
#include <SDL.h>
#include <stdbool.h>
#include <stdint.h>
#include <toml.h>
#include <windows.h>
#include "helpers.h"
enum SDLAxis {
SDL_AXIS_NULL,
@ -36,7 +33,7 @@ struct SDLAxisState {
enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN };
struct Keybindings {
uint8_t keycodes[255];
u8 keycodes[255];
SDL_GameControllerButton buttons[255];
SDLAxis axis[255];
Scroll scroll[2];
@ -47,7 +44,7 @@ enum EnumType { none, keycode, button, axis, scroll };
struct ConfigValue {
EnumType type;
union {
uint8_t keycode;
u8 keycode;
SDL_GameControllerButton button;
SDLAxis axis;
Scroll scroll;
@ -65,16 +62,16 @@ void UpdatePoll (HWND windowHandle);
void DisposePoll ();
void SetKeyboardButtons ();
ConfigValue StringToConfigEnum (const char *value);
void SetConfigValue (toml_table_t *table, const char *key, Keybindings *keybind);
InternalButtonState GetInternalButtonState (Keybindings bindings);
void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind);
InternalButtonState GetInternalButtonState (const Keybindings &bindings);
void SetRumble (int left, int right, int length);
bool KeyboardIsDown (uint8_t keycode);
bool KeyboardIsUp (uint8_t keycode);
bool KeyboardIsTapped (uint8_t keycode);
bool KeyboardIsReleased (uint8_t keycode);
bool KeyboardWasDown (uint8_t keycode);
bool KeyboardWasUp (uint8_t keycode);
bool KeyboardIsDown (u8 keycode);
bool KeyboardIsUp (u8 keycode);
bool KeyboardIsTapped (u8 keycode);
bool KeyboardIsReleased (u8 keycode);
bool KeyboardWasDown (u8 keycode);
bool KeyboardWasUp (u8 keycode);
POINT GetMousePosition ();
POINT GetLastMousePosition ();
POINT GetMouseRelativePosition ();
@ -99,6 +96,6 @@ float ControllerAxisWasDown (SDLAxis axis);
bool ControllerAxisWasUp (SDLAxis axis);
bool ControllerAxisIsTapped (SDLAxis axis);
bool ControllerAxisIsReleased (SDLAxis axis);
bool IsButtonTapped (Keybindings bindings);
bool IsButtonReleased (Keybindings bindings);
float IsButtonDown (Keybindings bindings);
bool IsButtonTapped (const Keybindings &bindings);
bool IsButtonReleased (const Keybindings &bindings);
float IsButtonDown (const Keybindings &bindings);

View File

@ -1,13 +0,0 @@
[wrap-file]
directory = libtomcrypt-1.18.2
source_url = https://github.com/libtom/libtomcrypt/releases/download/v1.18.2/crypt-1.18.2.tar.xz
source_filename = crypt-1.18.2.tar.xz
source_hash = 96ad4c3b8336050993c5bc2cf6c057484f2b0f9f763448151567fbab5e767b84
patch_filename = libtomcrypt_1.18.2-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/libtomcrypt_1.18.2-1/get_patch
patch_hash = 0ca889b864e5a23525774438439d9e385268ff7234d49029902375a6c5e18f14
diff_files = libtomcrypt.patch
[provide]
libtomcrypt = tomcrypt_dep

View File

@ -1,4 +0,0 @@
[wrap-git]
url = https://github.com/TsudaKageyu/minhook.git
revision = master
diff_files = minhook.patch

View File

@ -1,11 +0,0 @@
--- libtomcrypt-1.18.2/meson.build
+++ libtomcrypt-1.18.2/meson.build
@@ -14,7 +14,7 @@ extra_objects = []
subdir('src')
-tomcryptlib = library('tomcrypt', all_sources,
+tomcryptlib = static_library('tomcrypt', all_sources,
objects : extra_objects,
include_directories : core_inc)

View File

@ -1,21 +0,0 @@
--- minhook/meson.build
+++ minhook/meson.build
@@ -0,0 +1,18 @@
+project('minhook', 'c', version: '1.0.0')
+
+minhook_inc = include_directories('include')
+minhook_lib = static_library(
+ 'minhook',
+ include_directories: minhook_inc,
+ sources: [
+ 'src/buffer.c',
+ 'src/hook.c',
+ 'src/trampoline.c',
+ 'src/hde/hde32.c',
+ 'src/hde/hde64.c'
+ ]
+)
+minhook_dep = declare_dependency(
+ link_with: minhook_lib,
+ include_directories: minhook_inc,
+)

View File

@ -1,6 +0,0 @@
project('stb', 'cpp')
depinc = include_directories('.')
stb_dep = declare_dependency(
include_directories: depinc,
)

View File

@ -1,15 +0,0 @@
--- tomlc99/meson.build
+++ tomlc99/meson.build
@@ -0,0 +1,12 @@
+project('tomlc99', 'c', version: '1.0.0')
+
+tomlc99_inc = include_directories('.')
+tomlc99_lib = static_library(
+ 'tomlc99',
+ include_directories: tomlc99_inc,
+ sources: ['toml.c']
+)
+tomlc99_dep = declare_dependency(
+ link_with: tomlc99_lib,
+ include_directories: tomlc99_inc,
+)

View File

@ -1,33 +0,0 @@
+++ zlib/meson.build
@@ -0,0 +1,31 @@
+project('zlib', 'c', version: '1.0.0')
+
+zlib_inc = include_directories('.')
+zlib_sources = files(
+ 'adler32.c',
+ 'compress.c',
+ 'crc32.c',
+ 'deflate.c',
+ 'gzclose.c',
+ 'gzlib.c',
+ 'gzread.c',
+ 'gzwrite.c',
+ 'infback.c',
+ 'inffast.c',
+ 'inflate.c',
+ 'inftrees.c',
+ 'trees.c',
+ 'uncompr.c',
+ 'zutil.c'
+)
+
+zlib_lib = static_library(
+ 'zlib',
+ zlib_sources,
+ include_directories: zlib_inc
+)
+
+zlib_dep = declare_dependency(
+ include_directories: zlib_inc,
+ link_with: zlib_lib
+)

View File

@ -1,10 +0,0 @@
[wrap-file]
directory = pugixml-1.14
source_url = https://github.com/zeux/pugixml/archive/v1.14.tar.gz
source_filename = pugixml-1.14.tar.gz
source_hash = 610f98375424b5614754a6f34a491adbddaaec074e9044577d965160ec103d2e
method = cmake
[provide]
pugixml = pugixml_static_dep

View File

@ -1,7 +0,0 @@
[wrap-git]
url = https://github.com/cursey/safetyhook.git
revision = v0.4.1
method = cmake
[provide]
safetyhook = safetyhook_dep

View File

@ -1,15 +0,0 @@
[wrap-file]
directory = SDL2-2.26.5
source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.26.5/SDL2-2.26.5.tar.gz
source_filename = SDL2-2.26.5.tar.gz
source_hash = ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7
patch_filename = sdl2_2.26.5-5_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.26.5-5/get_patch
patch_hash = 4d8d3ae534c326f27b2d97616fdfa7cce41bd0333c7d9683dd8ae39d4ad70e6a
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.26.5-5/SDL2-2.26.5.tar.gz
wrapdb_version = 2.26.5-5
[provide]
sdl2 = sdl2_dep
sdl2main = sdl2main_dep
sdl2_test = sdl2_test_dep

View File

@ -1,8 +0,0 @@
[wrap-git]
directory=stb
url=https://github.com/nothings/stb.git
revision=head
patch_directory = stb
[provide]
stb = stb_dep

View File

@ -1,4 +0,0 @@
[wrap-git]
url = https://github.com/cktan/tomlc99.git
revision = master
diff_files = tomlc99.patch

View File

@ -1,13 +0,0 @@
[wrap-file]
directory = xxHash-0.8.2
source_url = https://github.com/Cyan4973/xxHash/archive/v0.8.2.tar.gz
source_filename = xxHash-0.8.2.tar.gz
source_hash = baee0c6afd4f03165de7a4e67988d16f0f2b257b51d0e3cb91909302a26a79c4
patch_filename = xxhash_0.8.2-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/xxhash_0.8.2-1/get_patch
patch_hash = e721ef7a4c4ee0ade8b8440f6f7cb9f935b68e825249d74cb1c2503c53e68d25
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/xxhash_0.8.2-1/xxHash-0.8.2.tar.gz
wrapdb_version = 0.8.2-1
[provide]
libxxhash = xxhash_dep

View File

@ -1,4 +0,0 @@
[wrap-git]
url = https://github.com/madler/zlib
revision = 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf
diff_files = zlib.patch

View File

@ -1,11 +0,0 @@
[wrap-file]
directory=zxing-cpp-2.2.1
source_url=https://github.com/zxing-cpp/zxing-cpp/archive/refs/tags/v2.2.1.zip
source_filename=zxing-cpp-2.2.1.zip
source_hash=71d9288f0637d321ee6823d8c27e684e9a00d4ffb92f18aff95fb5342cb6521d
method = cmake
[provide]
ZXing=ZXing_dep