forked from Hay1tsme/segatools
Make HKB hook public, with unity option fixes
This commit is contained in:
parent
94f9357382
commit
7051b849fa
16
Package.mk
16
Package.mk
@ -104,6 +104,21 @@ $(BUILD_DIR_ZIP)/mu3.zip:
|
|||||||
$(V)strip $(BUILD_DIR_ZIP)/mu3/*.{exe,dll}
|
$(V)strip $(BUILD_DIR_ZIP)/mu3/*.{exe,dll}
|
||||||
$(V)cd $(BUILD_DIR_ZIP)/mu3 ; zip -r ../mu3.zip *
|
$(V)cd $(BUILD_DIR_ZIP)/mu3 ; zip -r ../mu3.zip *
|
||||||
|
|
||||||
|
$(BUILD_DIR_ZIP)/hkb.zip:
|
||||||
|
$(V)echo ... $@
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/hkb
|
||||||
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/hkb/DEVICE
|
||||||
|
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||||
|
$(BUILD_DIR_64)/hkbhook/hkbhook.dll \
|
||||||
|
$(DIST_DIR)/hkb/segatools.ini \
|
||||||
|
$(DIST_DIR)/hkb/start.bat \
|
||||||
|
$(BUILD_DIR_ZIP)/hkb
|
||||||
|
$(V)cp pki/billing.pub \
|
||||||
|
pki/ca.crt \
|
||||||
|
$(BUILD_DIR_ZIP)/hkb/DEVICE
|
||||||
|
$(V)strip $(BUILD_DIR_ZIP)/hkb/*.{exe,dll}
|
||||||
|
$(V)cd $(BUILD_DIR_ZIP)/hkb ; zip -r ../hkb.zip *
|
||||||
|
|
||||||
$(BUILD_DIR_ZIP)/mai2.zip:
|
$(BUILD_DIR_ZIP)/mai2.zip:
|
||||||
$(V)echo ... $@
|
$(V)echo ... $@
|
||||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/mai2
|
$(V)mkdir -p $(BUILD_DIR_ZIP)/mai2
|
||||||
@ -136,6 +151,7 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
|
|||||||
$(BUILD_DIR_ZIP)/idz.zip \
|
$(BUILD_DIR_ZIP)/idz.zip \
|
||||||
$(BUILD_DIR_ZIP)/mercury.zip \
|
$(BUILD_DIR_ZIP)/mercury.zip \
|
||||||
$(BUILD_DIR_ZIP)/mu3.zip \
|
$(BUILD_DIR_ZIP)/mu3.zip \
|
||||||
|
$(BUILD_DIR_ZIP)/hkb.zip \
|
||||||
$(BUILD_DIR_ZIP)/mai2.zip \
|
$(BUILD_DIR_ZIP)/mai2.zip \
|
||||||
CHANGELOG.md \
|
CHANGELOG.md \
|
||||||
README.md \
|
README.md \
|
||||||
|
41
dist/hkb/segatools.ini
vendored
Normal file
41
dist/hkb/segatools.ini
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[vfs]
|
||||||
|
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||||
|
amfs=amfs
|
||||||
|
; Create an empty directory somewhere and insert the path here.
|
||||||
|
; This directory may be shared between multiple SEGA games.
|
||||||
|
; NOTE: This has nothing to do with Windows %APPDATA%.
|
||||||
|
appdata=appdata
|
||||||
|
option=Option
|
||||||
|
|
||||||
|
[dns]
|
||||||
|
; Insert the hostname or IP address of the server you wish to use here.
|
||||||
|
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
||||||
|
default=127.0.0.1
|
||||||
|
|
||||||
|
[ds]
|
||||||
|
; Region code on the emulated AMEX board DS EEPROM.
|
||||||
|
; 1: Japan
|
||||||
|
; 4: Export (some UI elements in English)
|
||||||
|
;
|
||||||
|
; NOTE: Changing this setting causes a factory reset.
|
||||||
|
region=1
|
||||||
|
|
||||||
|
[netenv]
|
||||||
|
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
|
||||||
|
; SEGA games are somewhat picky about their LAN environment, so leaving this
|
||||||
|
; setting enabled is recommended.
|
||||||
|
enable=1
|
||||||
|
|
||||||
|
[keychip]
|
||||||
|
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||||
|
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||||
|
; that subnet must start with 192.168.
|
||||||
|
subnet=192.168.155.0
|
||||||
|
|
||||||
|
[gfx]
|
||||||
|
enable=1
|
||||||
|
|
||||||
|
[io4]
|
||||||
|
test=0x31
|
||||||
|
service=0x32
|
||||||
|
coin=0x33
|
11
dist/hkb/start.bat
vendored
Normal file
11
dist/hkb/start.bat
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@echo off
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
|
start inject.exe -d -k hkbhook.dll amdaemon.exe -f -c common.json terminal.json satellite.json
|
||||||
|
inject.exe -d -k hkbhook.dll hkb.exe -screen-fullscreen 0 -screen-quality Fantastic -silent-crashes -logFile gameLog.txt
|
||||||
|
|
||||||
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
|
echo Game processes have terminated
|
52
hkbhook/config.c
Normal file
52
hkbhook/config.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "board/config.h"
|
||||||
|
|
||||||
|
#include "gfxhook/config.h"
|
||||||
|
|
||||||
|
#include "hooklib/config.h"
|
||||||
|
#include "hooklib/dvd.h"
|
||||||
|
|
||||||
|
#include "hkbhook/config.h"
|
||||||
|
|
||||||
|
#include "platform/config.h"
|
||||||
|
|
||||||
|
void hkb_dll_config_load(
|
||||||
|
struct hkb_dll_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"hkbio",
|
||||||
|
L"path",
|
||||||
|
L"",
|
||||||
|
cfg->path,
|
||||||
|
_countof(cfg->path),
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hkb_led_config_load(
|
||||||
|
struct hkb_led_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
cfg->enable = GetPrivateProfileIntW(L"led", L"enable", 1, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hkb_hook_config_load(
|
||||||
|
struct hkb_hook_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
platform_config_load(&cfg->platform, filename);
|
||||||
|
aime_config_load(&cfg->aime, filename);
|
||||||
|
dvd_config_load(&cfg->dvd, filename);
|
||||||
|
io4_config_load(&cfg->io4, filename);
|
||||||
|
gfx_config_load(&cfg->gfx, filename);
|
||||||
|
hkb_dll_config_load(&cfg->dll, filename);
|
||||||
|
hkb_led_config_load(&cfg->led, filename);
|
||||||
|
}
|
33
hkbhook/config.h
Normal file
33
hkbhook/config.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "board/config.h"
|
||||||
|
|
||||||
|
#include "gfxhook/gfx.h"
|
||||||
|
|
||||||
|
#include "hooklib/dvd.h"
|
||||||
|
|
||||||
|
#include "hkbhook/hkb-dll.h"
|
||||||
|
|
||||||
|
#include "platform/config.h"
|
||||||
|
|
||||||
|
#include "hkbhook/led.h"
|
||||||
|
|
||||||
|
struct hkb_hook_config {
|
||||||
|
struct platform_config platform;
|
||||||
|
struct aime_config aime;
|
||||||
|
struct dvd_config dvd;
|
||||||
|
struct io4_config io4;
|
||||||
|
struct gfx_config gfx;
|
||||||
|
struct hkb_dll_config dll;
|
||||||
|
struct hkb_led_config led;
|
||||||
|
};
|
||||||
|
|
||||||
|
void hkb_dll_config_load(
|
||||||
|
struct hkb_dll_config *cfg,
|
||||||
|
const wchar_t *filename);
|
||||||
|
|
||||||
|
void hkb_hook_config_load(
|
||||||
|
struct hkb_hook_config *cfg,
|
||||||
|
const wchar_t *filename);
|
154
hkbhook/dllmain.c
Normal file
154
hkbhook/dllmain.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
|
#include "board/sg-reader.h"
|
||||||
|
#include "board/vfd.h"
|
||||||
|
|
||||||
|
#include "gfxhook/d3d9.h"
|
||||||
|
#include "gfxhook/d3d11.h"
|
||||||
|
#include "gfxhook/dxgi.h"
|
||||||
|
#include "gfxhook/gfx.h"
|
||||||
|
|
||||||
|
#include "hook/process.h"
|
||||||
|
|
||||||
|
#include "hooklib/dvd.h"
|
||||||
|
#include "hooklib/serial.h"
|
||||||
|
#include "hooklib/spike.h"
|
||||||
|
#include "hooklib/cursor.h"
|
||||||
|
|
||||||
|
#include "hkbhook/config.h"
|
||||||
|
#include "hkbhook/io4.h"
|
||||||
|
#include "hkbhook/led.h"
|
||||||
|
#include "hkbhook/hkb-dll.h"
|
||||||
|
#include "hkbhook/unity.h"
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static HMODULE hkb_hook_mod;
|
||||||
|
static process_entry_t hkb_startup;
|
||||||
|
static struct hkb_hook_config hkb_hook_cfg;
|
||||||
|
|
||||||
|
static DWORD CALLBACK hkb_pre_startup(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
dprintf("--- Begin hkb_pre_startup ---\n");
|
||||||
|
|
||||||
|
/* Load config */
|
||||||
|
|
||||||
|
hkb_hook_config_load(&hkb_hook_cfg, L".\\segatools.ini");
|
||||||
|
|
||||||
|
/* Hook Win32 APIs */
|
||||||
|
|
||||||
|
dvd_hook_init(&hkb_hook_cfg.dvd, hkb_hook_mod);
|
||||||
|
gfx_hook_init(&hkb_hook_cfg.gfx);
|
||||||
|
gfx_d3d9_hook_init(&hkb_hook_cfg.gfx, hkb_hook_mod);
|
||||||
|
gfx_d3d11_hook_init(&hkb_hook_cfg.gfx, hkb_hook_mod);
|
||||||
|
gfx_dxgi_hook_init(&hkb_hook_cfg.gfx, hkb_hook_mod);
|
||||||
|
serial_hook_init();
|
||||||
|
|
||||||
|
/* Initialize emulation hooks */
|
||||||
|
|
||||||
|
hr = platform_hook_init(
|
||||||
|
&hkb_hook_cfg.platform,
|
||||||
|
"SDEC",
|
||||||
|
"ACA2",
|
||||||
|
hkb_hook_mod);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor_hook_init();
|
||||||
|
// COM1: Touch
|
||||||
|
// COM2: LED (Satalite)
|
||||||
|
// COM3: Reader (Satalite)
|
||||||
|
// COM3: LED (Terminal)
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hkb_hook_cfg.platform.nusec.platform_id[0] != '\0' && hkb_hook_cfg.platform.nusec.platform_id[3] == '4') {
|
||||||
|
hr = led_hook_init(&hkb_hook_cfg.led, 3);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
hr = sg_reader_hook_init(&hkb_hook_cfg.aime, 1, hkb_hook_mod);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
hr = vfd_hook_init(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
hr = led_hook_init(&hkb_hook_cfg.led, 2);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
hr = sg_reader_hook_init(&hkb_hook_cfg.aime, 3, hkb_hook_mod);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
hr = vfd_hook_init(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = hkb_dll_init(&hkb_hook_cfg.dll, hkb_hook_mod);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = hkb_io4_hook_init(&hkb_hook_cfg.io4);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize Unity native plugin DLL hooks
|
||||||
|
|
||||||
|
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||||
|
hooked earlier in the `hkbhook` initialization. */
|
||||||
|
|
||||||
|
unity_hook_init();
|
||||||
|
|
||||||
|
/* Initialize debug helpers */
|
||||||
|
|
||||||
|
spike_hook_init(L".\\segatools.ini");
|
||||||
|
|
||||||
|
dprintf("--- End hkb_pre_startup ---\n");
|
||||||
|
|
||||||
|
/* Jump to EXE start address */
|
||||||
|
|
||||||
|
return hkb_startup();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
ExitProcess(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (cause != DLL_PROCESS_ATTACH) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hkb_hook_mod = mod;
|
||||||
|
|
||||||
|
hr = process_hijack_startup(hkb_pre_startup, &hkb_startup);
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
dprintf("Failed to hijack process startup: %x\n", (int) hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCEEDED(hr);
|
||||||
|
}
|
103
hkbhook/hkb-dll.c
Normal file
103
hkbhook/hkb-dll.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "hkbhook/hkb-dll.h"
|
||||||
|
|
||||||
|
#include "util/dll-bind.h"
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
const struct dll_bind_sym hkb_dll_syms[] = {
|
||||||
|
{
|
||||||
|
.sym = "hkb_io_init",
|
||||||
|
.off = offsetof(struct hkb_dll, init),
|
||||||
|
}, {
|
||||||
|
.sym = "hkb_io_poll",
|
||||||
|
.off = offsetof(struct hkb_dll, poll),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hkb_dll hkb_dll;
|
||||||
|
|
||||||
|
// Copypasta DLL binding and diagnostic message boilerplate.
|
||||||
|
// Not much of this lends itself to being easily factored out. Also there
|
||||||
|
// will be a lot of API-specific branching code here eventually as new API
|
||||||
|
// versions get defined, so even though these functions all look the same
|
||||||
|
// now this won't remain the case forever.
|
||||||
|
|
||||||
|
HRESULT hkb_dll_init(const struct hkb_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("Ongeki IO: Failed to load IO DLL: %lx: %S\n",
|
||||||
|
hr,
|
||||||
|
cfg->path);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Ongeki IO: Using custom IO DLL: %S\n", cfg->path);
|
||||||
|
src = owned;
|
||||||
|
} else {
|
||||||
|
owned = NULL;
|
||||||
|
src = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_api_version = (void *) GetProcAddress(src, "hkb_io_get_api_version");
|
||||||
|
|
||||||
|
if (get_api_version != NULL) {
|
||||||
|
hkb_dll.api_version = get_api_version();
|
||||||
|
} else {
|
||||||
|
hkb_dll.api_version = 0x0100;
|
||||||
|
dprintf("Custom IO DLL does not expose hkb_io_get_api_version, "
|
||||||
|
"assuming API version 1.0.\n"
|
||||||
|
"Please ask the developer to update their DLL.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hkb_dll.api_version >= 0x0200) {
|
||||||
|
hr = E_NOTIMPL;
|
||||||
|
dprintf("Ongeki IO: Custom IO DLL implements an unsupported "
|
||||||
|
"API version (%#04x). Please update Segatools.\n",
|
||||||
|
hkb_dll.api_version);
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym = hkb_dll_syms;
|
||||||
|
hr = dll_bind(&hkb_dll, src, &sym, _countof(hkb_dll_syms));
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
if (src != self) {
|
||||||
|
dprintf("Ongeki 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;
|
||||||
|
}
|
19
hkbhook/hkb-dll.h
Normal file
19
hkbhook/hkb-dll.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hkbio/hkbio.h"
|
||||||
|
|
||||||
|
struct hkb_dll {
|
||||||
|
uint16_t api_version;
|
||||||
|
HRESULT (*init)(void);
|
||||||
|
HRESULT (*poll)(uint8_t *opbtn, uint8_t *gamebtn);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hkb_dll_config {
|
||||||
|
wchar_t path[MAX_PATH];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct hkb_dll hkb_dll;
|
||||||
|
|
||||||
|
HRESULT hkb_dll_init(const struct hkb_dll_config *cfg, HINSTANCE self);
|
22
hkbhook/hkbhook.def
Normal file
22
hkbhook/hkbhook.def
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
LIBRARY hkbhook
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
CreateDXGIFactory
|
||||||
|
CreateDXGIFactory1
|
||||||
|
CreateDXGIFactory2
|
||||||
|
D3D11CreateDevice
|
||||||
|
D3D11CreateDeviceAndSwapChain
|
||||||
|
Direct3DCreate9
|
||||||
|
aime_io_get_api_version
|
||||||
|
aime_io_init
|
||||||
|
aime_io_led_set_color
|
||||||
|
aime_io_nfc_get_aime_id
|
||||||
|
aime_io_nfc_get_felica_id
|
||||||
|
aime_io_nfc_poll
|
||||||
|
amDllVideoClose @2
|
||||||
|
amDllVideoGetVBiosVersion @4
|
||||||
|
amDllVideoOpen @1
|
||||||
|
amDllVideoSetResolution @3
|
||||||
|
hkb_io_get_api_version
|
||||||
|
hkb_io_init
|
||||||
|
hkb_io_poll
|
109
hkbhook/io4.c
Normal file
109
hkbhook/io4.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
|
|
||||||
|
#include "hkbhook/hkb-dll.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
bool hkb_io_coin = false;
|
||||||
|
uint16_t hkb_io_coins = 0;
|
||||||
|
|
||||||
|
static HRESULT hkb_io4_poll(void *ctx, struct io4_state *state);
|
||||||
|
|
||||||
|
static const struct io4_ops hkb_io4_ops = {
|
||||||
|
.poll = hkb_io4_poll,
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT hkb_io4_hook_init(const struct io4_config *cfg)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(hkb_dll.init != NULL);
|
||||||
|
|
||||||
|
hr = io4_hook_init(cfg, &hkb_io4_ops, NULL);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hkb_dll.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT hkb_io4_poll(void *ctx, struct io4_state *state)
|
||||||
|
{
|
||||||
|
uint8_t opbtn;
|
||||||
|
uint8_t gamebtn;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(hkb_dll.poll != NULL);
|
||||||
|
|
||||||
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
hr = hkb_dll.poll(&opbtn, &gamebtn);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opbtn & HKB_IO_OPBTN_TEST) {
|
||||||
|
state->buttons[0] |= IO4_BUTTON_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opbtn & HKB_IO_OPBTN_SERVICE) {
|
||||||
|
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opbtn & HKB_IO_OPBTN_COIN) {
|
||||||
|
if (!hkb_io_coin) {
|
||||||
|
hkb_io_coin = true;
|
||||||
|
hkb_io_coins++;
|
||||||
|
state->buttons[0] |= 1 << 25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hkb_io_coin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->chutes[0] = 128 + 256 * hkb_io_coins;
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_RIGHT) {
|
||||||
|
state->buttons[1] |= 1 << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_LEFT) {
|
||||||
|
state->buttons[1] |= 1 << 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_UP) {
|
||||||
|
state->buttons[1] |= 1 << 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_DOWN) {
|
||||||
|
state->buttons[1] |= 1 << 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_ENTER) {
|
||||||
|
state->buttons[1] |= 1 << 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_CANCEL) {
|
||||||
|
state->buttons[1] |= 1 << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_ARR_RIGHT) {
|
||||||
|
state->buttons[1] |= 1 << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamebtn & HKB_IO_GAMEBTN_ARR_LEFT) {
|
||||||
|
state->buttons[1] |= 1 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
7
hkbhook/io4.h
Normal file
7
hkbhook/io4.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "board/io4.h"
|
||||||
|
|
||||||
|
HRESULT hkb_io4_hook_init(const struct io4_config *cfg);
|
98
hkbhook/led.c
Normal file
98
hkbhook/led.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hook/iohook.h"
|
||||||
|
|
||||||
|
#include "hooklib/uart.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
#include "util/dump.h"
|
||||||
|
|
||||||
|
#include "hkbhook/led.h"
|
||||||
|
|
||||||
|
static HRESULT hkb_led_handle_irp(struct irp *irp);
|
||||||
|
static HRESULT hkb_led_handle_irp_locked(struct irp *irp);
|
||||||
|
|
||||||
|
static CRITICAL_SECTION hkb_led_lock;
|
||||||
|
static bool hkb_led_started;
|
||||||
|
static struct uart hkb_led_uart;
|
||||||
|
static uint8_t hkb_led_written_bytes[520];
|
||||||
|
static uint8_t hkb_led_readable_bytes[520];
|
||||||
|
|
||||||
|
HRESULT led_hook_init(const struct hkb_led_config *cfg, uint8_t port)
|
||||||
|
{
|
||||||
|
if (!cfg->enable) {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeCriticalSection(&hkb_led_lock);
|
||||||
|
|
||||||
|
uart_init(&hkb_led_uart, port);
|
||||||
|
hkb_led_uart.written.bytes = hkb_led_written_bytes;
|
||||||
|
hkb_led_uart.written.nbytes = sizeof(hkb_led_written_bytes);
|
||||||
|
hkb_led_uart.readable.bytes = hkb_led_readable_bytes;
|
||||||
|
hkb_led_uart.readable.nbytes = sizeof(hkb_led_readable_bytes);
|
||||||
|
|
||||||
|
return iohook_push_handler(hkb_led_handle_irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT hkb_led_handle_irp(struct irp *irp)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(irp != NULL);
|
||||||
|
|
||||||
|
if (!uart_match_irp(&hkb_led_uart, irp)) {
|
||||||
|
return iohook_invoke_next(irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&hkb_led_lock);
|
||||||
|
hr = hkb_led_handle_irp_locked(irp);
|
||||||
|
LeaveCriticalSection(&hkb_led_lock);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT hkb_led_handle_irp_locked(struct irp *irp)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (irp->op == IRP_OP_WRITE) {
|
||||||
|
dprintf("WRITE:\n");
|
||||||
|
dump_const_iobuf(&irp->write);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (irp->op == IRP_OP_READ) {
|
||||||
|
dprintf("READ:\n");
|
||||||
|
dump_iobuf(&hkb_led_uart.readable);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (irp->op == IRP_OP_OPEN) {
|
||||||
|
/* Unfortunately the card reader UART gets opened and closed
|
||||||
|
repeatedly */
|
||||||
|
|
||||||
|
if (!hkb_led_started) {
|
||||||
|
dprintf("Led: Open\n");
|
||||||
|
|
||||||
|
hkb_led_started = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = uart_handle_irp(&hkb_led_uart, irp);
|
||||||
|
|
||||||
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hkb_led_uart.written.pos = 0;
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
39
hkbhook/led.h
Normal file
39
hkbhook/led.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct hkb_led_config {
|
||||||
|
bool enable;
|
||||||
|
};
|
||||||
|
struct hbk_led_packet_head {
|
||||||
|
uint8_t sync;
|
||||||
|
uint8_t dst;
|
||||||
|
uint8_t src;
|
||||||
|
uint8_t len;
|
||||||
|
};
|
||||||
|
struct hbk_led_req_header {
|
||||||
|
struct hbk_led_packet_head head;
|
||||||
|
uint8_t cmd;
|
||||||
|
};
|
||||||
|
struct hbk_led_resp_header {
|
||||||
|
struct hbk_led_packet_head head;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t report;
|
||||||
|
};
|
||||||
|
struct hbk_led_packet_tail {
|
||||||
|
uint8_t checksum;
|
||||||
|
};
|
||||||
|
struct hbk_led_req_any {
|
||||||
|
struct hbk_led_req_header header;
|
||||||
|
struct hbk_led_packet_tail tail;
|
||||||
|
};
|
||||||
|
struct hbk_led_resp_any {
|
||||||
|
struct hbk_led_resp_header header;
|
||||||
|
struct hbk_led_packet_tail tail;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
HRESULT led_hook_init(const struct hkb_led_config *cfg, uint8_t port);
|
35
hkbhook/meson.build
Normal file
35
hkbhook/meson.build
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
shared_library(
|
||||||
|
'hkbhook',
|
||||||
|
name_prefix : '',
|
||||||
|
include_directories : inc,
|
||||||
|
implicit_include_directories : false,
|
||||||
|
vs_module_defs : 'hkbhook.def',
|
||||||
|
c_pch : '../precompiled.h',
|
||||||
|
dependencies : [
|
||||||
|
capnhook.get_variable('hook_dep'),
|
||||||
|
capnhook.get_variable('hooklib_dep'),
|
||||||
|
xinput_lib,
|
||||||
|
],
|
||||||
|
link_with : [
|
||||||
|
aimeio_lib,
|
||||||
|
board_lib,
|
||||||
|
gfxhook_lib,
|
||||||
|
hooklib_lib,
|
||||||
|
hkbio_lib,
|
||||||
|
platform_lib,
|
||||||
|
util_lib,
|
||||||
|
],
|
||||||
|
sources : [
|
||||||
|
'config.c',
|
||||||
|
'config.h',
|
||||||
|
'dllmain.c',
|
||||||
|
'io4.c',
|
||||||
|
'io4.h',
|
||||||
|
'led.c',
|
||||||
|
'led.h',
|
||||||
|
'hkb-dll.c',
|
||||||
|
'hkb-dll.h',
|
||||||
|
'unity.h',
|
||||||
|
'unity.c',
|
||||||
|
],
|
||||||
|
)
|
105
hkbhook/unity.c
Normal file
105
hkbhook/unity.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "hook/table.h"
|
||||||
|
#include "hook/iohook.h"
|
||||||
|
|
||||||
|
#include "hooklib/dll.h"
|
||||||
|
#include "hooklib/path.h"
|
||||||
|
#include "hooklib/reg.h"
|
||||||
|
#include "hook/procaddr.h"
|
||||||
|
#include "hooklib/serial.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target);
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
|
||||||
|
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
||||||
|
|
||||||
|
static const struct hook_symbol unity_kernel32_syms[] = {
|
||||||
|
{
|
||||||
|
.name = "LoadLibraryW",
|
||||||
|
.patch = my_LoadLibraryW,
|
||||||
|
.link = (void **) &next_LoadLibraryW,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wchar_t *target_modules[] = {
|
||||||
|
L"mono.dll",
|
||||||
|
L"cri_ware_unity.dll",
|
||||||
|
L"HKBSys_api.dll",
|
||||||
|
L"amdaemon_api.dll",
|
||||||
|
};
|
||||||
|
static const size_t target_modules_len = _countof(target_modules);
|
||||||
|
|
||||||
|
void unity_hook_init(void)
|
||||||
|
{
|
||||||
|
dll_hook_insert_hooks(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dll_hook_insert_hooks(HMODULE target)
|
||||||
|
{
|
||||||
|
hook_table_apply(
|
||||||
|
target,
|
||||||
|
"kernel32.dll",
|
||||||
|
unity_kernel32_syms,
|
||||||
|
_countof(unity_kernel32_syms));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name)
|
||||||
|
{
|
||||||
|
const wchar_t *name_end;
|
||||||
|
const wchar_t *target_module;
|
||||||
|
bool already_loaded;
|
||||||
|
HMODULE result;
|
||||||
|
size_t name_len;
|
||||||
|
size_t target_module_len;
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the module is already loaded
|
||||||
|
already_loaded = GetModuleHandleW(name) != NULL;
|
||||||
|
|
||||||
|
// Must call the next handler so the DLL reference count is incremented
|
||||||
|
result = next_LoadLibraryW(name);
|
||||||
|
|
||||||
|
if (!already_loaded && result != NULL) {
|
||||||
|
name_len = wcslen(name);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < target_modules_len; i++) {
|
||||||
|
target_module = target_modules[i];
|
||||||
|
target_module_len = wcslen(target_module);
|
||||||
|
|
||||||
|
// Check if the newly loaded library is at least the length of
|
||||||
|
// the name of the target module
|
||||||
|
if (name_len < target_module_len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_end = &name[name_len - target_module_len];
|
||||||
|
|
||||||
|
// Check if the name of the newly loaded library is one of the
|
||||||
|
// modules the path hooks should be injected into
|
||||||
|
if (_wcsicmp(name_end, target_module) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintf("Unity: Loaded %S\n", target_module);
|
||||||
|
|
||||||
|
dll_hook_insert_hooks(result);
|
||||||
|
path_hook_insert_hooks(result);
|
||||||
|
reg_hook_insert_hooks(result);
|
||||||
|
proc_addr_insert_hooks(result);
|
||||||
|
serial_hook_apply_hooks(result);
|
||||||
|
iohook_apply_hooks(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
3
hkbhook/unity.h
Normal file
3
hkbhook/unity.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void unity_hook_init(void);
|
31
hkbio/config.c
Normal file
31
hkbio/config.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hkbio/config.h"
|
||||||
|
|
||||||
|
void hkb_io_config_load(
|
||||||
|
struct hkb_io_config *cfg,
|
||||||
|
const wchar_t *filename)
|
||||||
|
{
|
||||||
|
wchar_t key[240];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename);
|
||||||
|
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename);
|
||||||
|
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename);
|
||||||
|
|
||||||
|
cfg->vk_up = GetPrivateProfileIntW(L"io4", L"up", VK_UP, filename);
|
||||||
|
cfg->vk_down = GetPrivateProfileIntW(L"io4", L"down", VK_DOWN, filename);
|
||||||
|
cfg->vk_left = GetPrivateProfileIntW(L"io4", L"left", VK_LEFT, filename);
|
||||||
|
cfg->vk_right = GetPrivateProfileIntW(L"io4", L"right", VK_RIGHT, filename);
|
||||||
|
cfg->vk_enter = GetPrivateProfileIntW(L"io4", L"enter", VK_SPACE, filename);
|
||||||
|
cfg->vk_cancel = GetPrivateProfileIntW(L"io4", L"cancel", VK_LSHIFT, filename);
|
||||||
|
cfg->vk_arr_right = GetPrivateProfileIntW(L"io4", L"right_arrow", 'A', filename);
|
||||||
|
cfg->vk_arr_left = GetPrivateProfileIntW(L"io4", L"left_arrow", 'D', filename);
|
||||||
|
}
|
24
hkbio/config.h
Normal file
24
hkbio/config.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct hkb_io_config {
|
||||||
|
uint8_t vk_test;
|
||||||
|
uint8_t vk_service;
|
||||||
|
uint8_t vk_coin;
|
||||||
|
uint8_t vk_up;
|
||||||
|
uint8_t vk_down;
|
||||||
|
uint8_t vk_left;
|
||||||
|
uint8_t vk_right;
|
||||||
|
uint8_t vk_enter;
|
||||||
|
uint8_t vk_cancel;
|
||||||
|
uint8_t vk_arr_right;
|
||||||
|
uint8_t vk_arr_left;
|
||||||
|
};
|
||||||
|
|
||||||
|
void hkb_io_config_load(
|
||||||
|
struct hkb_io_config *cfg,
|
||||||
|
const wchar_t *filename);
|
74
hkbio/hkbio.c
Normal file
74
hkbio/hkbio.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <xinput.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "hkbio/hkbio.h"
|
||||||
|
#include "hkbio/config.h"
|
||||||
|
|
||||||
|
static struct hkb_io_config cfg;
|
||||||
|
|
||||||
|
uint16_t hkb_io_get_api_version(void)
|
||||||
|
{
|
||||||
|
return 0x0100;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hkb_io_init(void)
|
||||||
|
{
|
||||||
|
hkb_io_config_load(&cfg, L".\\segatools.ini");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hkb_io_poll(uint8_t *opbtn, uint8_t *gamebtn)
|
||||||
|
{
|
||||||
|
|
||||||
|
*opbtn = 0;
|
||||||
|
*gamebtn = 0;
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_test) & 0x8000) {
|
||||||
|
*opbtn |= HKB_IO_OPBTN_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_service) & 0x8000) {
|
||||||
|
*opbtn |= HKB_IO_OPBTN_SERVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_coin) & 0x8000) {
|
||||||
|
*opbtn |= HKB_IO_OPBTN_COIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_right) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_left) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_up) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_down) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_enter) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_ENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_cancel) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_arr_right) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_ARR_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetAsyncKeyState(cfg.vk_arr_left) & 0x8000) {
|
||||||
|
*gamebtn |= HKB_IO_GAMEBTN_ARR_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
47
hkbio/hkbio.h
Normal file
47
hkbio/hkbio.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HKB_IO_OPBTN_TEST = 0x01,
|
||||||
|
HKB_IO_OPBTN_SERVICE = 0x02,
|
||||||
|
HKB_IO_OPBTN_COIN = 0x04,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HKB_IO_GAMEBTN_RIGHT = 0x01,
|
||||||
|
HKB_IO_GAMEBTN_LEFT = 0x02,
|
||||||
|
HKB_IO_GAMEBTN_UP = 0x04,
|
||||||
|
HKB_IO_GAMEBTN_DOWN = 0x08,
|
||||||
|
HKB_IO_GAMEBTN_ENTER = 0x10,
|
||||||
|
HKB_IO_GAMEBTN_CANCEL = 0x20,
|
||||||
|
HKB_IO_GAMEBTN_ARR_RIGHT = 0x40,
|
||||||
|
HKB_IO_GAMEBTN_ARR_LEFT = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get the version of the Ongeki 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 hkb_io_get_api_version(void);
|
||||||
|
|
||||||
|
/* Initialize the IO DLL. This is the second function that will be called on
|
||||||
|
your DLL, after hkb_io_get_api_version.
|
||||||
|
|
||||||
|
All subsequent calls to this API may originate from arbitrary threads.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
HRESULT hkb_io_init(void);
|
||||||
|
|
||||||
|
/* Send any queued outputs (of which there are currently none, though this may
|
||||||
|
change in subsequent API versions) and retrieve any new inputs.
|
||||||
|
|
||||||
|
Minimum API version: 0x0100 */
|
||||||
|
|
||||||
|
HRESULT hkb_io_poll(uint8_t *opbtn, uint8_t *gamebtn);
|
13
hkbio/meson.build
Normal file
13
hkbio/meson.build
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
hkbio_lib = static_library(
|
||||||
|
'hkbio',
|
||||||
|
name_prefix : '',
|
||||||
|
include_directories : inc,
|
||||||
|
implicit_include_directories : false,
|
||||||
|
c_pch : '../precompiled.h',
|
||||||
|
sources : [
|
||||||
|
'hkbio.c',
|
||||||
|
'hkbio.h',
|
||||||
|
'config.c',
|
||||||
|
'config.h',
|
||||||
|
],
|
||||||
|
)
|
@ -62,6 +62,7 @@ subdir('mu3io')
|
|||||||
subdir('mercuryio')
|
subdir('mercuryio')
|
||||||
subdir('cxbio')
|
subdir('cxbio')
|
||||||
subdir('mai2io')
|
subdir('mai2io')
|
||||||
|
subdir('hkbio')
|
||||||
|
|
||||||
subdir('chunihook')
|
subdir('chunihook')
|
||||||
subdir('divahook')
|
subdir('divahook')
|
||||||
@ -72,3 +73,4 @@ subdir('mu3hook')
|
|||||||
subdir('mercuryhook')
|
subdir('mercuryhook')
|
||||||
subdir('cxbhook')
|
subdir('cxbhook')
|
||||||
subdir('mai2hook')
|
subdir('mai2hook')
|
||||||
|
subdir('hkbhook')
|
||||||
|
@ -36,12 +36,20 @@ static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
|||||||
static wchar_t* my_System_getAppRootPath();
|
static wchar_t* my_System_getAppRootPath();
|
||||||
static wchar_t* (*next_System_getAppRootPath)();
|
static wchar_t* (*next_System_getAppRootPath)();
|
||||||
|
|
||||||
|
static wchar_t* my_AppImage_getOptionMountRootPath();
|
||||||
|
static wchar_t* (*next_AppImage_getOptionMountRootPath)();
|
||||||
|
|
||||||
static const struct hook_symbol amdaemon_syms[] = {
|
static const struct hook_symbol amdaemon_syms[] = {
|
||||||
{
|
{
|
||||||
.name = "System_getAppRootPath",
|
.name = "System_getAppRootPath",
|
||||||
.patch = my_System_getAppRootPath,
|
.patch = my_System_getAppRootPath,
|
||||||
.link = (void **) &next_System_getAppRootPath,
|
.link = (void **) &next_System_getAppRootPath,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "AppImage_getOptionMountRootPath",
|
||||||
|
.patch = my_AppImage_getOptionMountRootPath,
|
||||||
|
.link = (void **) &next_AppImage_getOptionMountRootPath,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static wchar_t game[5] = {0};
|
static wchar_t game[5] = {0};
|
||||||
@ -505,3 +513,11 @@ static wchar_t* my_System_getAppRootPath()
|
|||||||
wcscat_s(path, MAX_PATH, L"\\");
|
wcscat_s(path, MAX_PATH, L"\\");
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wchar_t* my_AppImage_getOptionMountRootPath()
|
||||||
|
{
|
||||||
|
wchar_t *path = malloc(sizeof(wchar_t) * MAX_PATH);
|
||||||
|
wcscpy_s(path, MAX_PATH, vfs_config.option);
|
||||||
|
wcscat_s(path, MAX_PATH, L"\\");
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user