1
1
mirror of synced 2025-01-19 09:07:28 +01:00

Initial refactor

cards.dat has been replaced with cards.ini
there are no more plugins though plugin support still exists
card reading is not yet implemented
08.18/amauth support is not yet implemented
This commit is contained in:
BroGamer 2023-09-10 17:50:00 +12:00
parent 4ff4324cb1
commit b119478ce3
40 changed files with 3389 additions and 3675 deletions

View File

@ -1,13 +1,21 @@
BasedOnStyle: GNU
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: ForIndentation
IndentCaseLabels: False
BreakBeforeBraces: Attach
ColumnLimit: 150
ColumnLimit: 200
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveMacros: Consecutive
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: True
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AlwaysBreakTemplateDeclarations: Yes
SpaceAfterTemplateKeyword: True
SpacesInAngles: Never
SpaceBeforeParens: Always
AlwaysBreakAfterReturnType: TopLevelDefinitions
RemoveBracesLLVM: True
AlignEscapedNewlines: Left
AccessModifierOffset: -4

View File

@ -1,5 +1,3 @@
root = true
[*]
indent_style = tab
indent_size = 4
indent_size = 4

View File

@ -4,15 +4,15 @@ on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Install depends
run: sudo apt-get install -y mingw-w64 clang
run: sudo apt-get install -y mingw-w64 ninja-build nasm; pip3 install meson
- name: Make
run: make dist-no-7z
run: make setup dist-no-7z
- uses: actions/upload-artifact@v3
with:
name: dist

13
.gitignore vendored
View File

@ -1,6 +1,9 @@
x86_64-pc-windows
*.o
*.dll
*.7z
.cache
build/
compile_commands.json
.cache
subprojects/minhook
subprojects/packagecache
subprojects/tomlc99
subprojects/SDL2-2.26.5
subprojects/xxHash-0.8.2
dist.7z

9
.gitmodules vendored
View File

@ -1,9 +0,0 @@
[submodule "minhook"]
path = minhook
url = https://github.com/TsudaKageyu/minhook
[submodule "SDL"]
path = SDL
url = https://github.com/libsdl-org/SDL
[submodule "tomlc99"]
path = tomlc99
url = https://github.com/cktan/tomlc99

View File

@ -1,66 +1,15 @@
OUT = TAL
CC = x86_64-w64-mingw32-gcc
TARGET = x86_64-pc-windows-gnu
SRC = src/dllmain.c src/helpers.c src/poll.c src/boilerplate.c tomlc99/toml.c minhook/src/buffer.c minhook/src/hook.c minhook/src/trampoline.c minhook/src/hde/hde32.c minhook/src/hde/hde64.c
OBJ = ${addprefix ${TARGET}/,${SRC:.c=.o}}
CFLAGS = -std=c99 -Iminhook/include -ISDL/include -ISDL/build/include -Itomlc99 -Wall -Ofast -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=_WIN32_WINNT_WIN7
LDFLAGS = -shared -static -static-libgcc -s
LIBS = SDL/build/libSDL3.a SDL/build/libSDL3_main.a -lmingw32 -luuid -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lsetupapi -lversion
DEPS = SDL
all: options ${OUT} plugins
.PHONY: dirs
dirs:
@mkdir -p ${TARGET}/src
@mkdir -p ${TARGET}/minhook/src/hde
@mkdir -p ${TARGET}/tomlc99
.PHONY: options
options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
${TARGET}/%.o: %.c
@echo BUILD $@
@${CC} -c ${CFLAGS} $< -o $@
.PHONY: SDL
SDL:
@cd SDL && cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=build-scripts/cmake-toolchain-mingw64-x86_64.cmake && cmake --build build
.PHONY: ${OUT}
${OUT}: dirs ${DEPS} ${OBJ}
@echo LINK $@
@${CC} ${CFLAGS} -o ${TARGET}/$@.dll ${OBJ} ${LDFLAGS} ${LIBS}
.PHONY: fmt
fmt:
@cd src && clang-format -i *.h *.c -style=file
@cd plugins/8.18 && clang-format -i *.c -style=file
@cd plugins/amauth && clang-format -i *.c -style=file
.PHONY: clean
clean:
rm -rf ${TARGET}
.PHONY: plugins
plugins:
make -C plugins/8.18
make -C plugins/amauth
strip ${TARGET}/*.dll
.PHONY: dist-no-7z
dist-no-7z: options ${OUT} plugins
mkdir -p out/plugins
cp ${TARGET}/${OUT}.dll out/
mv out/${OUT}.dll out/bnusio.dll
cp ${TARGET}/patches.*.dll out/plugins
cp ${TARGET}/amauth.dll out/plugins
cp -r dist/* out/
.PHONY: dist
dist: dist-no-7z
cd out && 7z a -t7z ../${OUT}.7z .
rm -rf out
all:
@meson compile -C build
@strip build/bnusio.dll
setup:
@meson setup build --cross cross-mingw-64.txt
dist-no-7z: all
@mkdir -p out/
@cp build/bnusio.dll out/
@cp -r dist/* out/
dist: dist-no-7z
@cd out && 7z a -t7z ../dist.7z .
@rm -rf out

View File

@ -2,10 +2,6 @@
Plugins are just libraries with certain exported functions that go in the plugins folder.
```
void PreInit()
```
Runs in dllmain, may run into loader locks. You can also just use your own dllmain for this but that involves writing out all the arguments.
```
void Init()
```
@ -30,18 +26,7 @@ callback(0, 0, cardData, data);
```
```
void Card1Insert()
void CardInsert()
```
Runs when user presses CARD_INSERT_1, causes TAL to not insert a card if any plugins have this present
```
void Card2Insert()
```
Runs when user presses CARD_INSERT_2, causes TAL to not insert a card if any plugins have this present
```
void BeforeCard1Insert()
```
Runs before CARD_INSERT_1 is handled
```
void BeforeCard2Insert()
```
Runs before CARD_INSERT_2 is handled
Runs when user presses CARD_INSERT, causes TAL to not insert a card if any plugins have this present
void BeforeCardInsert()

1
SDL

@ -1 +0,0 @@
Subproject commit 180afcdf3998e5175b744d3f2d87147802809450

12
cross-mingw-64.txt Normal file
View File

@ -0,0 +1,12 @@
[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'
nasm = 'nasm'
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

11
dist/config.toml vendored
View File

@ -1,6 +1,5 @@
# Values for random drum hit amounts
drumMax = 20000
drumMin = 10000
server = "127.0.0.1"
pcb_id = "TAL0000001"
server = "127.0.0.1"
res = { x = 1360, y = 768 }
unlock_songs = true
shared_audio = true
vsync = false

File diff suppressed because it is too large Load Diff

3
dist/keyconfig.toml vendored
View File

@ -7,8 +7,7 @@ DEBUG_DOWN = ["DOWNARROW"]
DEBUG_ENTER = ["ENTER"]
COIN_ADD = ["ENTER", "SDL_START"]
CARD_INSERT_1 = ["P"]
CARD_INSERT_2 = []
CARD_INSERT = ["P"]
P1_LEFT_BLUE = ["D", "SDL_LTRIGGER"]
P1_LEFT_RED = ["F", "SDL_LSTICK_PRESS"]

View File

@ -1,4 +0,0 @@
unlock_songs = true
shared_audio = true
vsync = false
windowRes = { x = 1920, y = 1080 }

59
meson.build Normal file
View File

@ -0,0 +1,59 @@
project('TaikoArcadeLoader', 'c', 'cpp', 'nasm', version: '1.0.0')
warning_level = 3
debug = true
optimization = 3
b_lto = true
b_pgo = 'use'
cpp_std = 'c++20'
cpp = meson.get_compiler('cpp')
add_project_arguments(
cpp.get_supported_arguments(
'-D_WIN32_WINNT=_WIN32_WINNT_WIN10',
'-std=c++20',
'-Werror',
),
language: 'cpp',
)
add_project_link_arguments(
cpp.get_supported_arguments(
'-static',
#'-s',
'-lws2_32',
'-lssp',
),
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'])
library(
'bnusio',
link_with: [
minhook.get_variable('minhook_lib'),
tomlc99.get_variable('tomlc99_lib'),
sdl2.get_variable('sdl2'),
xxhash.get_variable('xxhash'),
],
include_directories: [
'src',
minhook.get_variable('minhook_inc'),
tomlc99.get_variable('tomlc99_inc'),
sdl2.get_variable('core_inc'),
xxhash.get_variable('inc'),
],
sources : [
'src/dllmain.cpp',
'src/helpers.cpp',
'src/poll.cpp',
'src/bnusio.cpp',
'src/patches/jp_nov_2020.cpp',
'src/patches/cn_jun_2023.cpp',
],
name_prefix: ''
)

@ -1 +0,0 @@
Subproject commit 426cb6880035ee3cceed05384bb3f2db01a20a15

View File

@ -1,31 +0,0 @@
OUT = patches.8.18
CC = clang
TARGET = x86_64-pc-windows-gnu
SRC = dllmain.c
OBJ = ${addprefix ../../${TARGET}/plugins/8.18/,${SRC:.c=.o}}
EXTERN_SRC = src/helpers.c tomlc99/toml.c minhook/src/buffer.c minhook/src/hook.c minhook/src/trampoline.c minhook/src/hde/hde32.c minhook/src/hde/hde64.c
EXTERN_OBJ = ${addprefix ../../${TARGET}/,${EXTERN_SRC:.c=.o}}
CFLAGS = -std=c99 -I../../src -I../../minhook/include -I../../tomlc99 -Wall -Ofast -target ${TARGET} -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=_WIN32_WINNT_WIN7
LDFLAGS = -shared -static -static-libgcc -s
LIBS = -lmingw32 -luuid -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lsetupapi -lversion
all: options ${OUT}
.PHONY: dirs
dirs:
@mkdir -p ../../${TARGET}/plugins/8.18
.PHONY: options
options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
../../${TARGET}/plugins/8.18/%.o: %.c
@echo BUILD $@
@${CC} -c ${CFLAGS} $< -o $@
.PHONY: ${OUT}
${OUT}: dirs ${OBJ}
@echo LINK $@
@${CC} ${CFLAGS} -o ../../${TARGET}/$@.dll ${OBJ} ${EXTERN_OBJ} ${LDFLAGS} ${LIBS}

View File

@ -1,137 +0,0 @@
#define BASE_ADDRESS 0x140000000
#include "helpers.h"
const u64 song_data_size = 1024 * 1024 * 64;
void *song_data;
#define RDX_MOV 0x48, 0xBA
#define R8_MOV 0x49, 0xB8
#define GENERATE_MOV(instruction, location) \
instruction, (u8)(u64)(location), (u8)((u64)(location) >> 8), (u8)((u64)(location) >> 16), (u8)((u64)(location) >> 24), \
(u8)((u64)(location) >> 32), (u8)((u64)(location) >> 40), (u8)((u64)(location) >> 48), (u8)((u64)(location) >> 56)
HOOK_DYNAMIC (u8, __fastcall, qrVtable1, u64 a1) { return 1; }
HOOK_DYNAMIC (u8, __fastcall, qrReadFromCOM1, u64 a1) {
*(u32 *)(a1 + 40) = 1;
*(u32 *)(a1 + 16) = 1;
return 1;
}
void
PreInit () {
toml_table_t *config = openConfig (configPath ("plugins/patches.toml"));
if (!config) return;
void *handle = GetModuleHandle (0);
WRITE_MEMORY (ASLR (0x1400239C0, handle), u8, 0xC3); // Stop error
if (readConfigBool (config, "unlock_songs", true)) WRITE_MEMORY (ASLR (0x140314E8D, handle), u8, 0xB0, 0x01); // Unlock songs
if (readConfigBool (config, "shared_audio", true)) WRITE_MEMORY (ASLR (0x140692E17, handle), u8, 0xEB); // Shared audio
if (!readConfigBool (config, "vsync", false)) WRITE_MEMORY (ASLR (0x140517339, handle), u8, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x90); // Disable VSync
// Remove song limit
WRITE_MEMORY (ASLR (0x140313726, handle), i32, 9000);
// Remove for with server
WRITE_MEMORY (ASLR (0x1402F39E6, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1402F3AB0, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1402F3BE4, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x14030643B, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140306507, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403065D3, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403066FB, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403067C7, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140306893, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x14030698B, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140313666, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403139F4, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140313B04, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140313C24, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140313CF4, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403140C4, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1403147AA, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140225FB6, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140226146, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314DCC, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314EC9, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140338E2C, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1400EE0A4, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1400EE8B5, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1400EEDA6, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140315608, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x14034A7EB, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x1402F3CB3, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314059, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140226063, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x14022609F, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140226296, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140306A2E, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314F46, handle), i32, 9000);
WRITE_MEMORY (ASLR (0x140314F97, handle), i32, 9000);
song_data = malloc (song_data_size);
memset (song_data, 0, song_data_size);
// Song data
WRITE_MEMORY (ASLR (0x14031367B, handle), u8, GENERATE_MOV (R8_MOV, song_data));
// Crown data
WRITE_MEMORY (ASLR (0x1402F3AC6, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1402F39FC, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1402F3BFA, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1403140D7, handle), u8, GENERATE_MOV (R8_MOV, song_data));
// Score ranks
WRITE_MEMORY (ASLR (0x1403065EA, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x14030651E, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140306452, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1403068AA, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1403067DE, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140306712, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x1403069A2, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
// Unknown
WRITE_MEMORY (ASLR (0x140313755, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140313A0B, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140313B4C, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140313D38, handle), u8, GENERATE_MOV (RDX_MOV, song_data));
WRITE_MEMORY (ASLR (0x140313C42, handle), u8, GENERATE_MOV (R8_MOV, song_data));
// Save settings cross session without F:/ and G:/ drive
WRITE_MEMORY (ASLR (0x140B5C528, handle), char, "./Setting1.bin");
WRITE_MEMORY (ASLR (0x140B5C538, handle), char, "./Setting2.bin");
// Move F:/ files to current directory
WRITE_MEMORY (ASLR (0x140B1B4B0, handle), char, "./");
WRITE_MEMORY (ASLR (0x14001C941, handle), u8, 0x02);
// Patch TLS v1.0 to v1.2
WRITE_MEMORY (ASLR (0x14044B1A9, handle), u8, 0x10);
toml_table_t *windowResSection = openConfigSection (config, "windowRes");
if (windowResSection) {
i32 windowResX = readConfigInt (windowResSection, "x", 0);
i32 windowResY = readConfigInt (windowResSection, "y", 0);
if (windowResX > 0 && windowResY > 0) {
WRITE_MEMORY (ASLR (0x14035FC5B, handle), i32, windowResX);
WRITE_MEMORY (ASLR (0x14035FC62, handle), i32, windowResY);
}
}
toml_free (config);
// Move various files to current directory
void *amHandle = GetModuleHandle ("AMFrameWork.dll");
WRITE_MEMORY (amHandle + 0x33EF7, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x3404A, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x34429, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x3457C, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x3497A, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x34ACD, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x148AF, u8, 0xEB);
WRITE_MEMORY (amHandle + 0x14A1A, u8, 0xEB);
INSTALL_HOOK_DYNAMIC (qrVtable1, amHandle + 0x1BA00);
INSTALL_HOOK_DYNAMIC (qrReadFromCOM1, amHandle + 0x1BC20);
}
void
BeforeCard1Insert () {
memset (song_data, 0, song_data_size);
}
void
BeforeCard2Insert () {
memset (song_data, 0, song_data_size);
}

View File

@ -1,31 +0,0 @@
OUT = amauth
CXX := x86_64-w64-mingw32-g++
TARGET := x86_64-pc-windows-gnu
SRC = dllmain.cpp
OBJ = ${addprefix ../../${TARGET}/plugins/amauth/,${SRC:.cpp=.o}}
EXTERN_SRC = src/helpers.c tomlc99/toml.c minhook/src/buffer.c minhook/src/hook.c minhook/src/trampoline.c minhook/src/hde/hde32.c minhook/src/hde/hde64.c
EXTERN_OBJ = ${addprefix ../../${TARGET}/,${EXTERN_SRC:.c=.o}}
CXXFLAGS = -std=c++11 -I../../src -I../../minhook/include -I../../tomlc99 -Wall -Ofast -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=_WIN32_WINNT_WIN7
LDFLAGS := -shared -static -static-libgcc -s
LIBS := -lmingw32 -luuid -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lsetupapi -lversion -lws2_32
all: options ${OUT}
.PHONY: dirs
dirs:
@mkdir -p ../../${TARGET}/plugins/amauth
.PHONY: options
options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CXX = ${CXX}"
../../${TARGET}/plugins/amauth/%.o: %.cpp
@echo BUILD $@
@${CXX} -c ${CXXFLAGS} $< -o $@
.PHONY: ${OUT}
${OUT}: dirs ${OBJ}
@echo LINK $@
@${CXX} ${CXXFLAGS} -o ../../${TARGET}/$@.dll ${OBJ} ${EXTERN_OBJ} ${LDFLAGS} ${LIBS}

View File

@ -1,363 +0,0 @@
// Here be lions
// The following code is shit
// It attempts to recreate the functionality of AMAuthd
// However some of this functionality is needless
#include <unknwn.h>
#include <ws2tcpip.h>
// Needs to be after for DEFINE_GUID
#include "helpers.h"
DWORD reg = 0;
char server_ip[0x10];
char *server_hostname = (char *)"127.0.0.1";
char *pcb_id = (char *)"TAL0000001";
DEFINE_GUID (IID_CAuthFactory, 0x4603BB03, 0x058D, 0x43D9, 0xB9, 0x6F, 0x63, 0x9B, 0xE9, 0x08, 0xC1, 0xED);
DEFINE_GUID (IID_CAuth, 0x045A5150, 0xD2B3, 0x4590, 0xA3, 0x8B, 0xC1, 0x15, 0x86, 0x78, 0xE1, 0xAC);
class CAuth : public IUnknown {
public:
STDMETHODIMP
QueryInterface (REFIID riid, LPVOID *ppvObj) {
wchar_t *iid_str;
StringFromCLSID (riid, &iid_str);
printf ("QueryInterface %ls\n", iid_str);
if (riid == IID_IUnknown || riid == IID_CAuth) {
*ppvObj = this;
this->AddRef ();
return 0;
} else {
*ppvObj = 0;
return E_NOINTERFACE;
}
}
STDMETHODIMP_ (ULONG) AddRef () { return this->refCount++; }
STDMETHODIMP_ (ULONG) Release () {
this->refCount--;
if (this->refCount <= 0) {
// delete this;
return 0;
}
return this->refCount;
}
virtual i64
Unk3 (u32 a1) {
return 1;
}
virtual i64
Unk4 () {
return 1;
}
virtual i32
Unk5 () {
return 0;
}
virtual i64
Unk6 () {
return 1;
}
virtual i32
Unk7 () {
return 0;
}
virtual i32
Unk8 () {
return 0;
}
virtual i32
Unk9 (i32 *a1) {
memset (a1, 0, sizeof (i32) * 0x31);
a1[0] = 15;
a1[2] = 2;
a1[3] = 1;
a1[6] = 9;
a1[8] = 2;
a1[9] = 1;
a1[10] = 27;
a1[11] = 33;
a1[12] = 41;
a1[13] = 50;
a1[14] = 59;
a1[15] = 1179656;
a1[30] = 1;
a1[46] = 1;
a1[47] = 3;
a1[48] = 9;
return 0;
}
virtual i32
Unk10 (char *a1) {
memset (a1, 0, 0xB0);
strncpy_s (a1, 0x10, "STANDALONE", 0xF);
strncpy_s (a1 + 0x10, 0x10, pcb_id, 0xF); // PCB ID
strncpy_s (a1 + 0x20, 0x10, "000000-00000", 0xF); // ignored by game
strncpy_s (a1 + 0x30, 0x10, server_ip, 0xF);
strncpy_s (a1 + 0x40, 0x10, server_ip, 0xF);
strncpy_s (a1 + 0x50, 0x10, server_ip, 0xF);
strncpy_s (a1 + 0x60, 0x10, "***.***.***.***", 0xF); // Subnet mask
strncpy_s (a1 + 0x70, 0x10, "***.***.***.***", 0xF); // GATEWAY
strncpy_s (a1 + 0x80, 0x10, "***.***.***.***", 0xF); // PRIMARY DNS
return 0;
}
virtual i32
Unk11 (char *a1) {
memset (a1, 0, 0x13C);
strncpy_s (a1, 4, "1", 3);
strncpy_s (a1 + 4, 0x10, "ALLNET", 0xF);
strncpy_s (a1 + 20, 8, "SBWY", 7);
strncpy_s (a1 + 28, 8, "12.00", 7);
strncpy_s (a1 + 36, 8, "TAL0", 7); // ignored by game
strncpy_s (a1 + 44, 8, "08.18", 7); // GAME VERSION
strncpy_s (a1 + 52, 4, "0", 3);
strncpy_s (a1 + 56, 4, "PCB", 3);
return 0;
}
virtual i32
Unk12 () {
return 1;
}
virtual i32
Unk13 () {
return 1;
}
virtual i32
Unk14 (char *a1) {
memset (a1, 0, 0x8A2);
strncpy_s (a1, 0x101, server_hostname, 0x100);
strncpy_s (a1 + 0x101, 0x101, server_hostname, 0x100);
strncpy_s (a1 + 0x202, 0x100, "TAIKO ARCADE LOADER", 0xFF); // ALL.Net SHOP NAME
strncpy_s (a1 + 0x302, 0x100, "TAIKO ARCADE LOADER", 0xFF);
strncpy_s (a1 + 0x402, 0x10, "1", 0xF);
strncpy_s (a1 + 0x412, 0x100, "TAIKO ARCADE LOADER", 0xFF);
strncpy_s (a1 + 0x512, 0x100, "X", 0xFF);
strncpy_s (a1 + 0x612, 0x100, "Y", 0xFF);
strncpy_s (a1 + 0x712, 0x100, "Z", 0xFF);
strncpy_s (a1 + 0x812, 0x10, "JPN0123", 0xF);
strncpy_s (a1 + 0x832, 0x10, "JPN", 0xF);
strncpy_s (a1 + 0x842, 0x10, "002,00", 0xF);
strncpy_s (a1 + 0x842, 0x10, "PowerOnResponseVer2", 0xF);
return 0;
}
virtual i32
Unk15 () {
return 0;
}
virtual i32
Unk16 () {
return 0;
}
virtual i32
Unk17 () {
return 0;
}
virtual i32
Unk18 (void *a1) {
return 0;
}
virtual i32
Unk19 (u8 *a1) {
memset (a1, 0, 0x38);
a1[0] = 1;
return 1;
}
virtual i32
Unk20 () {
return 0;
}
virtual i32
Unk21 () {
return 1;
}
virtual i32
Unk22 () {
return 0;
}
virtual i32
Unk23 () {
return 0;
}
virtual i32
Unk24 () {
return 0;
}
virtual i32
Unk25 () {
return 1;
}
virtual i32
Unk26 () {
return 0;
}
virtual i32
Unk27 () {
return 1;
}
virtual i32
Unk28 () {
return 0;
}
virtual i32
Unk29 () {
return 0;
}
virtual i32
Unk30 () {
return 0;
}
virtual i32
PrintDebugInfo () {
return 0;
}
virtual i32
Unk32 (void *a1) {
return 0;
}
virtual void
Unk33 () {}
public:
CAuth () {}
virtual ~CAuth () {}
private:
i32 refCount = 0;
};
class CAuthFactory : public IClassFactory {
public:
STDMETHODIMP
QueryInterface (REFIID riid, LPVOID *ppvObj) {
wchar_t *iid_str;
StringFromCLSID (riid, &iid_str);
printf ("QueryInterface %ls\n", iid_str);
if (riid == IID_IUnknown || riid == IID_IClassFactory || riid == IID_CAuthFactory) {
*ppvObj = this;
return 0;
} else {
*ppvObj = 0;
return E_NOINTERFACE;
}
}
STDMETHODIMP_ (ULONG) AddRef () { return 2; }
STDMETHODIMP_ (ULONG) Release () { return 1; }
virtual HRESULT
CreateInstance (IUnknown *outer, REFIID riid, void **object) {
if (outer != 0) return CLASS_E_NOAGGREGATION;
wchar_t *iid_str;
StringFromCLSID (riid, &iid_str);
printf ("CreateInstance %ls\n", iid_str);
CAuth *auth = new CAuth ();
return auth->QueryInterface (riid, object);
}
virtual HRESULT
LockServer (i32 lock) {
return 0;
}
};
extern "C" {
void
Init () {
CoInitializeEx (0, 0);
CoRegisterClassObject (IID_CAuthFactory, (IUnknown *)new CAuthFactory (), CLSCTX_LOCAL_SERVER, 1, &reg);
toml_table_t *config = openConfig (configPath ((char *)"config.toml"));
if (config) {
server_hostname = readConfigString (config, (char *)"server", server_hostname);
pcb_id = readConfigString (config, (char *)"pcb_id", pcb_id);
// Get ipv4 address of server
struct addrinfo *res = 0;
getaddrinfo (server_hostname, "", 0, &res);
for (struct addrinfo *i = res; i != 0; i = i->ai_next) {
if (res->ai_addr->sa_family != AF_INET) { continue; }
struct sockaddr_in *p = (struct sockaddr_in *)res->ai_addr;
inet_ntop (AF_INET, &p->sin_addr, server_ip, 0x10);
break;
}
}
}
void
Exit () {
CoRevokeClassObject (reg);
CoUninitialize ();
}
void
Test () {
i32 res;
CoInitializeEx (0, 0);
CAuth *auth;
res = CoCreateInstance (IID_CAuthFactory, 0, 4, IID_CAuth, (void **)&auth);
if (res != S_OK) {
printf ("AMAuthd not running %x\n", res);
CoUninitialize ();
return;
}
auth->AddRef ();
i32 *unk9 = (i32 *)malloc (sizeof (i32) * 0x50);
memset (unk9, 0, sizeof (i32) * 0x50);
res = auth->Unk9 (unk9);
printf ("unk9: %d\n", res);
for (int i = 0; i < 0x50; i++) {
printf ("%d\n", unk9[i]);
}
free (unk9);
char *unk14 = (char *)malloc (0x8A2);
res = auth->Unk14 (unk14);
printf ("unk14: %d\n", res);
printf ("unk14 %s\n", unk14);
printf ("unk14 + 0x101 %s\n", unk14 + 0x101);
printf ("unk14 + 0x202 %s\n", unk14 + 0x202);
printf ("unk14 + 0x302 %s\n", unk14 + 0x302);
printf ("unk14 + 0x402 %s\n", unk14 + 0x402);
printf ("unk14 + 0x412 %s\n", unk14 + 0x412);
printf ("unk14 + 0x512 %s\n", unk14 + 0x512);
printf ("unk14 + 0x512 %s\n", unk14 + 0x612);
printf ("unk14 + 0x712 %s\n", unk14 + 0x712);
printf ("unk14 + 0x812 %s\n", unk14 + 0x812);
printf ("unk14 + 0x822 %s\n", unk14 + 0x822);
printf ("unk14 + 0x832 %s\n", unk14 + 0x832);
printf ("unk14 + 0x842 %s\n", unk14 + 0x842);
printf ("unk14 + 0x862 %s\n", unk14 + 0x862);
free (unk14);
char *unk11 = (char *)malloc (0x13C);
res = auth->Unk11 (unk11);
printf ("unk11: %d\n", res);
printf ("%s\n", unk11);
printf ("%s\n", unk11 + 4);
printf ("%s\n", unk11 + 20);
printf ("%s\n", unk11 + 28);
printf ("%s\n", unk11 + 36);
printf ("%s\n", unk11 + 44);
printf ("%s\n", unk11 + 52);
printf ("%s\n", unk11 + 56);
printf ("%s\n", unk11 + 60);
free (unk11);
char *unk10 = (char *)malloc (0xB0);
res = auth->Unk10 (unk10);
printf ("unk10: %d\n", res);
FILE *unk10fp = fopen ("unk10.bin", "w");
fwrite (unk10, 0xA8, 1, unk10fp);
fclose (unk10fp);
free (unk10);
u8 *unk19 = (u8 *)malloc (0x40);
memset (unk19, 0xFF, 0x40);
res = auth->Unk19 (unk19);
printf ("unk19: %d\n", res);
FILE *unk19fp = fopen ("unk19.bin", "w");
fwrite (unk19, 0x40, 1, unk19fp);
fclose (unk19fp);
free (unk19);
auth->Release ();
CoUninitialize ();
}
}

213
src/bnusio.cpp Normal file
View File

@ -0,0 +1,213 @@
#include "helpers.h"
#include "poll.h"
extern std::vector<HMODULE> plugins;
extern char accessCode[21];
extern char chipId[33];
namespace bnusio {
#define RETURN_FALSE(returnType, functionName, ...) \
returnType functionName (__VA_ARGS__) { return 0; }
extern "C" {
RETURN_FALSE (i64, bnusio_ClearSram);
RETURN_FALSE (i64, bnusio_Communication, i32 a1);
RETURN_FALSE (i64, bnusio_DecService, i32 a1, u16 a2);
RETURN_FALSE (void *, bnusio_GetBuffer, u16 a1, i64 a2, i16 a3);
RETURN_FALSE (i64, bnusio_GetCDOut, u8 a1);
RETURN_FALSE (void *, bnusio_GetCoinError, i32 a1);
RETURN_FALSE (i64, bnusio_GetCoinLock, u8 a1);
RETURN_FALSE (u64, bnusio_GetEncoder);
RETURN_FALSE (void *, bnusio_GetExpansionMode);
RETURN_FALSE (u8, bnusio_GetGout, u8 a1);
RETURN_FALSE (i64, bnusio_GetHopOut, u8 a1);
RETURN_FALSE (char *, bnusio_GetIoBoardName);
RETURN_FALSE (u16, bnusio_GetRegisterU16, i16 a1);
RETURN_FALSE (u8, bnusio_GetRegisterU8, u16 a1);
RETURN_FALSE (void *, bnusio_GetService, i32 a1);
RETURN_FALSE (void *, bnusio_GetServiceError, i32 a1);
RETURN_FALSE (u16, bnusio_GetStatusU16, u16 a1);
RETURN_FALSE (u8, bnusio_GetStatusU8, u16 a1);
RETURN_FALSE (u64, bnusio_GetSwIn64);
RETURN_FALSE (void *, bnusio_GetSystemError);
RETURN_FALSE (u8, bnusio_IsConnected);
RETURN_FALSE (u8, bnusio_IsWideUsio);
RETURN_FALSE (i64, bnusio_Open);
RETURN_FALSE (i32, bnusio_ResetIoBoard);
RETURN_FALSE (i64, bnusio_SetBuffer, u16 a1, i32 a2, i16 a3);
RETURN_FALSE (i64, bnusio_SetCDOut, u8 a1, u8 a2);
RETURN_FALSE (i64, bnusio_SetCoinLock, u8 a1, u8 a2);
RETURN_FALSE (i64, bnusio_SetExpansionMode, i16 a1);
RETURN_FALSE (i64, bnusio_SetGout, u8 a1, u8 a2);
RETURN_FALSE (i64, bnusio_SetHopOut, u8 a1, u8 a2);
RETURN_FALSE (i64, bnusio_SetHopperLimit, u16 a1, i16 a2);
RETURN_FALSE (i64, bnusio_SetHopperRequest, u16 a1, i16 a2);
RETURN_FALSE (void *, bnusio_SetPLCounter, i16 a1);
RETURN_FALSE (i64, bnusio_SetRegisterU16, u16 a1, u16 a2);
RETURN_FALSE (i64, bnusio_SetRegisterU8, u16 a1, u8 a2);
RETURN_FALSE (i64, bnusio_SetSystemError, i16 a1);
RETURN_FALSE (i64, bnusio_SramRead, i32 a1, u8 a2, i32 a3, u16 a4);
RETURN_FALSE (i64, bnusio_SramWrite, i32 a1, u8 a2, i32 a3, u16 a4);
RETURN_FALSE (i64, bnusio_ResetCoin);
RETURN_FALSE (i64, bnusio_DecCoin, i32 a1, u16 a2);
size_t
bnusio_GetFirmwareVersion () {
return 126;
}
Keybindings EXIT = {.keycodes = {VK_ESCAPE}};
Keybindings TEST = {.keycodes = {VK_F1}};
Keybindings SERVICE = {.keycodes = {VK_F2}};
Keybindings DEBUG_UP = {.keycodes = {VK_UP}};
Keybindings DEBUG_DOWN = {.keycodes = {VK_DOWN}};
Keybindings DEBUG_ENTER = {.keycodes = {VK_RETURN}};
Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_CONTROLLER_BUTTON_START}};
Keybindings CARD_INSERT = {.keycodes = {'P'}};
Keybindings P1_LEFT_BLUE = {.keycodes = {'D'}, .axis = {SDL_AXIS_LTRIGGER_DOWN}};
Keybindings P1_LEFT_RED = {.keycodes = {'F'}, .buttons = {SDL_CONTROLLER_BUTTON_LEFTSTICK}};
Keybindings P1_RIGHT_RED = {.keycodes = {'J'}, .buttons = {SDL_CONTROLLER_BUTTON_RIGHTSTICK}};
Keybindings P1_RIGHT_BLUE = {.keycodes = {'K'}, .axis = {SDL_AXIS_RTRIGGER_DOWN}};
Keybindings P2_LEFT_BLUE = {};
Keybindings P2_LEFT_RED = {};
Keybindings P2_RIGHT_RED = {};
Keybindings P2_RIGHT_BLUE = {};
struct AnalogGameButton {
Keybindings *bindings;
i32 offset;
};
u16 drumMin = 10000;
u16 drumMax = 20000;
AnalogGameButton analogButtons[] = {{&P1_LEFT_BLUE}, {&P1_LEFT_RED}, {&P1_RIGHT_RED}, {&P1_RIGHT_BLUE}, {&P2_LEFT_BLUE}, {&P2_LEFT_RED}, {&P2_RIGHT_RED}, {&P2_RIGHT_BLUE}};
u16
bnusio_GetAnalogIn (u8 which) {
auto button = &analogButtons[which];
if (!IsButtonDown (*button->bindings)) {
button->offset = drumMin;
return 0;
} else if (button->offset == drumMax) {
return drumMax;
} else {
button->offset += 1;
return button->offset;
}
}
bool testEnabled = false;
int coin_count = 0;
bool inited = false;
HWND windowHandle = 0;
u16 __fastcall bnusio_GetCoin (i32 a1) {
if (a1 != 1) return coin_count;
if (!inited) {
windowHandle = FindWindowA ("nuFoundation.Window", 0);
InitializePoll (windowHandle);
for (auto plugin : plugins) {
auto initEvent = GetProcAddress (plugin, "Init");
if (initEvent) initEvent ();
}
inited = true;
}
UpdatePoll (windowHandle);
if (IsButtonTapped (COIN_ADD) && !testEnabled) coin_count++;
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
if (IsButtonTapped (EXIT)) ExitProcess (0);
for (auto plugin : plugins) {
auto updateEvent = GetProcAddress (plugin, "Update");
if (updateEvent) updateEvent ();
}
return coin_count;
}
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;
return sw;
}
}
HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; }
HOOK (u64, bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock")) { return 0xFFFFFF9C; }
HOOK (void, bngrw_fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; }
HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; }
HOOK (u64, bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID")) { return 0; }
HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; }
HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; }
HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; }
HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; }
HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; }
HOOK (u64, bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup")) { return 1; }
HOOK (u64, bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp")) { return 1; }
HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; }
HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; }
HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo")) { return 1; }
HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; }
HOOK (u64, bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower")) { return 0; }
HOOK (i32, bngrw_reqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) { return 1; }
HOOK (u64, bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit")) { return 0; }
HOOK (u64, bngrw_attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, i32 (*callback) (i32, i32, i32 *), i32 *a6) { return 1; }
HOOK (u64, bngrw_reqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, void (*callback) (i32, i32, u8[168], u64), u64 a5) { return 1; }
void
Init () {
INSTALL_HOOK (bngrw_DevReset);
INSTALL_HOOK (bngrw_ReadMifare);
INSTALL_HOOK (bngrw_fin);
INSTALL_HOOK (bngrw_GetFwVersion);
INSTALL_HOOK (bngrw_GetStationID);
INSTALL_HOOK (bngrw_GetRetryCount);
INSTALL_HOOK (bngrw_IsCmdExec);
INSTALL_HOOK (bngrw_ReqAction);
INSTALL_HOOK (bngrw_ReqAiccAuth);
INSTALL_HOOK (bngrw_ReqBeep);
INSTALL_HOOK (bngrw_ReqFwCleanup);
INSTALL_HOOK (bngrw_ReqFwVersionUp);
INSTALL_HOOK (bngrw_ReqLatchID);
INSTALL_HOOK (bngrw_ReqLed);
INSTALL_HOOK (bngrw_ReqSendMail);
INSTALL_HOOK (bngrw_ReqSendUrl);
INSTALL_HOOK (bngrw_ReqSetLedPower);
INSTALL_HOOK (bngrw_reqCancel);
INSTALL_HOOK (bngrw_Init);
auto configPath = std::filesystem::current_path () / "keyconfig.toml";
toml_table_t *config = openConfig (configPath);
if (config) {
SetConfigValue (config, "EXIT", &EXIT);
SetConfigValue (config, "TEST", &TEST);
SetConfigValue (config, "SERVICE", &SERVICE);
SetConfigValue (config, "DEBUG_UP", &DEBUG_UP);
SetConfigValue (config, "DEBUG_DOWN", &DEBUG_DOWN);
SetConfigValue (config, "DEBUG_ENTER", &DEBUG_ENTER);
SetConfigValue (config, "COIN_ADD", &COIN_ADD);
SetConfigValue (config, "CARD_INSERT", &CARD_INSERT);
SetConfigValue (config, "P1_LEFT_BLUE", &P1_LEFT_BLUE);
SetConfigValue (config, "P1_LEFT_RED", &P1_LEFT_RED);
SetConfigValue (config, "P1_RIGHT_RED", &P1_RIGHT_RED);
SetConfigValue (config, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE);
SetConfigValue (config, "P2_LEFT_BLUE", &P2_LEFT_BLUE);
SetConfigValue (config, "P2_LEFT_RED", &P2_LEFT_RED);
SetConfigValue (config, "P2_RIGHT_RED", &P2_RIGHT_RED);
SetConfigValue (config, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE);
toml_free (config);
}
}
} // namespace bnusio

3
src/bnusio.h Normal file
View File

@ -0,0 +1,3 @@
namespace bnusio {
void Init ();
} // namespace bnusio

View File

@ -1,117 +0,0 @@
#include "helpers.h"
// force show cursor
HOOK_DYNAMIC (i32, __stdcall, ShowMouse, i32 show) { return originalShowMouse (true); }
HOOK_DYNAMIC (i32, __stdcall, ExitWindows, i32 exitCode, i32 reason) {
ExitProcess (0);
return true;
}
// xinput stuff
HOOK_DYNAMIC (u32, __stdcall, XinputGetState, u32 index, void *state) { return ERROR_DEVICE_NOT_CONNECTED; }
HOOK_DYNAMIC (u32, __stdcall, XinputSetState, u32 index, void *state) { return ERROR_DEVICE_NOT_CONNECTED; }
HOOK_DYNAMIC (u32, __stdcall, XinputGetCapabilites, u32 index, u32 flags, void *state) { return ERROR_DEVICE_NOT_CONNECTED; }
// bnusio stuff
RETURN_FALSE (i64, __stdcall, bnusio_ClearSram);
RETURN_FALSE (i64, __fastcall, bnusio_Communication, i32 a1);
RETURN_FALSE (i64, __fastcall, bnusio_DecService, i32 a1, u16 a2);
RETURN_FALSE (void *, __fastcall, bnusio_GetBuffer, u16 a1, i64 a2, i16 a3);
RETURN_FALSE (i64, __fastcall, bnusio_GetCDOut, u8 a1);
RETURN_FALSE (void *, __fastcall, bnusio_GetCoinError, i32 a1);
RETURN_FALSE (i64, __fastcall, bnusio_GetCoinLock, u8 a1);
RETURN_FALSE (u64, __stdcall, bnusio_GetEncoder);
RETURN_FALSE (void *, __stdcall, bnusio_GetExpansionMode);
void *__stdcall bnusio_GetFirmwareVersion () { return (void *)(u16)126; }
RETURN_FALSE (u8, __stdcall, bnusio_GetGout, u8 a1);
RETURN_FALSE (i64, __stdcall, bnusio_GetHopOut, u8 a1);
RETURN_FALSE (char *, __stdcall, bnusio_GetIoBoardName);
RETURN_FALSE (u16, __fastcall, bnusio_GetRegisterU16, i16 a1);
RETURN_FALSE (u8, __fastcall, bnusio_GetRegisterU8, u16 a1);
RETURN_FALSE (void *, __fastcall, bnusio_GetService, i32 a1);
RETURN_FALSE (void *, __fastcall, bnusio_GetServiceError, i32 a1);
RETURN_FALSE (u16, __fastcall, bnusio_GetStatusU16, u16 a1);
RETURN_FALSE (u8, __fastcall, bnusio_GetStatusU8, u16 a1);
RETURN_FALSE (u64, __stdcall, bnusio_GetSwIn64);
RETURN_FALSE (void *, __stdcall, bnusio_GetSystemError);
RETURN_FALSE (u8, __stdcall, bnusio_IsConnected);
RETURN_FALSE (u8, __stdcall, bnusio_IsWideUsio);
RETURN_FALSE (i64, __stdcall, bnusio_Open);
RETURN_FALSE (i32, __stdcall, bnusio_ResetIoBoard);
RETURN_FALSE (i64, __fastcall, bnusio_SetBuffer, u16 a1, i32 a2, i16 a3);
RETURN_FALSE (i64, __fastcall, bnusio_SetCDOut, u8 a1, u8 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetCoinLock, u8 a1, u8 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetExpansionMode, i16 a1);
RETURN_FALSE (i64, __fastcall, bnusio_SetGout, u8 a1, u8 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetHopOut, u8 a1, u8 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetHopperLimit, u16 a1, i16 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetHopperRequest, u16 a1, i16 a2);
RETURN_FALSE (void *, __fastcall, bnusio_SetPLCounter, i16 a1);
RETURN_FALSE (i64, __fastcall, bnusio_SetRegisterU16, u16 a1, u16 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetRegisterU8, u16 a1, u8 a2);
RETURN_FALSE (i64, __fastcall, bnusio_SetSystemError, i16 a1);
RETURN_FALSE (i64, __fastcall, bnusio_SramRead, i32 a1, u8 a2, i32 a3, u16 a4);
RETURN_FALSE (i64, __fastcall, bnusio_SramWrite, i32 a1, u8 a2, i32 a3, u16 a4);
RETURN_FALSE (i64, __stdcall, bnusio_ResetCoin);
RETURN_FALSE (i64, __fastcall, bnusio_DecCoin, i32 a1, u16 a2);
HOOK_DYNAMIC (i64, __stdcall, UsbFinderInitialize) { return 0; }
HOOK_DYNAMIC (i64, __stdcall, UsbFinderRelease) { return 0; }
HOOK_DYNAMIC (i64, __fastcall, UsbFinderGetSerialNumber, i32 a1, char *a2) {
strcpy (a2, "284111080001");
return 0;
}
HOOK_DYNAMIC (u64, __stdcall, bngrw_DevReset) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReadMifare) { return 0xFFFFFF9C; }
HOOK_DYNAMIC (void, __stdcall, bngrw_fin) { return; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_GetFwVersion) { return 0; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_GetStationID) { return 0; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_GetRetryCount) { return 0; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_IsCmdExec) { return 0xFFFFFFFF; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqAction) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqAiccAuth) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqBeep) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqFwCleanup) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqFwVersionUp) { return 1; }
HOOK_DYNAMIC (i32, __stdcall, bngrw_ReqLatchID) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqLed) { return 1; }
HOOK_DYNAMIC (i32, __stdcall, bngrw_ReqSendMail) { return 1; }
HOOK_DYNAMIC (i32, __stdcall, bngrw_ReqSendUrl) { return 1; }
HOOK_DYNAMIC (u64, __stdcall, bngrw_ReqSetLedPower) { return 0; }
HOOK_DYNAMIC (i32, __stdcall, bngrw_reqCancel) { return 1; }
HOOK_DYNAMIC (i32, __stdcall, ssleay_Shutdown) { return 1; }
void
init_boilerplate () {
INSTALL_HOOK_DYNAMIC (ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"));
INSTALL_HOOK_DYNAMIC (ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx"));
INSTALL_HOOK_DYNAMIC (XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState"));
INSTALL_HOOK_DYNAMIC (XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState"));
INSTALL_HOOK_DYNAMIC (XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities"));
INSTALL_HOOK_DYNAMIC (UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize"));
INSTALL_HOOK_DYNAMIC (UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease"));
INSTALL_HOOK_DYNAMIC (UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"));
INSTALL_HOOK_DYNAMIC (bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset"));
INSTALL_HOOK_DYNAMIC (bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock"));
INSTALL_HOOK_DYNAMIC (bngrw_fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin"));
INSTALL_HOOK_DYNAMIC (bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion"));
INSTALL_HOOK_DYNAMIC (bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID"));
INSTALL_HOOK_DYNAMIC (bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount"));
INSTALL_HOOK_DYNAMIC (bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo"));
INSTALL_HOOK_DYNAMIC (bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower"));
INSTALL_HOOK_DYNAMIC (bngrw_reqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel"));
INSTALL_HOOK_DYNAMIC (ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown"));
}

View File

@ -1,2 +0,0 @@
#pragma once
void init_boilerplate ();

View File

@ -1,289 +0,0 @@
#include "boilerplate.h"
#include "helpers.h"
#include "poll.h"
#include <stdio.h>
#include <time.h>
bool testEnabled = false;
u16 drumMax = 0xFFFF;
u16 drumMin = 0xFFFF;
char accessCode1[21] = "00000000000000000001";
char accessCode2[21] = "00000000000000000002";
char chipId1[33] = "00000000000000000000000000000001";
char chipId2[33] = "00000000000000000000000000000002";
char *server = "127.0.0.1";
typedef i32 (*callbackAttach) (i32, i32, i32 *);
typedef void (*callbackTouch) (i32, i32, u8[168], u64);
typedef void event ();
typedef void waitTouchEvent (callbackTouch, u64);
bool waitingForTouch = false;
callbackTouch touchCallback;
u64 touchData;
callbackAttach attachCallback;
i32 *attachData;
HMODULE plugins[255] = { 0 };
#define ON_HIT(bind) IsButtonTapped (bind) ? drumMax == drumMin ? drumMax : (u16)(rand () % drumMax + drumMin) : 0
Keybindings EXIT = { .keycodes = { VK_ESCAPE } };
Keybindings TEST = { .keycodes = { VK_F1 } };
Keybindings SERVICE = { .keycodes = { VK_F2 } };
Keybindings DEBUG_UP = { .keycodes = { VK_UP } };
Keybindings DEBUG_DOWN = { .keycodes = { VK_DOWN } };
Keybindings DEBUG_ENTER = { .keycodes = { VK_RETURN } };
Keybindings COIN_ADD = { .keycodes = { VK_RETURN }, .buttons = { SDL_GAMEPAD_BUTTON_START } };
Keybindings CARD_INSERT_1 = { .keycodes = { 'P' } };
Keybindings CARD_INSERT_2 = {};
Keybindings P1_LEFT_BLUE = { .keycodes = { 'D' }, .axis = { SDL_AXIS_LTRIGGER_DOWN } };
Keybindings P1_LEFT_RED = { .keycodes = { 'F' }, .buttons = { SDL_GAMEPAD_BUTTON_LEFT_STICK } };
Keybindings P1_RIGHT_RED = { .keycodes = { 'J' }, .buttons = { SDL_GAMEPAD_BUTTON_RIGHT_STICK } };
Keybindings P1_RIGHT_BLUE = { .keycodes = { 'K' }, .axis = { SDL_AXIS_RTRIGGER_DOWN } };
Keybindings P2_LEFT_BLUE = {};
Keybindings P2_LEFT_RED = {};
Keybindings P2_RIGHT_RED = {};
Keybindings P2_RIGHT_BLUE = {};
u16 __fastcall bnusio_GetAnalogIn (u8 which) {
switch (which) {
case 0: return ON_HIT (P1_LEFT_BLUE); // Player 1 Left Blue
case 1: return ON_HIT (P1_LEFT_RED); // Player 1 Left Red
case 2: return ON_HIT (P1_RIGHT_RED); // Player 1 Right Red
case 3: return ON_HIT (P1_RIGHT_BLUE); // Player 1 Right Blue
case 4: return ON_HIT (P2_LEFT_BLUE); // Player 2 Left Blue
case 5: return ON_HIT (P2_LEFT_RED); // Player 2 Left Red
case 6: return ON_HIT (P2_RIGHT_RED); // Player 2 Right Red
case 7: return ON_HIT (P2_RIGHT_BLUE); // Player 2 Right Blue
default: return 0;
}
}
u16 __fastcall bnusio_GetCoin (i32 a1) {
static int coin_count = 0;
if (a1 != 1) return coin_count;
static bool inited = false;
static HWND windowHandle = 0;
if (!inited) {
windowHandle = FindWindowA ("nuFoundation.Window", 0);
InitializePoll (windowHandle);
toml_table_t *config = openConfig (configPath ("keyconfig.toml"));
if (config) {
SetConfigValue (config, "EXIT", &EXIT);
SetConfigValue (config, "TEST", &TEST);
SetConfigValue (config, "SERVICE", &SERVICE);
SetConfigValue (config, "DEBUG_UP", &DEBUG_UP);
SetConfigValue (config, "DEBUG_DOWN", &DEBUG_DOWN);
SetConfigValue (config, "DEBUG_ENTER", &DEBUG_ENTER);
SetConfigValue (config, "COIN_ADD", &COIN_ADD);
SetConfigValue (config, "CARD_INSERT_1", &CARD_INSERT_1);
SetConfigValue (config, "CARD_INSERT_2", &CARD_INSERT_2);
SetConfigValue (config, "P1_LEFT_BLUE", &P1_LEFT_BLUE);
SetConfigValue (config, "P1_LEFT_RED", &P1_LEFT_RED);
SetConfigValue (config, "P1_RIGHT_RED", &P1_RIGHT_RED);
SetConfigValue (config, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE);
SetConfigValue (config, "P2_LEFT_BLUE", &P2_LEFT_BLUE);
SetConfigValue (config, "P2_LEFT_RED", &P2_LEFT_RED);
SetConfigValue (config, "P2_RIGHT_RED", &P2_RIGHT_RED);
SetConfigValue (config, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE);
toml_free (config);
}
inited = true;
}
UpdatePoll (windowHandle);
if (IsButtonTapped (COIN_ADD) && !testEnabled) coin_count++;
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
if (IsButtonTapped (EXIT)) ExitProcess (0);
if (waitingForTouch) {
static u8 cardData[168]
= { 0x01, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x2E, 0x58, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x5C, 0x97, 0x44, 0xF0, 0x88, 0x04, 0x00, 0x43, 0x26, 0x2C, 0x33, 0x00, 0x04,
0x06, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x42, 0x47, 0x49, 0x43, 0x36,
0x00, 0x00, 0xFA, 0xE9, 0x69, 0x00, 0xF6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
bool hasInserted = false;
if (IsButtonTapped (CARD_INSERT_1)) {
for (int i = 0; plugins[i] != 0; i++) {
FARPROC insertEvent = GetProcAddress (plugins[i], "BeforeCard1Insert");
if (insertEvent) ((event *)insertEvent) ();
}
for (int i = 0; plugins[i] != 0; i++) {
FARPROC insertEvent = GetProcAddress (plugins[i], "Card1Insert");
if (insertEvent) {
((event *)insertEvent) ();
hasInserted = true;
}
}
if (!hasInserted) {
memcpy (cardData + 0x2C, chipId1, 33);
memcpy (cardData + 0x50, accessCode1, 21);
touchCallback (0, 0, cardData, touchData);
}
} else if (IsButtonTapped (CARD_INSERT_2)) {
for (int i = 0; plugins[i] != 0; i++) {
FARPROC insertEvent = GetProcAddress (plugins[i], "BeforeCard2Insert");
if (insertEvent) ((event *)insertEvent) ();
}
for (int i = 0; plugins[i] != 0; i++) {
FARPROC insertEvent = GetProcAddress (plugins[i], "Card2Insert");
if (insertEvent) {
((event *)insertEvent) ();
hasInserted = true;
}
}
if (!hasInserted) {
memcpy (cardData + 0x2C, chipId2, 33);
memcpy (cardData + 0x50, accessCode2, 21);
touchCallback (0, 0, cardData, touchData);
}
}
}
for (int i = 0; plugins[i] != 0; i++) {
FARPROC updateEvent = GetProcAddress (plugins[i], "Update");
if (updateEvent) ((event *)updateEvent) ();
}
if (attachCallback) attachCallback (0, 0, attachData);
return coin_count;
}
u32 __stdcall 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;
return sw;
}
i64 __stdcall bnusio_Close () {
for (int i = 0; plugins[i] != 0; i++) {
FARPROC exitEvent = GetProcAddress (plugins[i], "Exit");
if (exitEvent) ((event *)exitEvent) ();
}
return 0;
}
HOOK_DYNAMIC (u64, __stdcall, bngrw_Init) {
for (int i = 0; plugins[i] != 0; i++) {
FARPROC initEvent = GetProcAddress (plugins[i], "Init");
if (initEvent) ((event *)initEvent) ();
}
return 0;
}
HOOK_DYNAMIC (u64, __stdcall, bngrw_attach, i32 a1, char *a2, i32 a3, i32 a4, callbackAttach callback, i32 *a6) {
// This is way too fucking jank
attachCallback = callback;
attachData = a6;
return 1;
}
HOOK_DYNAMIC (i32, __stdcall, bngrw_reqWaitTouch, u32 a1, i32 a2, u32 a3, callbackTouch callback, u64 a5) {
waitingForTouch = true;
touchCallback = callback;
touchData = a5;
for (int i = 0; plugins[i] != 0; i++) {
FARPROC touchEvent = GetProcAddress (plugins[i], "WaitTouch");
if (touchEvent) ((waitTouchEvent *)touchEvent) (callback, a5);
}
return 1;
}
HOOK_DYNAMIC (i32, __stdcall, ws2_getaddrinfo, char *node, char *service, void *hints, void *out) {
return originalws2_getaddrinfo (server, service, hints, out);
}
u32 inline generate_rand () { return rand () + rand () * rand () + rand (); }
i32 __stdcall DllMain (HMODULE mod, DWORD cause, void *ctx) {
if (cause == DLL_PROCESS_DETACH) DisposePoll ();
if (cause != DLL_PROCESS_ATTACH) return true;
init_boilerplate ();
INSTALL_HOOK_DYNAMIC (bngrw_attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"));
INSTALL_HOOK_DYNAMIC (bngrw_reqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"));
INSTALL_HOOK_DYNAMIC (bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit"));
INSTALL_HOOK_DYNAMIC (ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"));
// Set current directory to the directory of the executable
// Find all files in the plugins directory that end with .dll
// Call loadlibraryW on those files
// Create a message box if they fail to load
wchar_t path[MAX_PATH];
GetModuleFileNameW (NULL, path, MAX_PATH);
*wcsrchr (path, '\\') = '\0';
SetCurrentDirectoryW (path);
WIN32_FIND_DATAW fd;
int i = 0;
HANDLE hFind = FindFirstFileW (L"plugins/*.dll", &fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
wchar_t filePath[MAX_PATH];
wcscpy (filePath, path);
wcscat (filePath, L"/plugins/");
wcscat (filePath, fd.cFileName);
HMODULE hModule = LoadLibraryW (filePath);
if (!hModule) {
wchar_t buf[128];
swprintf (buf, 128, L"Failed to load plugin %d", GetLastError ());
MessageBoxW (NULL, buf, fd.cFileName, MB_ICONERROR);
} else {
plugins[i] = hModule;
i++;
FARPROC preInitEvent = GetProcAddress (hModule, "PreInit");
if (preInitEvent) ((event *)preInitEvent) ();
}
} while (FindNextFileW (hFind, &fd));
FindClose (hFind);
}
toml_table_t *config = openConfig (configPath ("config.toml"));
if (config) {
drumMax = readConfigInt (config, "drumMax", drumMax);
drumMin = readConfigInt (config, "drumMin", drumMin);
server = readConfigString (config, "server", server);
toml_free (config);
}
FILE *cards = fopen (configPath ("cards.dat"), "r");
if (cards) {
fread (accessCode1, 1, 20, cards);
fread (accessCode2, 1, 20, cards);
fread (chipId1, 1, 32, cards);
fread (chipId2, 1, 32, cards);
fclose (cards);
} else {
FILE *cards_new = fopen (configPath ("cards.dat"), "w");
if (cards_new) {
srand (time (0));
sprintf (accessCode1, "%020d", generate_rand ());
fwrite (accessCode1, 1, 20, cards_new);
sprintf (accessCode2, "%020d", generate_rand ());
fwrite (accessCode2, 1, 20, cards_new);
sprintf (chipId1, "%032X", generate_rand ());
fwrite (chipId1, 1, 32, cards_new);
sprintf (chipId2, "%032X", generate_rand ());
fwrite (chipId2, 1, 32, cards_new);
fclose (cards_new);
}
}
return true;
}

149
src/dllmain.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "bnusio.h"
#include "helpers.h"
#include "patches/patches.h"
#include "poll.h"
#include <xxhash.h>
enum class GameVersion : XXH64_hash_t {
UNKNOWN = 0,
JP_NOV_2020 = 0x67C0F3042746D488,
CN_JUN_2023 = 0xA7EE39F2CC2C57C8,
};
GameVersion version = GameVersion::UNKNOWN;
std::vector<HMODULE> plugins;
const char *server = "127.0.0.1";
char accessCode[21] = "00000000000000000000";
char chipId[33] = "00000000000000000000000000000000";
HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse (true); }
HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) {
ExitProcess (0);
return true;
}
HOOK (i32, XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
HOOK (i32, XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
HOOK (i32, XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities")) { return ERROR_DEVICE_NOT_CONNECTED; }
HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) { return 1; }
HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; }
HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; }
HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) {
strcpy (a2, "284111080001");
return 0;
}
HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) { return originalws2_getaddrinfo (server, service, hints, out); }
void
GetGameVersion () {
wchar_t w_path[MAX_PATH];
GetModuleFileNameW (0, w_path, MAX_PATH);
std::filesystem::path path (w_path);
if (!std::filesystem::exists (path) || !path.has_filename ()) {
MessageBoxA (0, "Failed to find executable", 0, MB_OK);
ExitProcess (0);
}
std::ifstream stream (path, std::ios::binary);
if (!stream.is_open ()) {
MessageBoxA (0, "Failed to read executable", 0, MB_OK);
ExitProcess (0);
}
stream.seekg (0, stream.end);
size_t length = stream.tellg ();
stream.seekg (0, stream.beg);
char *buf = (char *)calloc (length + 1, sizeof (char));
stream.read (buf, length);
version = (GameVersion)XXH64 (buf, length, 0);
stream.close ();
free (buf);
printf ("%llx\n", (u64)version);
switch (version) {
case GameVersion::JP_NOV_2020:
case GameVersion::CN_JUN_2023: break;
default: MessageBoxA (0, "Unknown game version", 0, MB_OK); ExitProcess (0);
}
}
void
createCard () {
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 (0));
std::generate (buf, buf + 20, [&] () { return hexCharacterTable[rand () % 10]; });
WritePrivateProfileStringA ("card", "accessCode", buf, ".\\card.ini");
std::generate (buf, buf + 32, [&] () { return hexCharacterTable[rand () % 16]; });
WritePrivateProfileStringA ("card", "chipId", buf, ".\\card.ini");
}
BOOL
DllMain (HMODULE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
// This is bad, dont do this
// I/O in DllMain can easily cause a deadlock
GetGameVersion ();
auto pluginPath = std::filesystem::current_path () / "plugins";
if (std::filesystem::exists (pluginPath)) {
for (auto entry : std::filesystem::directory_iterator (pluginPath)) {
if (entry.path ().extension () == ".dll") {
auto name = entry.path ().wstring ();
HMODULE hModule = LoadLibraryW (name.c_str ());
if (!hModule) {
wchar_t buf[128];
wsprintfW (buf, L"Failed to load plugin %ls", name.c_str ());
MessageBoxW (0, buf, name.c_str (), MB_ICONERROR);
} else {
plugins.push_back (hModule);
}
}
}
}
auto configPath = std::filesystem::current_path () / "config.toml";
toml_table_t *config = openConfig (configPath);
if (config) {
server = readConfigString (config, "server", server);
toml_free (config);
}
if (!std::filesystem::exists (".\\card.ini")) createCard ();
GetPrivateProfileStringA ("card", "accessCode", accessCode, accessCode, 21, ".\\card.ini");
GetPrivateProfileStringA ("card", "chipId", chipId, chipId, 33, ".\\card.ini");
INSTALL_HOOK (ShowMouse);
INSTALL_HOOK (ExitWindows);
INSTALL_HOOK (XinputGetState);
INSTALL_HOOK (XinputSetState);
INSTALL_HOOK (XinputGetCapabilites);
INSTALL_HOOK (ssleay_Shutdown);
INSTALL_HOOK (UsbFinderInitialize);
INSTALL_HOOK (UsbFinderRelease);
INSTALL_HOOK (UsbFinderGetSerialNumber);
INSTALL_HOOK (ws2_getaddrinfo);
bnusio::Init ();
switch (version) {
case GameVersion::UNKNOWN: break;
case GameVersion::JP_NOV_2020: patches::JP_NOV_2020::Init (); break;
case GameVersion::CN_JUN_2023: patches::CN_JUN_2023::Init (); break;
}
}
return true;
}

View File

@ -3,28 +3,33 @@
void *consoleHandle = 0;
char *
configPath (char *name) {
static char buffer[MAX_PATH];
GetModuleFileNameA (NULL, buffer, MAX_PATH);
*(strrchr (buffer, '\\') + 1) = 0;
strcat_s (buffer, MAX_PATH, name);
return buffer;
}
toml_table_t *
openConfig (char *configFilePath) {
FILE *file = fopen (configFilePath, "r");
if (!file) {
printWarning ("%s (%s): cannot open file\n", __func__, configFilePath);
openConfig (std::filesystem::path path) {
if (!std::filesystem::exists (path) || !path.has_filename ()) {
printWarning ("%s (%s): file does not exist\n", __func__, path.string ().c_str ());
return 0;
}
std::ifstream stream (path);
if (!stream.is_open ()) {
printWarning ("%s (%s): could not open\n", __func__, path.string ().c_str ());
return 0;
}
stream.seekg (0, stream.end);
size_t length = stream.tellg ();
stream.seekg (0, stream.beg);
char *buf = (char *)calloc (length + 1, sizeof (char));
stream.read (buf, length);
char errorbuf[200];
toml_table_t *config = toml_parse_file (file, errorbuf, 200);
fclose (file);
toml_table_t *config = toml_parse (buf, errorbuf, 200);
stream.close ();
free (buf);
if (!config) {
printWarning ("%s (%s): %s\n", __func__, configFilePath, errorbuf);
printWarning ("%s (%s): %s\n", __func__, path.string ().c_str (), errorbuf);
return 0;
}
@ -32,7 +37,7 @@ openConfig (char *configFilePath) {
}
toml_table_t *
openConfigSection (toml_table_t *config, char *sectionName) {
openConfigSection (toml_table_t *config, const char *sectionName) {
toml_table_t *section = toml_table_in (config, sectionName);
if (!section) {
printWarning ("%s (%s): cannot find section\n", __func__, sectionName);
@ -43,7 +48,7 @@ openConfigSection (toml_table_t *config, char *sectionName) {
}
bool
readConfigBool (toml_table_t *table, char *key, bool notFoundValue) {
readConfigBool (toml_table_t *table, const char *key, bool notFoundValue) {
toml_datum_t data = toml_bool_in (table, key);
if (!data.ok) return notFoundValue;
@ -51,15 +56,15 @@ readConfigBool (toml_table_t *table, char *key, bool notFoundValue) {
}
int64_t
readConfigInt (toml_table_t *table, char *key, int64_t notFoundValue) {
readConfigInt (toml_table_t *table, const char *key, int64_t notFoundValue) {
toml_datum_t data = toml_int_in (table, key);
if (!data.ok) return notFoundValue;
return data.u.i;
}
char *
readConfigString (toml_table_t *table, char *key, char *notFoundValue) {
const char *
readConfigString (toml_table_t *table, const char *key, const char *notFoundValue) {
toml_datum_t data = toml_string_in (table, key);
if (!data.ok) return notFoundValue;

View File

@ -1,8 +1,11 @@
#pragma once
#include <MinHook.h>
#include <bits/stdc++.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <toml.h>
#include <windows.h>
@ -14,87 +17,83 @@ typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef float f32;
typedef double f64;
#ifdef DEFINE_GUID
#undef DEFINE_GUID
#endif
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#ifdef BASE_ADDRESS
#define ASLR(address, handle) ((u64)handle + (u64)address - (u64)BASE_ADDRESS)
#endif
#define FUNCTION_PTR(returnType, callingConvention, function, location, ...) \
returnType (callingConvention *function) (__VA_ARGS__) = (returnType (callingConvention *) (__VA_ARGS__)) (location)
#define FUNCTION_PTR(returnType, function, location, ...) returnType (*function) (__VA_ARGS__) = (returnType (*) (__VA_ARGS__)) (location)
#define FUNCTION_PTR_H(returnType, function, ...) extern returnType (*function) (__VA_ARGS__)
#define PROC_ADDRESS(libraryName, procName) GetProcAddress (LoadLibrary (TEXT (libraryName)), procName)
#define HOOK(returnType, callingConvention, functionName, location, ...) \
typedef returnType callingConvention (*functionName) (__VA_ARGS__); \
functionName original##functionName = NULL; \
void *where##functionName = (void *)location; \
returnType callingConvention implOf##functionName (__VA_ARGS__)
#define BASE_ADDRESS 0x140000000
#ifdef BASE_ADDRESS
const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
#define ASLR(address) ((u64)MODULE_HANDLE + (u64)address - (u64)BASE_ADDRESS)
#endif
#define HOOK_DYNAMIC(returnType, callingConvention, functionName, ...) \
typedef returnType callingConvention (*functionName) (__VA_ARGS__); \
functionName original##functionName = NULL; \
void *where##functionName = NULL; \
returnType callingConvention implOf##functionName (__VA_ARGS__)
#define HOOK(returnType, functionName, location, ...) \
typedef returnType (*functionName) (__VA_ARGS__); \
functionName original##functionName = NULL; \
void *where##functionName = (void *)location; \
returnType implOf##functionName (__VA_ARGS__)
#define INSTALL_HOOK(functionName) \
{ \
MH_Initialize (); \
MH_CreateHook ((void *)where##functionName, (void *)implOf##functionName, (void **)(&original##functionName)); \
MH_EnableHook ((void *)where##functionName); \
#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; \
returnType implOf##className##functionName (className *This, __VA_ARGS__)
#define INSTALL_HOOK(functionName) \
{ \
MH_Initialize (); \
MH_CreateHook ((void *)where##functionName, (void *)implOf##functionName, (void **)(&original##functionName)); \
MH_EnableHook ((void *)where##functionName); \
}
#define INSTALL_HOOK_DYNAMIC(functionName, location) \
{ \
where##functionName = (void *)location; \
INSTALL_HOOK (functionName); \
#define INSTALL_VTABLE_HOOK(className, object, functionName, functionIndex) \
{ \
where##className##functionName = (*(className##functionName ***)object)[functionIndex]; \
INSTALL_HOOK (className##functionName); \
}
#define WRITE_MEMORY(location, type, ...) \
{ \
const type data[] = { __VA_ARGS__ }; \
DWORD oldProtect; \
VirtualProtect ((void *)(location), sizeof (data), PAGE_EXECUTE_READWRITE, &oldProtect); \
memcpy ((void *)(location), data, sizeof (data)); \
VirtualProtect ((void *)(location), sizeof (data), oldProtect, &oldProtect); \
#define READ_MEMORY(location, type) *(type *)location
#define WRITE_MEMORY(location, type, ...) \
{ \
const type data[] = {__VA_ARGS__}; \
DWORD oldProtect; \
VirtualProtect ((void *)(location), sizeof (data), PAGE_EXECUTE_READWRITE, &oldProtect); \
memcpy ((void *)(location), data, sizeof (data)); \
VirtualProtect ((void *)(location), sizeof (data), oldProtect, &oldProtect); \
}
#define WRITE_MEMORY_STRING(location, data, length) \
{ \
DWORD oldProtect; \
VirtualProtect ((void *)(location), length, PAGE_EXECUTE_READWRITE, &oldProtect); \
memcpy ((void *)(location), data, length); \
VirtualProtect ((void *)(location), length, oldProtect, &oldProtect); \
#define WRITE_MEMORY_STRING(location, data, length) \
{ \
DWORD oldProtect; \
VirtualProtect ((void *)(location), length, PAGE_EXECUTE_READWRITE, &oldProtect); \
memcpy ((void *)(location), data, length); \
VirtualProtect ((void *)(location), length, oldProtect, &oldProtect); \
}
#define WRITE_NOP(location, count) \
{ \
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; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
#define WRITE_NOP(location, count) \
{ \
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; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
}
#define WRITE_NULL(location, count) \
{ \
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; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
#define WRITE_NULL(location, count) \
{ \
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; \
VirtualProtect ((void *)(location), (size_t)(count), oldProtect, &oldProtect); \
}
#define COUNTOFARR(arr) sizeof (arr) / sizeof (arr[0])
#define RETURN_FALSE(returnType, callingConvention, functionName, ...) \
returnType callingConvention functionName (__VA_ARGS__) { return 0; }
#define RETURN_TRUE(returnType, callingConvention, functionName, ...) \
returnType callingConvention functionName (__VA_ARGS__) { return 1; }
#define INFO_COLOUR FOREGROUND_GREEN
#define WARNING_COLOUR (FOREGROUND_RED | FOREGROUND_GREEN)
@ -103,16 +102,9 @@ typedef uint64_t u64;
#define printWarning(format, ...) printColour (WARNING_COLOUR, format, __VA_ARGS__)
#define printError(format, ...) printColour (ERROR_COLOUR, format, __VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
char *configPath (char *name);
toml_table_t *openConfig (char *configFilePath);
toml_table_t *openConfigSection (toml_table_t *config, char *sectionName);
bool readConfigBool (toml_table_t *table, char *key, bool notFoundValue);
int64_t readConfigInt (toml_table_t *table, char *key, int64_t notFoundValue);
char *readConfigString (toml_table_t *table, char *key, char *notFoundValue);
toml_table_t *openConfig (std::filesystem::path path);
toml_table_t *openConfigSection (toml_table_t *config, const char *sectionName);
bool readConfigBool (toml_table_t *table, const char *key, bool notFoundValue);
int64_t readConfigInt (toml_table_t *table, const char *key, int64_t notFoundValue);
const char *readConfigString (toml_table_t *table, const char *key, const char *notFoundValue);
void printColour (int colour, const char *format, ...);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,80 @@
#include "helpers.h"
namespace patches::CN_JUN_2023 {
i32 xRes = 1360;
i32 yRes = 768;
bool unlockSongs = true;
bool sharedAudio = true;
bool vsync = false;
u8 *haspBuffer;
HOOK (i32, HaspDecrypt, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_decrypt")) { return 0; }
HOOK (i32, HaspEncrypt, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_encrypt")) { return 0; }
HOOK (i32, HaspLogout, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_logout")) { return 0; }
HOOK (i32, HaspWrite, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_write")) { return 0; }
HOOK (i32, HaspLogin, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_login"), i32, char *, i32 *id) {
*id = 1;
return 0;
}
HOOK (i32, HaspGetInfo, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_get_info"), const char *, const char *, void *, const char **a4) {
*a4 = "type=\"HASP-HL\"";
return 0;
}
HOOK (i32, HaspRead, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_read"), i32, i32, i32 offset, i32 length, void *buffer) {
memcpy (buffer, haspBuffer + offset, length);
return 0;
}
void
Init () {
haspBuffer = (u8 *)malloc (0xD40);
memset (haspBuffer, 0, 0xD40);
strcpy ((char *)(haspBuffer + 0xD00), "284111080001");
u8 crc = 0;
for (int i = 0; i < 62; i++)
crc += haspBuffer[0xD00 + i];
haspBuffer[0xD3E] = crc;
haspBuffer[0xD3F] = haspBuffer[0xD3E] ^ 0xFF;
INSTALL_HOOK (HaspDecrypt);
INSTALL_HOOK (HaspEncrypt);
INSTALL_HOOK (HaspLogout);
INSTALL_HOOK (HaspWrite);
INSTALL_HOOK (HaspLogin);
INSTALL_HOOK (HaspGetInfo);
INSTALL_HOOK (HaspRead);
auto configPath = std::filesystem::current_path () / "config.toml";
toml_table_t *config = openConfig (configPath);
if (config) {
auto res = openConfigSection (config, "res");
if (res) {
xRes = readConfigInt (res, "x", xRes);
yRes = readConfigInt (res, "y", yRes);
}
unlockSongs = readConfigBool (config, "unlock_songs", unlockSongs);
sharedAudio = readConfigBool (config, "shared_audio", sharedAudio);
vsync = readConfigBool (config, "vsync", vsync);
toml_free (config);
}
WRITE_MEMORY (ASLR (0x14003F690), u8, 0xC3); // Skip errors
if (unlockSongs) WRITE_MEMORY (ASLR (0x140425BCD), u8, 0xB0, 0x01);
if (sharedAudio) WRITE_MEMORY (ASLR (0x140777F87), u8, 0xEB);
if (!vsync) WRITE_MEMORY (ASLR (0x1405FC5B9), u8, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x90);
// Move various files to current dir
WRITE_MEMORY (ASLR (0x140C7B158), char, "./SettingChina1.bin");
WRITE_MEMORY (ASLR (0x140C7B2B8), char, "./SettingChina1.bin");
WRITE_MEMORY (ASLR (0x140C7B2A0), char, "./SettingChina2.bin");
WRITE_MEMORY (ASLR (0x140C33C40), char, "./");
WRITE_MEMORY (ASLR (0x140C33C44), char, "./");
// Res
WRITE_MEMORY (ASLR (0x1404A4ED3), i32, xRes);
WRITE_MEMORY (ASLR (0x1404A4EDA), i32, yRes);
// Use TLS v1.2
WRITE_MEMORY (ASLR (0x140369662), u8, 0x10);
}
} // namespace patches::CN_JUN_2023

View File

@ -0,0 +1,9 @@
#include "helpers.h"
namespace patches::JP_NOV_2020 {
void
Init () {
MessageBoxA (0, "08.18 is currently not supported", 0, 0);
ExitProcess (0);
}
} // namespace patches::JP_NOV_2020

8
src/patches/patches.h Normal file
View File

@ -0,0 +1,8 @@
namespace patches {
namespace JP_NOV_2020 {
void Init ();
} // namespace JP_NOV_2020
namespace CN_JUN_2023 {
void Init ();
} // namespace CN_JUN_2023
} // namespace patches

View File

@ -1,533 +0,0 @@
#include "poll.h"
#include "SDL3/SDL_gamepad.h"
#include "SDL3/SDL_joystick.h"
#include "helpers.h"
#include <windows.h>
struct {
const char *string;
uint8_t keycode;
} ConfigKeyboardButtons[] = {
{ "F1", 0x70 }, { "F2", 0x71 }, { "F3", 0x72 }, { "F4", 0x73 }, { "F5", 0x74 }, { "F6", 0x75 },
{ "F7", 0x76 }, { "F8", 0x77 }, { "F9", 0x78 }, { "F10", 0x79 }, { "F11", 0x7A }, { "F12", 0x7B },
{ "NUM1", '1' }, { "NUM2", '2' }, { "NUM3", '3' }, { "NUM4", '4' }, { "NUM5", '5' }, { "NUM6", '6' },
{ "NUM7", '7' }, { "NUM8", '8' }, { "NUM9", '9' }, { "NUM0", '0' }, { "Q", 'Q' }, { "W", 'W' },
{ "E", 'E' }, { "R", 'R' }, { "T", 'T' }, { "Y", 'Y' }, { "U", 'U' }, { "I", 'I' },
{ "O", 'O' }, { "P", 'P' }, { "A", 'A' }, { "S", 'S' }, { "D", 'D' }, { "F", 'F' },
{ "G", 'G' }, { "H", 'H' }, { "J", 'J' }, { "K", 'K' }, { "L", 'L' }, { "Z", 'Z' },
{ "X", 'X' }, { "C", 'C' }, { "V", 'V' }, { "B", 'B' }, { "N", 'N' }, { "M", 'M' },
{ "UPARROW", 0x26 }, { "LEFTARROW", 0x25 }, { "DOWNARROW", 0x28 }, { "RIGHTARROW", 0x27 }, { "ENTER", 0x0D }, { "SPACE", 0x20 },
{ "CONTROL", 0x11 }, { "SHIFT", 0x10 }, { "TAB", 0x09 }, { "ESCAPE", 0x1B },
};
struct {
const char *string;
SDL_GamepadButton button;
} ConfigControllerButtons[] = {
{ "SDL_A", SDL_GAMEPAD_BUTTON_A },
{ "SDL_B", SDL_GAMEPAD_BUTTON_B },
{ "SDL_X", SDL_GAMEPAD_BUTTON_X },
{ "SDL_Y", SDL_GAMEPAD_BUTTON_Y },
{ "SDL_BACK", SDL_GAMEPAD_BUTTON_BACK },
{ "SDL_GUIDE", SDL_GAMEPAD_BUTTON_GUIDE },
{ "SDL_START", SDL_GAMEPAD_BUTTON_START },
{ "SDL_LSTICK_PRESS", SDL_GAMEPAD_BUTTON_LEFT_STICK },
{ "SDL_RSTICK_PRESS", SDL_GAMEPAD_BUTTON_RIGHT_STICK },
{ "SDL_LSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER },
{ "SDL_RSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER },
{ "SDL_DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP },
{ "SDL_DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN },
{ "SDL_DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT },
{ "SDL_DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT },
{ "SDL_MISC", SDL_GAMEPAD_BUTTON_MISC1 },
{ "SDL_PADDLE1", SDL_GAMEPAD_BUTTON_PADDLE1 },
{ "SDL_PADDLE2", SDL_GAMEPAD_BUTTON_PADDLE2 },
{ "SDL_PADDLE3", SDL_GAMEPAD_BUTTON_PADDLE3 },
{ "SDL_PADDLE4", SDL_GAMEPAD_BUTTON_PADDLE4 },
{ "SDL_TOUCHPAD", SDL_GAMEPAD_BUTTON_TOUCHPAD },
};
struct {
const char *string;
enum SDLAxis axis;
} ConfigControllerAXIS[] = {
{ "SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT }, { "SDL_LSTICK_UP", SDL_AXIS_LEFT_UP }, { "SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN },
{ "SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT }, { "SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT }, { "SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP },
{ "SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN }, { "SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT }, { "SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN },
{ "SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN },
};
struct {
const char *string;
enum Scroll scroll;
} ConfigMouseScroll[] = {
{ "SCROLL_UP", MOUSE_SCROLL_UP },
{ "SCROLL_DOWN", MOUSE_SCROLL_DOWN },
};
struct MouseState {
POINT Position;
POINT RelativePosition;
bool ScrolledUp;
bool ScrolledDown;
} currentMouseState, lastMouseState;
bool currentKeyboardState[0xFF];
bool lastKeyboardState[0xFF];
bool currentControllerButtonsState[SDL_GAMEPAD_BUTTON_MAX];
bool lastControllerButtonsState[SDL_GAMEPAD_BUTTON_MAX];
struct SDLAxisState currentControllerAxisState;
struct SDLAxisState lastControllerAxisState;
SDL_Window *window;
SDL_Gamepad *controllers[255];
void
SetConfigValue (toml_table_t *table, char *key, struct Keybindings *keybind) {
toml_array_t *array = toml_array_in (table, key);
if (!array) {
printWarning ("%s (%s): Cannot find array\n", __func__, key);
return;
}
memset (keybind, 0, sizeof (*keybind));
for (int i = 0; i < COUNTOFARR (keybind->buttons); i++)
keybind->buttons[i] = SDL_GAMEPAD_BUTTON_INVALID;
for (int i = 0;; i++) {
toml_datum_t bind = toml_string_at (array, i);
if (!bind.ok) break;
struct ConfigValue value = StringToConfigEnum (bind.u.s);
free (bind.u.s);
switch (value.type) {
case keycode:
for (int i = 0; i < COUNTOFARR (keybind->keycodes); i++) {
if (keybind->keycodes[i] == 0) {
keybind->keycodes[i] = value.keycode;
break;
}
}
break;
case button:
for (int i = 0; i < COUNTOFARR (keybind->buttons); i++) {
if (keybind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) {
keybind->buttons[i] = value.button;
break;
}
}
break;
case axis:
for (int i = 0; i < COUNTOFARR (keybind->axis); i++) {
if (keybind->axis[i] == 0) {
keybind->axis[i] = value.axis;
break;
}
}
case scroll:
for (int i = 0; i < COUNTOFARR (keybind->scroll); i++) {
if (keybind->scroll[i] == 0) {
keybind->scroll[i] = value.scroll;
break;
}
}
break;
default: break;
}
}
}
bool
InitializePoll (void *windowHandle) {
bool hasRumble = true;
SDL_SetMainReady ();
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
hasRumble = false;
} else {
printError ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): "
"%s\n",
SDL_GetError ());
return false;
}
}
if (SDL_AddGamepadMappingsFromFile (configPath ("gamecontrollerdb.txt")) == -1)
printError ("%s (): Cannot read gamecontrollerdb.txt\n", __func__);
int count = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks (&count);
if (joysticks == 0) { return hasRumble; }
for (int i = 0; i < count; i++) {
if (!SDL_IsGamepad (joysticks[i])) continue;
SDL_Gamepad *controller = SDL_OpenGamepad (joysticks[i]);
if (!controller) { continue; }
printInfo ("%s: %s\n", SDL_GetGamepadName (controller), SDL_GetGamepadMapping (controller));
controllers[i] = controller;
}
window = SDL_CreateWindowFrom (windowHandle);
if (window != NULL) SDL_SetWindowResizable (window, true);
else printError ("SDL_CreateWindowFrom (windowHandle): %s\n", SDL_GetError ());
return hasRumble;
}
void
UpdatePoll (void *DivaWindowHandle) {
if (DivaWindowHandle == NULL || GetForegroundWindow () != DivaWindowHandle) return;
memcpy (lastKeyboardState, currentKeyboardState, 255);
memcpy (lastControllerButtonsState, currentControllerButtonsState, 21);
lastMouseState = currentMouseState;
lastControllerAxisState = currentControllerAxisState;
for (uint8_t i = 0; i < 0xFF; i++)
currentKeyboardState[i] = GetAsyncKeyState (i) != 0;
currentMouseState.ScrolledUp = false;
currentMouseState.ScrolledDown = false;
SDL_Event event;
while (SDL_PollEvent (&event) != 0) {
switch (event.type) {
case SDL_GAMEPADADDED:
if (!SDL_IsGamepad (event.cdevice.which)) break;
SDL_Gamepad *controller = SDL_OpenGamepad (event.cdevice.which);
if (!controller) { continue; }
printInfo ("%s: %s\n", SDL_GetGamepadName (controller), SDL_GetGamepadMapping (controller));
controllers[event.cdevice.which] = controller;
break;
case SDL_GAMEPADREMOVED:
printInfo ("%s: %s\n", SDL_GetGamepadName (controllers[event.cdevice.which]), SDL_GetGamepadMapping (controllers[event.cdevice.which]));
if (!SDL_IsGamepad (event.cdevice.which)) break;
SDL_CloseGamepad (controllers[event.cdevice.which]);
break;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) currentMouseState.ScrolledUp = true;
else if (event.wheel.y < 0) currentMouseState.ScrolledDown = true;
break;
case SDL_GAMEPADBUTTONUP:
case SDL_GAMEPADBUTTONDOWN:
currentControllerButtonsState[event.cbutton.button] = event.cbutton.state;
printInfo ("%s\n", SDL_GetGamepadStringForButton (event.cbutton.button));
break;
case SDL_GAMEPADAXISMOTION:
if (event.caxis.value > 8000) {
switch (event.caxis.axis) {
case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = 1; break;
case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = 1; break;
case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = 1; break;
case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = 1; break;
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = 1; break;
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = 1; break;
}
} else if (event.caxis.value < -8000) {
switch (event.caxis.axis) {
case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftLeft = 1; break;
case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftUp = 1; break;
case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightLeft = 1; break;
case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightUp = 1; break;
}
} else {
switch (event.caxis.axis) {
case SDL_GAMEPAD_AXIS_LEFTX:
currentControllerAxisState.LeftRight = 0;
currentControllerAxisState.LeftLeft = 0;
break;
case SDL_GAMEPAD_AXIS_LEFTY:
currentControllerAxisState.LeftDown = 0;
currentControllerAxisState.LeftUp = 0;
break;
case SDL_GAMEPAD_AXIS_RIGHTX:
currentControllerAxisState.RightRight = 0;
currentControllerAxisState.RightLeft = 0;
break;
case SDL_GAMEPAD_AXIS_RIGHTY:
currentControllerAxisState.RightDown = 0;
currentControllerAxisState.RightUp = 0;
break;
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = 0; break;
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = 0; break;
}
}
break;
}
}
}
void
DisposePoll () {
SDL_DestroyWindow (window);
SDL_Quit ();
}
struct ConfigValue
StringToConfigEnum (char *value) {
struct ConfigValue rval = { 0 };
for (int i = 0; i < COUNTOFARR (ConfigKeyboardButtons); ++i)
if (!strcmp (value, ConfigKeyboardButtons[i].string)) {
rval.type = keycode;
rval.keycode = ConfigKeyboardButtons[i].keycode;
return rval;
}
for (int i = 0; i < COUNTOFARR (ConfigControllerButtons); ++i)
if (!strcmp (value, ConfigControllerButtons[i].string)) {
rval.type = button;
rval.button = ConfigControllerButtons[i].button;
return rval;
}
for (int i = 0; i < COUNTOFARR (ConfigControllerAXIS); ++i)
if (!strcmp (value, ConfigControllerAXIS[i].string)) {
rval.type = axis;
rval.axis = ConfigControllerAXIS[i].axis;
return rval;
}
for (int i = 0; i < COUNTOFARR (ConfigMouseScroll); ++i)
if (!strcmp (value, ConfigMouseScroll[i].string)) {
rval.type = scroll;
rval.scroll = ConfigMouseScroll[i].scroll;
return rval;
}
printError ("%s (%s): Unknown value\n", __func__, value);
return rval;
}
struct InternalButtonState
GetInternalButtonState (struct Keybindings bindings) {
struct InternalButtonState buttons = { 0 };
for (int i = 0; i < COUNTOFARR (ConfigKeyboardButtons); i++) {
if (bindings.keycodes[i] == 0) continue;
if (KeyboardIsReleased (bindings.keycodes[i])) buttons.Released = 1;
if (KeyboardIsDown (bindings.keycodes[i])) buttons.Down = 1;
if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = 1;
}
for (int i = 0; i < COUNTOFARR (ConfigControllerButtons); i++) {
if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue;
if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = 1;
if (ControllerButtonIsDown (bindings.buttons[i])) buttons.Down = 1;
if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = 1;
}
for (int i = 0; i < COUNTOFARR (ConfigControllerAXIS); i++) {
if (bindings.axis[i] == 0) continue;
if (ControllerAxisIsReleased (bindings.axis[i])) buttons.Released = 1;
if (ControllerAxisIsDown (bindings.axis[i])) buttons.Down = 1;
if (ControllerAxisIsTapped (bindings.axis[i])) buttons.Tapped = 1;
}
for (int 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;
}
return buttons;
}
void
SetRumble (int left, int right) {
for (int i = 0; i < COUNTOFARR (controllers); i++) {
if (!controllers[i] || !SDL_GamepadHasRumble (controllers[i])) continue;
SDL_RumbleGamepad (controllers[i], left, right, 1000);
}
}
bool
KeyboardIsDown (uint8_t keycode) {
return currentKeyboardState[keycode];
}
bool
KeyboardIsUp (uint8_t keycode) {
return !KeyboardIsDown (keycode);
}
bool
KeyboardIsTapped (uint8_t keycode) {
return KeyboardIsDown (keycode) && KeyboardWasUp (keycode);
}
bool
KeyboardIsReleased (uint8_t keycode) {
return KeyboardIsUp (keycode) && KeyboardWasDown (keycode);
}
bool
KeyboardWasDown (uint8_t keycode) {
return lastKeyboardState[keycode];
}
bool
KeyboardWasUp (uint8_t keycode) {
return !KeyboardWasDown (keycode);
}
POINT
GetMousePosition () { return currentMouseState.Position; }
POINT
GetLastMousePosition () { return lastMouseState.Position; }
POINT
GetMouseRelativePosition () { return currentMouseState.RelativePosition; }
POINT
GetLastMouseRelativePosition () { return lastMouseState.RelativePosition; }
void
SetMousePosition (POINT newPosition) {
currentMouseState.Position = newPosition;
}
bool
GetMouseScrollUp () {
return currentMouseState.ScrolledUp;
}
bool
GetMouseScrollDown () {
return currentMouseState.ScrolledDown;
}
bool
GetWasMouseScrollUp () {
return lastMouseState.ScrolledUp;
}
bool
GetWasMouseScrollDown () {
return lastMouseState.ScrolledDown;
}
bool
GetMouseScrollIsReleased (enum Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return !GetMouseScrollUp () && GetWasMouseScrollUp ();
else return !GetMouseScrollDown () && GetWasMouseScrollDown ();
}
bool
GetMouseScrollIsDown (enum Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
else return GetMouseScrollDown ();
}
bool
GetMouseScrollIsTapped (enum Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp () && !GetWasMouseScrollUp ();
else return GetMouseScrollDown () && !GetWasMouseScrollDown ();
}
bool
ControllerButtonIsDown (SDL_GamepadButton button) {
return currentControllerButtonsState[button];
}
bool
ControllerButtonIsUp (SDL_GamepadButton button) {
return !ControllerButtonIsDown (button);
}
bool
ControllerButtonWasDown (SDL_GamepadButton button) {
return lastControllerButtonsState[button];
}
bool
ControllerButtonWasUp (SDL_GamepadButton button) {
return !ControllerButtonWasDown (button);
}
bool
ControllerButtonIsTapped (SDL_GamepadButton button) {
return ControllerButtonIsDown (button) && ControllerButtonWasUp (button);
}
bool
ControllerButtonIsReleased (SDL_GamepadButton button) {
return ControllerButtonIsUp (button) && ControllerButtonWasDown (button);
}
bool
ControllerAxisIsDown (enum SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT: return currentControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT: return currentControllerAxisState.LeftRight;
case SDL_AXIS_LEFT_UP: return currentControllerAxisState.LeftUp;
case SDL_AXIS_LEFT_DOWN: return currentControllerAxisState.LeftDown;
case SDL_AXIS_RIGHT_LEFT: return currentControllerAxisState.RightLeft;
case SDL_AXIS_RIGHT_RIGHT: return currentControllerAxisState.RightRight;
case SDL_AXIS_RIGHT_UP: return currentControllerAxisState.RightUp;
case SDL_AXIS_RIGHT_DOWN: return currentControllerAxisState.RightDown;
case SDL_AXIS_LTRIGGER_DOWN: return currentControllerAxisState.LTriggerDown;
case SDL_AXIS_RTRIGGER_DOWN: return currentControllerAxisState.RTriggerDown;
default: return false;
}
}
bool
ControllerAxisIsUp (enum SDLAxis axis) {
return !ControllerAxisIsDown (axis);
}
bool
ControllerAxisWasDown (enum SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT: return lastControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT: return lastControllerAxisState.LeftRight;
case SDL_AXIS_LEFT_UP: return lastControllerAxisState.LeftUp;
case SDL_AXIS_LEFT_DOWN: return lastControllerAxisState.LeftDown;
case SDL_AXIS_RIGHT_LEFT: return lastControllerAxisState.RightLeft;
case SDL_AXIS_RIGHT_RIGHT: return lastControllerAxisState.RightRight;
case SDL_AXIS_RIGHT_UP: return lastControllerAxisState.RightUp;
case SDL_AXIS_RIGHT_DOWN: return lastControllerAxisState.RightDown;
case SDL_AXIS_LTRIGGER_DOWN: return lastControllerAxisState.LTriggerDown;
case SDL_AXIS_RTRIGGER_DOWN: return lastControllerAxisState.RTriggerDown;
default: return false;
}
}
bool
ControllerAxisWasUp (enum SDLAxis axis) {
return !ControllerAxisWasDown (axis);
}
bool
ControllerAxisIsTapped (enum SDLAxis axis) {
return ControllerAxisIsDown (axis) && ControllerAxisWasUp (axis);
}
bool
ControllerAxisIsReleased (enum SDLAxis axis) {
return ControllerAxisIsUp (axis) && ControllerAxisWasDown (axis);
}
bool
IsButtonTapped (struct Keybindings bindings) {
return GetInternalButtonState (bindings).Tapped;
}
bool
IsButtonReleased (struct Keybindings bindings) {
return GetInternalButtonState (bindings).Released;
}
bool
IsButtonDown (struct Keybindings bindings) {
return GetInternalButtonState (bindings).Down;
}

628
src/poll.cpp Normal file
View File

@ -0,0 +1,628 @@
#include "poll.h"
#include "helpers.h"
#include <windows.h>
struct {
const char *string;
uint8_t keycode;
} ConfigKeyboardButtons[] = {
{"F1", VK_F1},
{"F2", VK_F2},
{"F3", VK_F3},
{"F4", VK_F4},
{"F5", VK_F5},
{"F6", VK_F6},
{"F7", VK_F7},
{"F8", VK_F8},
{"F9", VK_F9},
{"F10", VK_F10},
{"F11", VK_F11},
{"F12", VK_F12},
{"NUM1", '1'},
{"NUM2", '2'},
{"NUM3", '3'},
{"NUM4", '4'},
{"NUM5", '5'},
{"NUM6", '6'},
{"NUM7", '7'},
{"NUM8", '8'},
{"NUM9", '9'},
{"NUM0", '0'},
{"Q", 'Q'},
{"W", 'W'},
{"E", 'E'},
{"R", 'R'},
{"T", 'T'},
{"Y", 'Y'},
{"U", 'U'},
{"I", 'I'},
{"O", 'O'},
{"P", 'P'},
{"A", 'A'},
{"S", 'S'},
{"D", 'D'},
{"F", 'F'},
{"G", 'G'},
{"H", 'H'},
{"J", 'J'},
{"K", 'K'},
{"L", 'L'},
{"Z", 'Z'},
{"X", 'X'},
{"C", 'C'},
{"V", 'V'},
{"B", 'B'},
{"N", 'N'},
{"M", 'M'},
{"UPARROW", VK_UP},
{"LEFTARROW", VK_LEFT},
{"DOWNARROW", VK_DOWN},
{"RIGHTARROW", VK_RIGHT},
{"ENTER", VK_RETURN},
{"SPACE", VK_SPACE},
{"CONTROL", VK_CONTROL},
{"SHIFT", VK_SHIFT},
{"TAB", VK_TAB},
{"ESCAPE", VK_ESCAPE},
};
struct {
const char *string;
SDL_GameControllerButton button;
} ConfigControllerButtons[] = {
{"SDL_A", SDL_CONTROLLER_BUTTON_A},
{"SDL_B", SDL_CONTROLLER_BUTTON_B},
{"SDL_X", SDL_CONTROLLER_BUTTON_X},
{"SDL_Y", SDL_CONTROLLER_BUTTON_Y},
{"SDL_BACK", SDL_CONTROLLER_BUTTON_BACK},
{"SDL_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE},
{"SDL_START", SDL_CONTROLLER_BUTTON_START},
{"SDL_LSTICK_PRESS", SDL_CONTROLLER_BUTTON_LEFTSTICK},
{"SDL_RSTICK_PRESS", SDL_CONTROLLER_BUTTON_RIGHTSTICK},
{"SDL_LSHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
{"SDL_RSHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
{"SDL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP},
{"SDL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN},
{"SDL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT},
{"SDL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
{"SDL_MISC", SDL_CONTROLLER_BUTTON_MISC1},
{"SDL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1},
{"SDL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2},
{"SDL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3},
{"SDL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4},
{"SDL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD},
};
struct {
const char *string;
SDLAxis axis;
} ConfigControllerAXIS[] = {
{"SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN}, {"SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT},
{"SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP}, {"SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT},
{"SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN}, {"SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN},
};
struct {
const char *string;
Scroll scroll;
} ConfigMouseScroll[] = {
{"SCROLL_UP", MOUSE_SCROLL_UP},
{"SCROLL_DOWN", MOUSE_SCROLL_DOWN},
};
struct MouseState {
POINT Position;
POINT RelativePosition;
bool ScrolledUp;
bool ScrolledDown;
} currentMouseState, lastMouseState;
bool currentKeyboardState[0xFF];
bool lastKeyboardState[0xFF];
bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX];
bool lastControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX];
SDLAxisState currentControllerAxisState;
SDLAxisState lastControllerAxisState;
SDL_Window *window;
SDL_GameController *controllers[255];
void
SetConfigValue (toml_table_t *table, const char *key, Keybindings *keybind) {
toml_array_t *array = toml_array_in (table, key);
if (!array) {
printWarning ("%s (%s): Cannot find array\n", __func__, key);
return;
}
memset (keybind, 0, sizeof (*keybind));
for (size_t i = 0; i < COUNTOFARR (keybind->buttons); i++)
keybind->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);
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;
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;
break;
}
}
break;
case axis:
for (size_t i = 0; i < COUNTOFARR (keybind->axis); i++) {
if (keybind->axis[i] == 0) {
keybind->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;
break;
}
}
break;
default:
break;
}
}
}
bool
InitializePoll (HWND windowHandle) {
bool hasRumble = true;
SDL_SetMainReady ();
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
hasRumble = false;
} else {
printError ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): "
"%s\n",
SDL_GetError ());
return false;
}
}
auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) printError ("%s (): Cannot read gamecontrollerdb.txt\n", __func__);
SDL_GameControllerEventState (SDL_ENABLE);
SDL_JoystickEventState (SDL_ENABLE);
for (int i = 0; i < SDL_NumJoysticks (); i++) {
if (!SDL_IsGameController (i)) continue;
SDL_GameController *controller = SDL_GameControllerOpen (i);
if (!controller) {
printWarning ("Could not open gamecontroller %s: %s\n", SDL_GameControllerNameForIndex (i), SDL_GetError ());
continue;
}
controllers[i] = controller;
}
window = SDL_CreateWindowFrom (windowHandle);
if (window != NULL) SDL_SetWindowResizable (window, SDL_TRUE);
else printError ("SDL_CreateWindowFrom (windowHandle): %s\n", SDL_GetError ());
atexit (DisposePoll);
return hasRumble;
}
void
UpdatePoll (HWND windowHandle) {
if (windowHandle == NULL || GetForegroundWindow () != windowHandle) return;
memcpy (lastKeyboardState, currentKeyboardState, 255);
memcpy (lastControllerButtonsState, currentControllerButtonsState, 21);
lastMouseState = currentMouseState;
lastControllerAxisState = currentControllerAxisState;
for (uint8_t i = 0; i < 0xFF; i++)
currentKeyboardState[i] = GetAsyncKeyState (i) != 0;
currentMouseState.ScrolledUp = false;
currentMouseState.ScrolledDown = false;
GetCursorPos (&currentMouseState.Position);
ScreenToClient (windowHandle, &currentMouseState.Position);
SDL_Event event;
SDL_GameController *controller;
while (SDL_PollEvent (&event) != 0) {
switch (event.type) {
case SDL_CONTROLLERDEVICEADDED:
if (!SDL_IsGameController (event.cdevice.which)) break;
controller = SDL_GameControllerOpen (event.cdevice.which);
if (!controller) {
printError ("%s (): Could not open gamecontroller %s: %s\n", __func__, SDL_GameControllerNameForIndex (event.cdevice.which), SDL_GetError ());
continue;
}
controllers[event.cdevice.which] = controller;
break;
case SDL_CONTROLLERDEVICEREMOVED:
if (!SDL_IsGameController (event.cdevice.which)) break;
SDL_GameControllerClose (controllers[event.cdevice.which]);
break;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0) currentMouseState.ScrolledUp = true;
else if (event.wheel.y < 0) currentMouseState.ScrolledDown = true;
break;
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERBUTTONDOWN:
currentControllerButtonsState[event.cbutton.button] = event.cbutton.state;
break;
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;
}
} 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;
}
} else {
switch (event.caxis.axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
currentControllerAxisState.LeftRight = 0;
currentControllerAxisState.LeftLeft = 0;
break;
case SDL_CONTROLLER_AXIS_LEFTY:
currentControllerAxisState.LeftDown = 0;
currentControllerAxisState.LeftUp = 0;
break;
case SDL_CONTROLLER_AXIS_RIGHTX:
currentControllerAxisState.RightRight = 0;
currentControllerAxisState.RightLeft = 0;
break;
case SDL_CONTROLLER_AXIS_RIGHTY:
currentControllerAxisState.RightDown = 0;
currentControllerAxisState.RightUp = 0;
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
currentControllerAxisState.LTriggerDown = 0;
break;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
currentControllerAxisState.RTriggerDown = 0;
break;
}
}
break;
}
}
}
void
DisposePoll () {
SDL_DestroyWindow (window);
SDL_Quit ();
}
ConfigValue
StringToConfigEnum (const char *value) {
ConfigValue rval;
for (size_t i = 0; i < COUNTOFARR (ConfigKeyboardButtons); ++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)) {
rval.type = button;
rval.button = ConfigControllerButtons[i].button;
return rval;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerAXIS); ++i)
if (!strcmp (value, ConfigControllerAXIS[i].string)) {
rval.type = axis;
rval.axis = ConfigControllerAXIS[i].axis;
return rval;
}
for (size_t i = 0; i < COUNTOFARR (ConfigMouseScroll); ++i)
if (!strcmp (value, ConfigMouseScroll[i].string)) {
rval.type = scroll;
rval.scroll = ConfigMouseScroll[i].scroll;
return rval;
}
printError ("%s (%s): Unknown value\n", __func__, value);
return rval;
}
InternalButtonState
GetInternalButtonState (Keybindings bindings) {
InternalButtonState buttons = {0};
for (size_t i = 0; i < COUNTOFARR (ConfigKeyboardButtons); i++) {
if (bindings.keycodes[i] == 0) continue;
if (KeyboardIsReleased (bindings.keycodes[i])) buttons.Released = 1;
if (KeyboardIsDown (bindings.keycodes[i])) buttons.Down = 1;
if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = 1;
}
for (size_t i = 0; i < COUNTOFARR (ConfigControllerButtons); i++) {
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = 1;
if (ControllerButtonIsDown (bindings.buttons[i])) buttons.Down = 1;
if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = 1;
}
for (size_t i = 0; i < COUNTOFARR (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;
}
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;
}
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;
SDL_GameControllerRumble (controllers[i], left, right, length);
}
}
bool
KeyboardIsDown (uint8_t keycode) {
return currentKeyboardState[keycode];
}
bool
KeyboardIsUp (uint8_t keycode) {
return !KeyboardIsDown (keycode);
}
bool
KeyboardIsTapped (uint8_t keycode) {
return KeyboardIsDown (keycode) && KeyboardWasUp (keycode);
}
bool
KeyboardIsReleased (uint8_t keycode) {
return KeyboardIsUp (keycode) && KeyboardWasDown (keycode);
}
bool
KeyboardWasDown (uint8_t keycode) {
return lastKeyboardState[keycode];
}
bool
KeyboardWasUp (uint8_t keycode) {
return !KeyboardWasDown (keycode);
}
POINT
GetMousePosition () { return currentMouseState.Position; }
POINT
GetLastMousePosition () { return lastMouseState.Position; }
POINT
GetMouseRelativePosition () { return currentMouseState.RelativePosition; }
POINT
GetLastMouseRelativePosition () { return lastMouseState.RelativePosition; }
void
SetMousePosition (POINT newPosition) {
currentMouseState.Position = newPosition;
}
bool
GetMouseScrollUp () {
return currentMouseState.ScrolledUp;
}
bool
GetMouseScrollDown () {
return currentMouseState.ScrolledDown;
}
bool
GetWasMouseScrollUp () {
return lastMouseState.ScrolledUp;
}
bool
GetWasMouseScrollDown () {
return lastMouseState.ScrolledDown;
}
bool
GetMouseScrollIsReleased (Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return !GetMouseScrollUp () && GetWasMouseScrollUp ();
else return !GetMouseScrollDown () && GetWasMouseScrollDown ();
}
bool
GetMouseScrollIsDown (Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp ();
else return GetMouseScrollDown ();
}
bool
GetMouseScrollIsTapped (Scroll scroll) {
if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp () && !GetWasMouseScrollUp ();
else return GetMouseScrollDown () && !GetWasMouseScrollDown ();
}
bool
ControllerButtonIsDown (SDL_GameControllerButton button) {
return currentControllerButtonsState[button];
}
bool
ControllerButtonIsUp (SDL_GameControllerButton button) {
return !ControllerButtonIsDown (button);
}
bool
ControllerButtonWasDown (SDL_GameControllerButton button) {
return lastControllerButtonsState[button];
}
bool
ControllerButtonWasUp (SDL_GameControllerButton button) {
return !ControllerButtonWasDown (button);
}
bool
ControllerButtonIsTapped (SDL_GameControllerButton button) {
return ControllerButtonIsDown (button) && ControllerButtonWasUp (button);
}
bool
ControllerButtonIsReleased (SDL_GameControllerButton button) {
return ControllerButtonIsUp (button) && ControllerButtonWasDown (button);
}
float
ControllerAxisIsDown (SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT:
return currentControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT:
return currentControllerAxisState.LeftRight;
case SDL_AXIS_LEFT_UP:
return currentControllerAxisState.LeftUp;
case SDL_AXIS_LEFT_DOWN:
return currentControllerAxisState.LeftDown;
case SDL_AXIS_RIGHT_LEFT:
return currentControllerAxisState.RightLeft;
case SDL_AXIS_RIGHT_RIGHT:
return currentControllerAxisState.RightRight;
case SDL_AXIS_RIGHT_UP:
return currentControllerAxisState.RightUp;
case SDL_AXIS_RIGHT_DOWN:
return currentControllerAxisState.RightDown;
case SDL_AXIS_LTRIGGER_DOWN:
return currentControllerAxisState.LTriggerDown;
case SDL_AXIS_RTRIGGER_DOWN:
return currentControllerAxisState.RTriggerDown;
default:
return false;
}
}
bool
ControllerAxisIsUp (SDLAxis axis) {
return !ControllerAxisIsDown (axis);
}
float
ControllerAxisWasDown (SDLAxis axis) {
switch (axis) {
case SDL_AXIS_LEFT_LEFT:
return lastControllerAxisState.LeftLeft;
case SDL_AXIS_LEFT_RIGHT:
return lastControllerAxisState.LeftRight;
case SDL_AXIS_LEFT_UP:
return lastControllerAxisState.LeftUp;
case SDL_AXIS_LEFT_DOWN:
return lastControllerAxisState.LeftDown;
case SDL_AXIS_RIGHT_LEFT:
return lastControllerAxisState.RightLeft;
case SDL_AXIS_RIGHT_RIGHT:
return lastControllerAxisState.RightRight;
case SDL_AXIS_RIGHT_UP:
return lastControllerAxisState.RightUp;
case SDL_AXIS_RIGHT_DOWN:
return lastControllerAxisState.RightDown;
case SDL_AXIS_LTRIGGER_DOWN:
return lastControllerAxisState.LTriggerDown;
case SDL_AXIS_RTRIGGER_DOWN:
return lastControllerAxisState.RTriggerDown;
default:
return false;
}
}
bool
ControllerAxisWasUp (SDLAxis axis) {
return !ControllerAxisWasDown (axis);
}
bool
ControllerAxisIsTapped (SDLAxis axis) {
return ControllerAxisIsDown (axis) && ControllerAxisWasUp (axis);
}
bool
ControllerAxisIsReleased (SDLAxis axis) {
return ControllerAxisIsUp (axis) && ControllerAxisWasDown (axis);
}
bool
IsButtonTapped (Keybindings bindings) {
return GetInternalButtonState (bindings).Tapped;
}
bool
IsButtonReleased (Keybindings bindings) {
return GetInternalButtonState (bindings).Released;
}
float
IsButtonDown (Keybindings bindings) {
return GetInternalButtonState (bindings).Down;
}

View File

@ -1,106 +1,103 @@
#pragma once
#include <SDL3/SDL.h>
#include <stdbool.h>
#include <stdint.h>
#include <toml.h>
#include <windows.h>
enum SDLAxis {
SDL_AXIS_NULL,
SDL_AXIS_LEFT_LEFT,
SDL_AXIS_LEFT_RIGHT,
SDL_AXIS_LEFT_UP,
SDL_AXIS_LEFT_DOWN,
SDL_AXIS_RIGHT_LEFT,
SDL_AXIS_RIGHT_RIGHT,
SDL_AXIS_RIGHT_UP,
SDL_AXIS_RIGHT_DOWN,
SDL_AXIS_LTRIGGER_DOWN,
SDL_AXIS_RTRIGGER_DOWN,
SDL_AXIS_MAX
};
struct SDLAxisState {
unsigned int LeftLeft : 1;
unsigned int LeftRight : 1;
unsigned int LeftUp : 1;
unsigned int LeftDown : 1;
unsigned int RightLeft : 1;
unsigned int RightRight : 1;
unsigned int RightUp : 1;
unsigned int RightDown : 1;
unsigned int LTriggerDown : 1;
unsigned int RTriggerDown : 1;
};
enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN };
struct Keybindings {
uint8_t keycodes[255];
SDL_GamepadButton buttons[255];
enum SDLAxis axis[255];
enum Scroll scroll[2];
};
typedef struct Keybindings Keybindings;
enum EnumType { none, keycode, button, axis, scroll };
struct ConfigValue {
enum EnumType type;
union {
uint8_t keycode;
SDL_GamepadButton button;
enum SDLAxis axis;
enum Scroll scroll;
};
};
struct InternalButtonState {
unsigned int Released : 1;
unsigned int Down : 1;
unsigned int Tapped : 1;
};
bool InitializePoll (void *DivaWindowHandle);
void UpdatePoll (void *DivaWindowHandle);
void DisposePoll ();
struct ConfigValue StringToConfigEnum (char *value);
void SetConfigValue (toml_table_t *table, char *key, struct Keybindings *keybind);
struct InternalButtonState GetInternalButtonState (struct Keybindings bindings);
void SetRumble (int left, int right);
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);
POINT GetMousePosition ();
POINT GetLastMousePosition ();
POINT GetMouseRelativePosition ();
POINT GetLastMouseRelativePosition ();
void SetMousePosition (POINT newPosition);
bool GetMouseScrollUp ();
bool GetMouseScrollDown ();
bool GetWasMouseScrollUp ();
bool GetWasMouseScrollDown ();
bool GetMouseScrollIsReleased (enum Scroll scroll);
bool GetMouseScrollIsDown (enum Scroll scroll);
bool GetMouseScrollIsTapped (enum Scroll scroll);
bool ControllerButtonIsDown (SDL_GamepadButton button);
bool ControllerButtonIsUp (SDL_GamepadButton button);
bool ControllerButtonWasDown (SDL_GamepadButton button);
bool ControllerButtonWasUp (SDL_GamepadButton button);
bool ControllerButtonIsTapped (SDL_GamepadButton button);
bool ControllerButtonIsReleased (SDL_GamepadButton button);
bool ControllerAxisIsDown (enum SDLAxis axis);
bool ControllerAxisIsUp (enum SDLAxis axis);
bool ControllerAxisWasDown (enum SDLAxis axis);
bool ControllerAxisWasUp (enum SDLAxis axis);
bool ControllerAxisIsTapped (enum SDLAxis axis);
bool ControllerAxisIsReleased (enum SDLAxis axis);
bool IsButtonTapped (struct Keybindings bindings);
bool IsButtonReleased (struct Keybindings bindings);
bool IsButtonDown (struct Keybindings bindings);
#pragma once
#include <SDL.h>
#include <stdbool.h>
#include <stdint.h>
#include <toml.h>
#include <windows.h>
enum SDLAxis {
SDL_AXIS_NULL,
SDL_AXIS_LEFT_LEFT,
SDL_AXIS_LEFT_RIGHT,
SDL_AXIS_LEFT_UP,
SDL_AXIS_LEFT_DOWN,
SDL_AXIS_RIGHT_LEFT,
SDL_AXIS_RIGHT_RIGHT,
SDL_AXIS_RIGHT_UP,
SDL_AXIS_RIGHT_DOWN,
SDL_AXIS_LTRIGGER_DOWN,
SDL_AXIS_RTRIGGER_DOWN,
SDL_AXIS_MAX
};
struct SDLAxisState {
float LeftLeft;
float LeftRight;
float LeftUp;
float LeftDown;
float RightLeft;
float RightRight;
float RightUp;
float RightDown;
float LTriggerDown;
float RTriggerDown;
};
enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN };
struct Keybindings {
uint8_t keycodes[255];
SDL_GameControllerButton buttons[255];
SDLAxis axis[255];
Scroll scroll[2];
};
enum EnumType { none, keycode, button, axis, scroll };
struct ConfigValue {
EnumType type;
union {
uint8_t keycode;
SDL_GameControllerButton button;
SDLAxis axis;
Scroll scroll;
};
};
struct InternalButtonState {
float Down;
bool Released;
bool Tapped;
};
bool InitializePoll (HWND windowHandle);
void UpdatePoll (HWND windowHandle);
void DisposePoll ();
ConfigValue StringToConfigEnum (const char *value);
void SetConfigValue (toml_table_t *table, const char *key, Keybindings *keybind);
InternalButtonState GetInternalButtonState (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);
POINT GetMousePosition ();
POINT GetLastMousePosition ();
POINT GetMouseRelativePosition ();
POINT GetLastMouseRelativePosition ();
void SetMousePosition (POINT newPosition);
bool GetMouseScrollUp ();
bool GetMouseScrollDown ();
bool GetWasMouseScrollUp ();
bool GetWasMouseScrollDown ();
bool GetMouseScrollIsReleased (Scroll scroll);
bool GetMouseScrollIsDown (Scroll scroll);
bool GetMouseScrollIsTapped (Scroll scroll);
bool ControllerButtonIsDown (SDL_GameControllerButton button);
bool ControllerButtonIsUp (SDL_GameControllerButton button);
bool ControllerButtonWasDown (SDL_GameControllerButton button);
bool ControllerButtonWasUp (SDL_GameControllerButton button);
bool ControllerButtonIsTapped (SDL_GameControllerButton button);
bool ControllerButtonIsReleased (SDL_GameControllerButton button);
float ControllerAxisIsDown (SDLAxis axis);
bool ControllerAxisIsUp (SDLAxis axis);
float ControllerAxisWasDown (SDLAxis axis);
bool ControllerAxisWasUp (SDLAxis axis);
bool ControllerAxisIsTapped (SDLAxis axis);
bool ControllerAxisIsReleased (SDLAxis axis);
bool IsButtonTapped (Keybindings bindings);
bool IsButtonReleased (Keybindings bindings);
float IsButtonDown (Keybindings bindings);

4
subprojects/minhook.wrap Executable file
View File

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

View File

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

View File

@ -0,0 +1,14 @@
+++ 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,
+)

15
subprojects/sdl2.wrap Normal file
View File

@ -0,0 +1,15 @@
[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

4
subprojects/tomlc99.wrap Normal file
View File

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

13
subprojects/xxhash.wrap Normal file
View File

@ -0,0 +1,13 @@
[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 +0,0 @@
Subproject commit 894902820a3ea2f1ec470cd7fe338bde54045cf5