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:
parent
b5d9488df6
commit
91a9f9ad25
@ -11,6 +11,7 @@ AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: True
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
SpaceAfterTemplateKeyword: True
|
||||
SpacesInAngles: Never
|
||||
|
@ -1,3 +1,5 @@
|
||||
[*]
|
||||
indent_style = tab
|
||||
charset = utf-8
|
||||
end_of_line = crlf
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
35
.github/workflows/build.yml
vendored
35
.github/workflows/build.yml
vendored
@ -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
136
.gitignore
vendored
@ -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
234
CMakeLists.txt
Normal 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"
|
||||
)
|
26
Makefile
26
Makefile
@ -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
|
11
PLUGINS.md
11
PLUGINS.md
@ -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()
|
||||
|
26
README.md
26
README.md
@ -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.
|
||||
|
@ -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
47
exports.def
Normal 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
|
101
meson.build
101
meson.build
@ -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: ''
|
||||
)
|
153
src/bnusio.cpp
153
src/bnusio.cpp
@ -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 ();
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
namespace bnusio {
|
||||
void Init ();
|
||||
void Update ();
|
||||
|
@ -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);
|
||||
|
130
src/helpers.cpp
130
src/helpers.cpp
@ -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 §ionName) {
|
||||
openConfigSection (const toml_table_t *config, const std::string §ionName) {
|
||||
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 ¬FoundValue) {
|
||||
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 ¬FoundValue) {
|
||||
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;
|
||||
|
@ -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 §ionName);
|
||||
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 ¬FoundValue);
|
||||
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 §ionName);
|
||||
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 ¬FoundValue);
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
112
src/logger.h
112
src/logger.h
@ -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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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 ());
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ¤tFileName) -> 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
|
||||
|
236
src/poll.cpp
236
src/poll.cpp
@ -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;
|
||||
}
|
||||
|
31
src/poll.h
31
src/poll.h
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/TsudaKageyu/minhook.git
|
||||
revision = master
|
||||
diff_files = minhook.patch
|
@ -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)
|
||||
|
@ -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,
|
||||
+)
|
@ -1,6 +0,0 @@
|
||||
project('stb', 'cpp')
|
||||
|
||||
depinc = include_directories('.')
|
||||
stb_dep = declare_dependency(
|
||||
include_directories: depinc,
|
||||
)
|
@ -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,
|
||||
+)
|
@ -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
|
||||
+)
|
@ -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
|
@ -1,7 +0,0 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/cursey/safetyhook.git
|
||||
revision = v0.4.1
|
||||
method = cmake
|
||||
|
||||
[provide]
|
||||
safetyhook = safetyhook_dep
|
@ -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
|
@ -1,8 +0,0 @@
|
||||
[wrap-git]
|
||||
directory=stb
|
||||
url=https://github.com/nothings/stb.git
|
||||
revision=head
|
||||
patch_directory = stb
|
||||
|
||||
[provide]
|
||||
stb = stb_dep
|
@ -1,4 +0,0 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/cktan/tomlc99.git
|
||||
revision = master
|
||||
diff_files = tomlc99.patch
|
@ -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
|
@ -1,4 +0,0 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/madler/zlib
|
||||
revision = 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf
|
||||
diff_files = zlib.patch
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user