add ll3 hook
This commit is contained in:
parent
05d337c499
commit
068e3f3963
16
Package.mk
16
Package.mk
@ -20,6 +20,21 @@ $(BUILD_DIR_ZIP)/siva.zip:
|
|||||||
$(V)strip $(BUILD_DIR_ZIP)/siva/*.{exe,dll}
|
$(V)strip $(BUILD_DIR_ZIP)/siva/*.{exe,dll}
|
||||||
$(V)cd $(BUILD_DIR_ZIP)/siva ; zip -r ../siva.zip *
|
$(V)cd $(BUILD_DIR_ZIP)/siva ; zip -r ../siva.zip *
|
||||||
|
|
||||||
|
$(BUILD_DIR_ZIP)/ll3.zip:
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/ll3
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/ll3/DEVICE
|
||||||
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
|
$(BUILD_DIR_64)/ll3hook/ll3hook.dll \
|
||||||
|
$(DIST_DIR)/ll3/taitools.ini \
|
||||||
|
$(DIST_DIR)/ll3/start.bat \
|
||||||
|
$(BUILD_DIR_ZIP)/ll3
|
||||||
|
$(V)cp pki/billing.pub \
|
||||||
|
pki/ca.crt \
|
||||||
|
$(BUILD_DIR_ZIP)/ll3/DEVICE
|
||||||
|
$(V)strip $(BUILD_DIR_ZIP)/ll3/*.{exe,dll}
|
||||||
|
$(V)cd $(BUILD_DIR_ZIP)/ll3 ; zip -r ../ll3.zip *
|
||||||
|
|
||||||
$(BUILD_DIR_ZIP)/doc.zip: \
|
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||||
$(DOC_DIR)/config \
|
$(DOC_DIR)/config \
|
||||||
| $(zipdir)/
|
| $(zipdir)/
|
||||||
@ -28,6 +43,7 @@ $(BUILD_DIR_ZIP)/doc.zip: \
|
|||||||
|
|
||||||
$(BUILD_DIR_ZIP)/taitools.zip: \
|
$(BUILD_DIR_ZIP)/taitools.zip: \
|
||||||
$(BUILD_DIR_ZIP)/siva.zip \
|
$(BUILD_DIR_ZIP)/siva.zip \
|
||||||
|
$(BUILD_DIR_ZIP)/ll3.zip \
|
||||||
CHANGELOG.md \
|
CHANGELOG.md \
|
||||||
README.md \
|
README.md \
|
||||||
|
|
||||||
|
13
dist/ll3/start.bat
vendored
Normal file
13
dist/ll3/start.bat
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM chcp 932
|
||||||
|
start inject.exe -d -k ll3hook.dll d_drive\Service\NesysService.exe -app
|
||||||
|
inject.exe -d -k ll3hook.dll ll3.exe -singlemonitor -windowmode -highquality
|
||||||
|
REM Comment above and uncomment below for terminal mode
|
||||||
|
REM inject.exe -d -k ll3hook.dll ll3.exe -singlemonitor -windowmode -highquality -centralmode
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo The game process has terminated
|
||||||
|
pause
|
5
dist/ll3/taitools.ini
vendored
Normal file
5
dist/ll3/taitools.ini
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[vfs]
|
||||||
|
d_drive=d_drive
|
||||||
|
|
||||||
|
[netenv]
|
||||||
|
enable=1
|
@ -520,8 +520,9 @@ static WINHTTPAPI BOOL hook_WinHttpCrackUrl(
|
|||||||
} else {
|
} else {
|
||||||
wcscat_s(bfr, _countof(bfr), pos->to);
|
wcscat_s(bfr, _countof(bfr), pos->to);
|
||||||
wcscat_s(bfr, _countof(bfr), path);
|
wcscat_s(bfr, _countof(bfr), path);
|
||||||
|
//dprintf("DNS: Replaced cracked url %S (%d) -> %S\n", lpUrlComponents->lpszHostName, (int)lpUrlComponents->dwHostNameLength, bfr);
|
||||||
lpUrlComponents->lpszHostName = bfr;
|
lpUrlComponents->lpszHostName = bfr;
|
||||||
lpUrlComponents->dwHostNameLength = wcslen(bfr);
|
lpUrlComponents->dwHostNameLength = wcslen(pos->to);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
115
hooklib/reg.c
115
hooklib/reg.c
@ -37,6 +37,11 @@ static LSTATUS reg_hook_open_locked(
|
|||||||
const wchar_t *name,
|
const wchar_t *name,
|
||||||
HKEY *out);
|
HKEY *out);
|
||||||
|
|
||||||
|
static LSTATUS reg_hook_open_locked_a(
|
||||||
|
HKEY parent,
|
||||||
|
const char *name,
|
||||||
|
HKEY *out);
|
||||||
|
|
||||||
static LSTATUS reg_hook_query_val_locked(
|
static LSTATUS reg_hook_query_val_locked(
|
||||||
struct reg_hook_key *key,
|
struct reg_hook_key *key,
|
||||||
const wchar_t *name,
|
const wchar_t *name,
|
||||||
@ -53,6 +58,13 @@ static LSTATUS WINAPI hook_RegOpenKeyExW(
|
|||||||
uint32_t access,
|
uint32_t access,
|
||||||
HKEY *out);
|
HKEY *out);
|
||||||
|
|
||||||
|
static LSTATUS WINAPI hook_RegOpenKeyExA(
|
||||||
|
HKEY parent,
|
||||||
|
const char *name,
|
||||||
|
uint32_t flags,
|
||||||
|
uint32_t access,
|
||||||
|
HKEY *out);
|
||||||
|
|
||||||
static LSTATUS WINAPI hook_RegCreateKeyExW(
|
static LSTATUS WINAPI hook_RegCreateKeyExW(
|
||||||
HKEY parent,
|
HKEY parent,
|
||||||
const wchar_t *name,
|
const wchar_t *name,
|
||||||
@ -132,6 +144,13 @@ static LSTATUS (WINAPI *next_RegOpenKeyExW)(
|
|||||||
uint32_t access,
|
uint32_t access,
|
||||||
HKEY *out);
|
HKEY *out);
|
||||||
|
|
||||||
|
static LSTATUS (WINAPI *next_RegOpenKeyExA)(
|
||||||
|
HKEY parent,
|
||||||
|
const char *name,
|
||||||
|
uint32_t flags,
|
||||||
|
uint32_t access,
|
||||||
|
HKEY *out);
|
||||||
|
|
||||||
static LSTATUS (WINAPI *next_RegCreateKeyExW)(
|
static LSTATUS (WINAPI *next_RegCreateKeyExW)(
|
||||||
HKEY parent,
|
HKEY parent,
|
||||||
const wchar_t *name,
|
const wchar_t *name,
|
||||||
@ -208,6 +227,10 @@ static const struct hook_symbol reg_hook_syms[] = {
|
|||||||
.name = "RegOpenKeyExW",
|
.name = "RegOpenKeyExW",
|
||||||
.patch = hook_RegOpenKeyExW,
|
.patch = hook_RegOpenKeyExW,
|
||||||
.link = (void **) &next_RegOpenKeyExW,
|
.link = (void **) &next_RegOpenKeyExW,
|
||||||
|
}, {
|
||||||
|
.name = "RegOpenKeyExA",
|
||||||
|
.patch = hook_RegOpenKeyExA,
|
||||||
|
.link = (void **) &next_RegOpenKeyExA,
|
||||||
}, {
|
}, {
|
||||||
.name = "RegCreateKeyExW",
|
.name = "RegCreateKeyExW",
|
||||||
.patch = hook_RegCreateKeyExW,
|
.patch = hook_RegCreateKeyExW,
|
||||||
@ -403,6 +426,7 @@ static LSTATUS reg_hook_open_locked(
|
|||||||
//dprintf("Reg: %ls vs %ls\n", name, key->name);
|
//dprintf("Reg: %ls vs %ls\n", name, key->name);
|
||||||
|
|
||||||
if (key->root == parent && wstr_ieq(key->name, name)) {
|
if (key->root == parent && wstr_ieq(key->name, name)) {
|
||||||
|
dprintf("Reg: Replace key %S\n", name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,6 +441,7 @@ static LSTATUS reg_hook_open_locked(
|
|||||||
/* Assume only one handle will be open at a time */
|
/* Assume only one handle will be open at a time */
|
||||||
|
|
||||||
if (key->handle != NULL) {
|
if (key->handle != NULL) {
|
||||||
|
dprintf("Reg: Fake handle already open: %p\n", key->handle);
|
||||||
return ERROR_SHARING_VIOLATION;
|
return ERROR_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,6 +457,67 @@ static LSTATUS reg_hook_open_locked(
|
|||||||
KEY_READ,
|
KEY_READ,
|
||||||
out);
|
out);
|
||||||
|
|
||||||
|
|
||||||
|
if (err == ERROR_SUCCESS) {
|
||||||
|
key->handle = *out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LSTATUS reg_hook_open_locked_a(
|
||||||
|
HKEY parent,
|
||||||
|
const char *name,
|
||||||
|
HKEY *out)
|
||||||
|
{
|
||||||
|
struct reg_hook_key *key;
|
||||||
|
LSTATUS err;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
wchar_t wide_str[MAX_PATH];
|
||||||
|
int cvt_num = mbstowcs(wide_str, name, MAX_PATH);
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
for (i = 0 ; i < reg_hook_nkeys ; i++) {
|
||||||
|
/* Assume reg keys are referenced from a root key and not from some
|
||||||
|
intermediary key */
|
||||||
|
key = ®_hook_keys[i];
|
||||||
|
//dprintf("Reg: %ls vs %ls\n", name, key->name);
|
||||||
|
|
||||||
|
if (key->root == parent && wstr_ieq(key->name, wide_str)) {
|
||||||
|
dprintf("Reg: Replace key %S\n", wide_str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (Bail out if we didn't find anything; this causes the open/create call
|
||||||
|
to be passed onward down the hook chain) */
|
||||||
|
|
||||||
|
if (i >= reg_hook_nkeys) {
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assume only one handle will be open at a time */
|
||||||
|
|
||||||
|
if (key->handle != NULL) {
|
||||||
|
dprintf("Reg: Fake handle already open: %p\n", key->handle);
|
||||||
|
return ERROR_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open a unique HKEY handle that we can use to identify accesses to
|
||||||
|
this virtual registry key. We open a read-only handle to an arbitrary
|
||||||
|
registry key that we can reliably assume exists and isn't one of the
|
||||||
|
hardcoded root handles. HKLM\SOFTWARE will suffice for this purpose. */
|
||||||
|
|
||||||
|
err = next_RegOpenKeyExA(
|
||||||
|
HKEY_LOCAL_MACHINE,
|
||||||
|
"SOFTWARE",
|
||||||
|
0,
|
||||||
|
KEY_READ,
|
||||||
|
out);
|
||||||
|
|
||||||
|
|
||||||
if (err == ERROR_SUCCESS) {
|
if (err == ERROR_SUCCESS) {
|
||||||
key->handle = *out;
|
key->handle = *out;
|
||||||
}
|
}
|
||||||
@ -467,6 +553,35 @@ static LSTATUS WINAPI hook_RegOpenKeyExW(
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static LSTATUS WINAPI hook_RegOpenKeyExA(
|
||||||
|
HKEY parent,
|
||||||
|
const char *name,
|
||||||
|
uint32_t flags,
|
||||||
|
uint32_t access,
|
||||||
|
HKEY *out)
|
||||||
|
{
|
||||||
|
LSTATUS err;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(®_hook_lock);
|
||||||
|
err = reg_hook_open_locked_a(parent, name, out);
|
||||||
|
LeaveCriticalSection(®_hook_lock);
|
||||||
|
|
||||||
|
if (err == ERROR_SUCCESS) {
|
||||||
|
if (*out != NULL) {
|
||||||
|
//dprintf("Registry: Opened virtual key %s\n", name);
|
||||||
|
} else {
|
||||||
|
err = next_RegOpenKeyExA(parent, name, flags, access, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static LSTATUS WINAPI hook_RegCreateKeyExW(
|
static LSTATUS WINAPI hook_RegCreateKeyExW(
|
||||||
HKEY parent,
|
HKEY parent,
|
||||||
const wchar_t *name,
|
const wchar_t *name,
|
||||||
|
34
ll3hook/config.c
Normal file
34
ll3hook/config.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "ll3hook/config.h"
|
||||||
|
|
||||||
|
#include "platform/config.h"
|
||||||
|
|
||||||
|
void ll3_dll_config_load(
|
||||||
|
struct ll3_dll_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"ll3io",
|
||||||
|
L"path",
|
||||||
|
L"",
|
||||||
|
cfg->path,
|
||||||
|
_countof(cfg->path),
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ll3_hook_config_load(
|
||||||
|
struct ll3_hook_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
platform_config_load(&cfg->platform, filename);
|
||||||
|
ll3_dll_config_load(&cfg->dll, filename);
|
||||||
|
gfx_config_load(&cfg->gfx, filename);
|
||||||
|
}
|
19
ll3hook/config.h
Normal file
19
ll3hook/config.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "ll3hook/ll3-dll.h"
|
||||||
|
|
||||||
|
#include "platform/config.h"
|
||||||
|
#include "gfxhook/config.h"
|
||||||
|
#include "board/config.h"
|
||||||
|
|
||||||
|
struct ll3_hook_config {
|
||||||
|
struct platform_config platform;
|
||||||
|
struct ll3_dll_config dll;
|
||||||
|
struct gfx_config gfx;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ll3_hook_config_load(
|
||||||
|
struct ll3_hook_config *cfg,
|
||||||
|
const wchar_t *filename);
|
@ -50,35 +50,12 @@ static DWORD CALLBACK ll3_pre_startup(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = sg_reader_hook_init(&ll3_hook_cfg.aime, 1, ll3_hook_mod);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = vfd_hook_init(2);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = ll3_dll_init(&ll3_hook_cfg.dll, ll3_hook_mod);
|
hr = ll3_dll_init(&ll3_hook_cfg.dll, ll3_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = ll3_io4_hook_init(&ll3_hook_cfg.io4);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start elisabeth Hooks for the LED and IO Board DLLs */
|
|
||||||
elisabeth_hook_init(&ll3_hook_cfg.elisabeth);
|
|
||||||
|
|
||||||
touch_hook_init(&ll3_hook_cfg.touch);
|
|
||||||
|
|
||||||
/* Initialize debug helpers */
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
spike_hook_init(L".\\taitools.ini");
|
spike_hook_init(L".\\taitools.ini");
|
||||||
@ -97,6 +74,10 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
|||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (cause == DLL_THREAD_ATTACH && sizeof(uint64_t) == 4) {
|
||||||
|
dprintf("Connected\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (cause != DLL_PROCESS_ATTACH) {
|
if (cause != DLL_PROCESS_ATTACH) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
100
ll3hook/ll3-dll.c
Normal file
100
ll3hook/ll3-dll.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ll3hook/ll3-dll.h"
|
||||||
|
|
||||||
|
#include "util/dll-bind.h"
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
const struct dll_bind_sym ll3_dll_syms[] = {
|
||||||
|
{
|
||||||
|
.sym = "ll3_io_init",
|
||||||
|
.off = offsetof(struct ll3_dll, init),
|
||||||
|
}, {
|
||||||
|
.sym = "ll3_io_read_coin_counter",
|
||||||
|
.off = offsetof(struct ll3_dll, read_coin_counter),
|
||||||
|
}, {
|
||||||
|
.sym = "ll3_io_get_btns",
|
||||||
|
.off = offsetof(struct ll3_dll, get_btns),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ll3_dll ll3_dll;
|
||||||
|
|
||||||
|
HRESULT ll3_dll_init(const struct ll3_dll_config *cfg, HINSTANCE self)
|
||||||
|
{
|
||||||
|
uint16_t (*get_api_version)(void);
|
||||||
|
const struct dll_bind_sym *sym;
|
||||||
|
HINSTANCE owned;
|
||||||
|
HINSTANCE src;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(self != NULL);
|
||||||
|
|
||||||
|
if (cfg->path[0] != L'\0') {
|
||||||
|
owned = LoadLibraryW(cfg->path);
|
||||||
|
|
||||||
|
if (owned == NULL) {
|
||||||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
dprintf("ll3 IO: Failed to load IO DLL: %lx: %S\n",
|
||||||
|
hr,
|
||||||
|
cfg->path);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("ll3 IO: Using custom IO DLL: %S\n", cfg->path);
|
||||||
|
src = owned;
|
||||||
|
} else {
|
||||||
|
owned = NULL;
|
||||||
|
src = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_api_version = (void *) GetProcAddress(src, "ll3_io_get_api_version");
|
||||||
|
|
||||||
|
if (get_api_version != NULL) {
|
||||||
|
ll3_dll.api_version = get_api_version();
|
||||||
|
} else {
|
||||||
|
ll3_dll.api_version = 0x0100;
|
||||||
|
dprintf("Custom IO DLL does not expose ll3_io_get_api_version, "
|
||||||
|
"assuming API version 1.0.\n"
|
||||||
|
"Please ask the developer to update their DLL.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ll3_dll.api_version >= 0x0200) {
|
||||||
|
hr = E_NOTIMPL;
|
||||||
|
dprintf("ll3 IO: Custom IO DLL implements an unsupported "
|
||||||
|
"API version (%#04x). Please update Segatools.\n",
|
||||||
|
ll3_dll.api_version);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym = ll3_dll_syms;
|
||||||
|
hr = dll_bind(&ll3_dll, src, &sym, _countof(ll3_dll_syms));
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
if (src != self) {
|
||||||
|
dprintf("ll3 IO: Custom IO DLL does not provide function "
|
||||||
|
"\"%s\". Please contact your IO DLL's developer for "
|
||||||
|
"further assistance.\n",
|
||||||
|
sym->sym);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
} else {
|
||||||
|
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
owned = NULL;
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (owned != NULL) {
|
||||||
|
FreeLibrary(owned);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
20
ll3hook/ll3-dll.h
Normal file
20
ll3hook/ll3-dll.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "ll3io/ll3io.h"
|
||||||
|
|
||||||
|
struct ll3_dll {
|
||||||
|
uint16_t api_version;
|
||||||
|
HRESULT (*init)(void);
|
||||||
|
void (*read_coin_counter)(uint16_t *coins, uint16_t *services);
|
||||||
|
void (*get_btns)(uint8_t *btn, uint8_t *stick);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ll3_dll_config {
|
||||||
|
wchar_t path[MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ll3_dll ll3_dll;
|
||||||
|
|
||||||
|
HRESULT ll3_dll_init(const struct ll3_dll_config *cfg, HINSTANCE self);
|
7
ll3hook/ll3hook.def
Normal file
7
ll3hook/ll3hook.def
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
LIBRARY ll3hook
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
ll3_io_get_api_version
|
||||||
|
ll3_io_init
|
||||||
|
ll3_io_read_coin_counter
|
||||||
|
ll3_io_get_btns
|
30
ll3io/config.c
Normal file
30
ll3io/config.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ll3io/config.h"
|
||||||
|
|
||||||
|
void ll3_io_config_load(struct ll3_input_config *cfg, const wchar_t *filename)
|
||||||
|
{
|
||||||
|
cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename);
|
||||||
|
cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename);
|
||||||
|
cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename);
|
||||||
|
|
||||||
|
cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"deck", 0, filename);
|
||||||
|
cfg->xinput_player = GetPrivateProfileIntW(L"deck", L"controller_num", 0, filename);
|
||||||
|
|
||||||
|
cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename);
|
||||||
|
cfg->btn_r = GetPrivateProfileIntW(L"deck", L"right_button", 'N', filename);
|
||||||
|
|
||||||
|
cfg->stick_l_up = GetPrivateProfileIntW(L"deck", L"left_stick_up", 'W', filename);
|
||||||
|
cfg->stick_l_right = GetPrivateProfileIntW(L"deck", L"left_stick_right", 'D', filename);
|
||||||
|
cfg->stick_l_down = GetPrivateProfileIntW(L"deck", L"left_stick_down", 'S', filename);
|
||||||
|
cfg->stick_l_left = GetPrivateProfileIntW(L"deck", L"left_stick_left", 'A', filename);
|
||||||
|
|
||||||
|
cfg->stick_r_up = GetPrivateProfileIntW(L"deck", L"right_stick_up", 'I', filename);
|
||||||
|
cfg->stick_r_right = GetPrivateProfileIntW(L"deck", L"right_stick_right", 'L', filename);
|
||||||
|
cfg->stick_r_down = GetPrivateProfileIntW(L"deck", L"right_stick_down", 'K', filename);
|
||||||
|
cfg->stick_r_left = GetPrivateProfileIntW(L"deck", L"right_stick_left", 'J', filename);
|
||||||
|
}
|
28
ll3io/config.h
Normal file
28
ll3io/config.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct ll3_input_config {
|
||||||
|
uint8_t is_xinput;
|
||||||
|
uint8_t xinput_player;
|
||||||
|
|
||||||
|
uint8_t test;
|
||||||
|
uint8_t service;
|
||||||
|
uint8_t coin;
|
||||||
|
uint8_t btn_l;
|
||||||
|
uint8_t btn_r;
|
||||||
|
|
||||||
|
uint8_t stick_l_up;
|
||||||
|
uint8_t stick_l_right;
|
||||||
|
uint8_t stick_l_down;
|
||||||
|
uint8_t stick_l_left;
|
||||||
|
uint8_t stick_r_up;
|
||||||
|
uint8_t stick_r_right;
|
||||||
|
uint8_t stick_r_down;
|
||||||
|
uint8_t stick_r_left;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void ll3_io_config_load(struct ll3_input_config *cfg, const wchar_t *filename);
|
64
ll3io/ll3io.c
Normal file
64
ll3io/ll3io.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <xinput.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "ll3io/ll3io.h"
|
||||||
|
#include "ll3io/config.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static bool ll3_io_coin = false;
|
||||||
|
static bool ll3_io_service = false;
|
||||||
|
static uint16_t ll3_coin_ct = 0;
|
||||||
|
static uint16_t ll3_service_ct = 0;
|
||||||
|
static struct ll3_input_config cfg;
|
||||||
|
|
||||||
|
uint16_t ll3_io_get_api_version(void)
|
||||||
|
{
|
||||||
|
return 0x0100;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT ll3_io_init(void)
|
||||||
|
{
|
||||||
|
dprintf("ll3 IO: Init\n");
|
||||||
|
ll3_io_config_load(&cfg, L".\\bananatools.ini");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ll3_io_get_btns(uint8_t *btn, uint8_t *stick)
|
||||||
|
{
|
||||||
|
if (GetAsyncKeyState(cfg.test) & 0x8000) {
|
||||||
|
*btn |= ll3_BTN_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.service) & 0x8000) {
|
||||||
|
*btn |= ll3_BTN_SERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ll3_io_read_coin_counter(uint16_t *coins, uint16_t *services)
|
||||||
|
{
|
||||||
|
if (GetAsyncKeyState(cfg.coin) & 0x8000) {
|
||||||
|
if (!ll3_io_coin) {
|
||||||
|
ll3_io_coin = true;
|
||||||
|
ll3_coin_ct++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ll3_io_coin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.service) & 0x8000) {
|
||||||
|
if (!ll3_io_service) {
|
||||||
|
ll3_io_service = true;
|
||||||
|
ll3_service_ct++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ll3_io_service = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*coins = ll3_coin_ct;
|
||||||
|
*services = ll3_service_ct;
|
||||||
|
}
|
57
ll3io/ll3io.h
Normal file
57
ll3io/ll3io.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ll3_BTN_TEST = 0x01,
|
||||||
|
ll3_BTN_SERVICE = 0x02,
|
||||||
|
ll3_BTN_COIN = 0x03,
|
||||||
|
ll3_BTN_LEFT = 0x04,
|
||||||
|
ll3_BTN_RIGHT = 0x05,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ll3_STICK_L_UP = 0x01,
|
||||||
|
ll3_STICK_L_RIGHT = 0x02,
|
||||||
|
ll3_STICK_L_DOWN = 0x03,
|
||||||
|
ll3_STICK_L_LEFT = 0x04,
|
||||||
|
ll3_STICK_R_UP = 0x05,
|
||||||
|
ll3_STICK_R_RIGHT = 0x06,
|
||||||
|
ll3_STICK_R_DOWN = 0x07,
|
||||||
|
ll3_STICK_R_LEFT = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get the version of the Theatrhythm IO API that this DLL supports. This
|
||||||
|
function should return a positive 16-bit integer, where the high byte is
|
||||||
|
the major version and the low byte is the minor version (as defined by the
|
||||||
|
Semantic Versioning standard).
|
||||||
|
|
||||||
|
The latest API version as of this writing is 0x0100. */
|
||||||
|
|
||||||
|
uint16_t ll3_io_get_api_version(void);
|
||||||
|
|
||||||
|
/* Initialize the IO DLL. This is the second function that will be called on
|
||||||
|
your DLL, after ll3_io_get_api_version.
|
||||||
|
|
||||||
|
All subsequent calls to this API may originate from arbitrary threads.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
HRESULT ll3_io_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
|
||||||
|
ll3_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into
|
||||||
|
a left hand side set of inputs and a right hand side set of inputs: the bit
|
||||||
|
mappings are the same in both cases.
|
||||||
|
|
||||||
|
All buttons are active-high, even though some buttons' electrical signals
|
||||||
|
on a real cabinet are active-low.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
void ll3_io_get_btns(uint8_t *btn, uint8_t *stick);
|
||||||
|
|
||||||
|
void ll3_io_read_coin_counter(uint16_t *coins, uint16_t *services);
|
16
ll3io/meson.build
Normal file
16
ll3io/meson.build
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
ll3io_lib = static_library(
|
||||||
|
'll3io',
|
||||||
|
name_prefix : '',
|
||||||
|
include_directories : inc,
|
||||||
|
implicit_include_directories : false,
|
||||||
|
c_pch : '../precompiled.h',
|
||||||
|
dependencies : [
|
||||||
|
xinput_lib,
|
||||||
|
],
|
||||||
|
sources : [
|
||||||
|
'll3io.c',
|
||||||
|
'll3io.h',
|
||||||
|
'config.c',
|
||||||
|
'config.h',
|
||||||
|
],
|
||||||
|
)
|
@ -55,6 +55,8 @@ subdir('util')
|
|||||||
subdir('gfxhook')
|
subdir('gfxhook')
|
||||||
|
|
||||||
subdir('sivaio')
|
subdir('sivaio')
|
||||||
|
subdir('ll3io')
|
||||||
|
|
||||||
subdir('minihook')
|
subdir('minihook')
|
||||||
subdir('sivahook')
|
subdir('sivahook')
|
||||||
|
subdir('ll3hook')
|
||||||
|
@ -67,6 +67,8 @@ static uint32_t WINAPI hook_IcmpSendEcho2(
|
|||||||
uint32_t ReplySize,
|
uint32_t ReplySize,
|
||||||
uint32_t Timeout);
|
uint32_t Timeout);
|
||||||
|
|
||||||
|
static uint32_t WINAPI hook_FlushIpNetTable(DWORD dwIfIndex);
|
||||||
|
|
||||||
/* Link pointers */
|
/* Link pointers */
|
||||||
|
|
||||||
static uint32_t (WINAPI *next_GetAdaptersAddresses)(
|
static uint32_t (WINAPI *next_GetAdaptersAddresses)(
|
||||||
@ -124,6 +126,9 @@ static const struct hook_symbol netenv_hook_syms[] = {
|
|||||||
.name = "IcmpSendEcho2",
|
.name = "IcmpSendEcho2",
|
||||||
.patch = hook_IcmpSendEcho2,
|
.patch = hook_IcmpSendEcho2,
|
||||||
.link = (void **) &next_IcmpSendEcho2,
|
.link = (void **) &next_IcmpSendEcho2,
|
||||||
|
}, {
|
||||||
|
.name = "FlushIpNetTable",
|
||||||
|
.patch = hook_FlushIpNetTable,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -294,7 +299,8 @@ static uint32_t WINAPI hook_GetAdaptersInfo(
|
|||||||
return ERROR_BUFFER_OVERFLOW;
|
return ERROR_BUFFER_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf("Netenv: GetAdaptersInfo: Virtualized LAN configuration:\n");
|
// This spams console on NesysService.exe, comment out for now
|
||||||
|
/*dprintf("Netenv: GetAdaptersInfo: Virtualized LAN configuration:\n");
|
||||||
dprintf("Netenv: Interface IP : %3i.%3i.%3i.%3i\n",
|
dprintf("Netenv: Interface IP : %3i.%3i.%3i.%3i\n",
|
||||||
(uint8_t) (netenv_ip_iface >> 24),
|
(uint8_t) (netenv_ip_iface >> 24),
|
||||||
(uint8_t) (netenv_ip_iface >> 16),
|
(uint8_t) (netenv_ip_iface >> 16),
|
||||||
@ -311,7 +317,7 @@ static uint32_t WINAPI hook_GetAdaptersInfo(
|
|||||||
netenv_mac_addr[2],
|
netenv_mac_addr[2],
|
||||||
netenv_mac_addr[3],
|
netenv_mac_addr[3],
|
||||||
netenv_mac_addr[4],
|
netenv_mac_addr[4],
|
||||||
netenv_mac_addr[5]);
|
netenv_mac_addr[5]);*/
|
||||||
|
|
||||||
memset(&iface, 0, sizeof(iface));
|
memset(&iface, 0, sizeof(iface));
|
||||||
memset(&router, 0, sizeof(router));
|
memset(&router, 0, sizeof(router));
|
||||||
@ -410,7 +416,7 @@ static uint32_t WINAPI hook_GetIfTable(
|
|||||||
*pdwSize = sizeof(*row) + sizeof(DWORD);
|
*pdwSize = sizeof(*row) + sizeof(DWORD);
|
||||||
|
|
||||||
if (pIfTable == NULL || nbytes < sizeof(*row) + sizeof(DWORD)) {
|
if (pIfTable == NULL || nbytes < sizeof(*row) + sizeof(DWORD)) {
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
return ERROR_INSUFFICIENT_BUFFER; // was ERROR_BUFFER_OVERFLOW
|
||||||
}
|
}
|
||||||
|
|
||||||
pIfTable->dwNumEntries = 1;
|
pIfTable->dwNumEntries = 1;
|
||||||
@ -499,3 +505,8 @@ static uint32_t WINAPI hook_IcmpSendEcho2(
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t WINAPI hook_FlushIpNetTable(DWORD dwIfIndex)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user