forked from Hay1tsme/segatools
ekt: initial code
This commit is contained in:
19
Package.mk
19
Package.mk
@ -256,6 +256,24 @@ $(BUILD_DIR_ZIP)/apm3.zip:
|
||||
$(V)strip $(BUILD_DIR_ZIP)/apm3/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/apm3 ; zip -r ../apm3.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/ekt.zip:
|
||||
$(V)echo ... $@
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/ekt
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/ekt/DEVICE
|
||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
|
||||
$(BUILD_DIR_GAMES_64)/ekthook/ekthook.dll \
|
||||
$(DIST_DIR)/ekt/segatools_terminal.ini \
|
||||
$(DIST_DIR)/ekt/segatools_satellite.ini \
|
||||
$(DIST_DIR)/ekt/launch_terminal.bat \
|
||||
$(DIST_DIR)/ekt/launch_satellite.bat \
|
||||
$(DIST_DIR)/ekt/config_hook.json \
|
||||
$(BUILD_DIR_ZIP)/ekt
|
||||
$(V)cp pki/billing.pub \
|
||||
pki/ca.crt \
|
||||
$(BUILD_DIR_ZIP)/ekt/DEVICE
|
||||
$(V)strip $(BUILD_DIR_ZIP)/ekt/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/ekt ; zip -r ../ekt.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||
$(DOC_DIR)/config \
|
||||
$(DOC_DIR)/chunihook.md \
|
||||
@ -282,6 +300,7 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
|
||||
$(BUILD_DIR_ZIP)/fgo.zip \
|
||||
$(BUILD_DIR_ZIP)/kemono.zip \
|
||||
$(BUILD_DIR_ZIP)/apm3.zip \
|
||||
$(BUILD_DIR_ZIP)/ekt.zip \
|
||||
CHANGELOG.md \
|
||||
README.md \
|
||||
|
||||
|
5
dist/ekt/config_hook.json
vendored
Normal file
5
dist/ekt/config_hook.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"common": {
|
||||
"language": "english"
|
||||
}
|
||||
}
|
18
dist/ekt/launch_satellite.bat
vendored
Normal file
18
dist/ekt/launch_satellite.bat
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
set SEGATOOLS_CONFIG_PATH=..\segatools_satellite.ini
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
pushd PackageBase
|
||||
start /min "AM Daemon" ..\inject -d -k ..\ekthook.dll amdaemon.exe -c config_sate.json ..\config_hook.json
|
||||
popd
|
||||
pushd exe
|
||||
..\inject -d -k ..\ekthook.dll ekt.exe -logfile game.log -screen-fullscreen 0 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes
|
||||
popd
|
||||
exit /b 0
|
||||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
echo.
|
||||
echo Game processes have terminated
|
||||
pause
|
18
dist/ekt/launch_terminal.bat
vendored
Normal file
18
dist/ekt/launch_terminal.bat
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
set SEGATOOLS_CONFIG_PATH=..\segatools_terminal.ini
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
pushd PackageBase
|
||||
start /min "AM Daemon" ..\inject -d -k ..\ekthook.dll amdaemon.exe -c config_sate.json ..\config_hook.json
|
||||
popd
|
||||
pushd exe
|
||||
..\inject -d -k ..\ekthook.dll ekt.exe -logfile game.log -screen-fullscreen 0 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes
|
||||
popd
|
||||
exit /b 0
|
||||
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
echo.
|
||||
echo Game processes have terminated
|
||||
pause
|
170
dist/ekt/segatools_satellite.ini
vendored
Normal file
170
dist/ekt/segatools_satellite.ini
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
; -----------------------------------------------------------------------------
|
||||
; Path settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[vfs]
|
||||
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||
amfs=
|
||||
; Insert the path to the game Option directory here (contains Axxx directories)
|
||||
option=
|
||||
; 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=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Device settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[aime]
|
||||
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
|
||||
; reader.
|
||||
enable=1
|
||||
aimePath=DEVICE\aime.txt
|
||||
|
||||
; Virtual-key code. If this button is **held** then the emulated IC card reader
|
||||
; emulates an IC card in its proximity. A variety of different IC cards can be
|
||||
; emulated; the exact choice of card that is emulated depends on the presence or
|
||||
; absence of the configured card ID files. Default is the Return key.
|
||||
scan=0x0D
|
||||
|
||||
[led15093]
|
||||
; 837-15093-06 LED board emulation setting.
|
||||
enable=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Network settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
; The final octet of the local host's IP address on the virtualized subnet (so,
|
||||
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
|
||||
; local host's virtualized LAN IP is `192.168.32.11`).
|
||||
addrSuffix=11
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Board settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[keychip]
|
||||
; Keychip serial number. Keychip serials observed in the wild follow this
|
||||
; pattern: `A\d{2}(E|X)-(01|20)[ABCDU]\d{8}`.
|
||||
id=A69E-01A88888888
|
||||
|
||||
; 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.189.0
|
||||
|
||||
; Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This
|
||||
; is actually supposed to be a separate three-character `platformId` and
|
||||
; integer `modelType` setting, but they are combined here for convenience.
|
||||
; Use `ACA1` for the Satellite.
|
||||
; Use `ACA2` for the Terminal.
|
||||
platformId=ACA1
|
||||
|
||||
[pcbid]
|
||||
; Set the Windows host name. This should be an ALLS MAIN ID, without the
|
||||
; hyphen (which is not a valid character in a Windows host name).
|
||||
serialNo=ACAE01A99999999
|
||||
|
||||
[system]
|
||||
; Enable ALLS system settings.
|
||||
enable=1
|
||||
|
||||
; Enable freeplay mode. This will disable the coin slot and set the game to
|
||||
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
|
||||
; allow you to start a game in freeplay mode.
|
||||
freeplay=0
|
||||
|
||||
; LAN Install: If multiple machines are present on the same LAN then set
|
||||
; this to 1 on exactly one machine and set this to 0 on all others.
|
||||
dipsw1=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Misc. hook settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[unity]
|
||||
; Enable Unity hook. This will allow you to run custom .NET code before the game
|
||||
enable=1
|
||||
|
||||
; Path to a .NET DLL that should run before the game. Useful for loading
|
||||
; modding frameworks such as BepInEx.
|
||||
targetAssembly=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Custom IO settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[aimeio]
|
||||
; To use a custom card reader IO DLL enter its path here.
|
||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||
path=
|
||||
|
||||
[ektio]
|
||||
; To use a custom APM3 IO DLL enter its path here.
|
||||
; Leave empty if you want to use Segatools built-in gamepad input.
|
||||
path=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Input settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
|
||||
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
|
||||
;
|
||||
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
;
|
||||
; This is, admittedly, not the most user-friendly configuration method in the
|
||||
; world. An improved solution will be provided later.
|
||||
|
||||
[io4]
|
||||
; Test button virtual-key code. Default is the 1 key.
|
||||
test=0x31
|
||||
; Service button virtual-key code. Default is the 2 key.
|
||||
service=0x32
|
||||
; Keyboard button to increment coin counter. Default is the 3 key.
|
||||
coin=0x33
|
||||
; SW1. Default is the 4 key.
|
||||
sw1=0x34
|
||||
; SW2. Default is the 5 key.
|
||||
sw2=0x35
|
||||
|
||||
; Input API selection for IO4 input emulator.
|
||||
; For now only "keyboard" is supported.
|
||||
mode=keyboard
|
||||
|
||||
[keyboard]
|
||||
|
||||
menu=0x41
|
||||
start=0x42
|
||||
stratagem=0x43
|
||||
stratagem_lock=0x44
|
||||
hougu=0x45
|
||||
|
||||
tenkey_0=0x60
|
||||
tenkey_1=0x61
|
||||
tenkey_2=0x62
|
||||
tenkey_3=0x63
|
||||
tenkey_4=0x64
|
||||
tenkey_5=0x65
|
||||
tenkey_6=0x66
|
||||
tenkey_7=0x67
|
||||
tenkey_8=0x68
|
||||
tenkey_9=0x69
|
||||
tenkey_clear=0x6E
|
||||
tenkey_enter=0x0D
|
||||
|
||||
vol_down=0x6D
|
||||
vol_up=0x6B
|
||||
|
158
dist/ekt/segatools_terminal.ini
vendored
Normal file
158
dist/ekt/segatools_terminal.ini
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
; -----------------------------------------------------------------------------
|
||||
; Path settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[vfs]
|
||||
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||
amfs=
|
||||
; Insert the path to the game Option directory here (contains Axxx directories)
|
||||
option=
|
||||
; 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=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Device settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[aime]
|
||||
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
|
||||
; reader.
|
||||
enable=1
|
||||
aimePath=DEVICE\aime.txt
|
||||
|
||||
; Virtual-key code. If this button is **held** then the emulated IC card reader
|
||||
; emulates an IC card in its proximity. A variety of different IC cards can be
|
||||
; emulated; the exact choice of card that is emulated depends on the presence or
|
||||
; absence of the configured card ID files. Default is the Return key.
|
||||
scan=0x0D
|
||||
|
||||
[led15093]
|
||||
; 837-15093-06 LED board emulation setting.
|
||||
enable=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Network settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
; The final octet of the local host's IP address on the virtualized subnet (so,
|
||||
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
|
||||
; local host's virtualized LAN IP is `192.168.32.11`).
|
||||
addrSuffix=11
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Board settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[keychip]
|
||||
; Keychip serial number. Keychip serials observed in the wild follow this
|
||||
; pattern: `A\d{2}(E|X)-(01|20)[ABCDU]\d{8}`.
|
||||
id=A69E-01A88888888
|
||||
|
||||
; 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.189.0
|
||||
|
||||
; Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This
|
||||
; is actually supposed to be a separate three-character `platformId` and
|
||||
; integer `modelType` setting, but they are combined here for convenience.
|
||||
; Use `ACA1` for the Satellite.
|
||||
; Use `ACA2` for the Terminal.
|
||||
platformId=ACA2
|
||||
|
||||
[pcbid]
|
||||
; Set the Windows host name. This should be an ALLS MAIN ID, without the
|
||||
; hyphen (which is not a valid character in a Windows host name).
|
||||
serialNo=ACAE01A99999999
|
||||
|
||||
[system]
|
||||
; Enable ALLS system settings.
|
||||
enable=1
|
||||
|
||||
; Enable freeplay mode. This will disable the coin slot and set the game to
|
||||
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
|
||||
; allow you to start a game in freeplay mode.
|
||||
freeplay=0
|
||||
|
||||
; LAN Install: If multiple machines are present on the same LAN then set
|
||||
; this to 1 on exactly one machine and set this to 0 on all others.
|
||||
dipsw1=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Misc. hook settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[unity]
|
||||
; Enable Unity hook. This will allow you to run custom .NET code before the game
|
||||
enable=1
|
||||
|
||||
; Path to a .NET DLL that should run before the game. Useful for loading
|
||||
; modding frameworks such as BepInEx.
|
||||
targetAssembly=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Custom IO settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[aimeio]
|
||||
; To use a custom card reader IO DLL enter its path here.
|
||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||
path=
|
||||
|
||||
[ektio]
|
||||
; To use a custom APM3 IO DLL enter its path here.
|
||||
; Leave empty if you want to use Segatools built-in gamepad input.
|
||||
path=
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Input settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
|
||||
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
|
||||
;
|
||||
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||
;
|
||||
; This is, admittedly, not the most user-friendly configuration method in the
|
||||
; world. An improved solution will be provided later.
|
||||
|
||||
[io4]
|
||||
; Test button virtual-key code. Default is the 1 key.
|
||||
test=0x31
|
||||
; Service button virtual-key code. Default is the 2 key.
|
||||
service=0x32
|
||||
; Keyboard button to increment coin counter. Default is the 3 key.
|
||||
coin=0x33
|
||||
; SW1. Default is the 4 key.
|
||||
sw1=0x34
|
||||
; SW2. Default is the 5 key.
|
||||
sw2=0x35
|
||||
|
||||
; Input API selection for IO4 input emulator.
|
||||
; For now only "keyboard" is supported.
|
||||
mode=keyboard
|
||||
|
||||
[keyboard]
|
||||
|
||||
cancel=0x53
|
||||
decide=0x41
|
||||
|
||||
up=0x26
|
||||
right=0x27
|
||||
down=0x28
|
||||
left=0x25
|
||||
|
||||
left_2=0x4F
|
||||
right_2=0x57
|
117
games/ekthook/config.c
Normal file
117
games/ekthook/config.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "amex/amex.h"
|
||||
#include "amex/config.h"
|
||||
|
||||
#include "board/config.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
#include "ekthook/config.h"
|
||||
#include "ekthook/ekt-dll.h"
|
||||
|
||||
void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
wchar_t tmpstr[16];
|
||||
|
||||
memset(cfg->board_number, ' ', sizeof(cfg->board_number));
|
||||
memset(cfg->chip_number, ' ', sizeof(cfg->chip_number));
|
||||
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
|
||||
cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
|
||||
cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 0, filename);
|
||||
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
|
||||
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename);
|
||||
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"led15093",
|
||||
L"boardNumber",
|
||||
L"15093-06",
|
||||
tmpstr,
|
||||
_countof(tmpstr),
|
||||
filename);
|
||||
|
||||
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
|
||||
for (int i = n; i < sizeof(cfg->board_number); i++)
|
||||
{
|
||||
cfg->board_number[i] = ' ';
|
||||
}
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"led15093",
|
||||
L"chipNumber",
|
||||
L"6710A",
|
||||
tmpstr,
|
||||
_countof(tmpstr),
|
||||
filename);
|
||||
|
||||
n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number));
|
||||
for (int i = n; i < sizeof(cfg->chip_number); i++)
|
||||
{
|
||||
cfg->chip_number[i] = ' ';
|
||||
}
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"led15093",
|
||||
L"bootChipNumber",
|
||||
L"6709 ",
|
||||
tmpstr,
|
||||
_countof(tmpstr),
|
||||
filename);
|
||||
|
||||
n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number));
|
||||
for (int i = n; i < sizeof(cfg->boot_chip_number); i++)
|
||||
{
|
||||
cfg->boot_chip_number[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void ekt_dll_config_load(
|
||||
struct ekt_dll_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"ektio",
|
||||
L"path",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
}
|
||||
|
||||
void ekt_hook_config_load(
|
||||
struct ekt_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);
|
||||
io4_config_load(&cfg->io4, filename);
|
||||
dvd_config_load(&cfg->dvd, filename);
|
||||
led15093_config_load(&cfg->led15093, filename);
|
||||
y3_config_load(&cfg->y3, filename);
|
||||
ekt_dll_config_load(&cfg->dll, filename);
|
||||
}
|
||||
|
||||
void y3_config_load(struct y3_config *cfg, const wchar_t *filename){
|
||||
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"y3", L"enable", 1, filename);
|
||||
cfg->ws_enable = GetPrivateProfileIntW(L"y3", L"ws_enable", 1, filename);
|
||||
cfg->ws_port = GetPrivateProfileIntW(L"y3", L"ws_port", 3597, filename);
|
||||
cfg->ws_timeout = GetPrivateProfileIntW(L"y3", L"ws_timeout", 30000, filename);
|
||||
}
|
41
games/ekthook/config.h
Normal file
41
games/ekthook/config.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ekt-dll.h"
|
||||
#include "amex/amex.h"
|
||||
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/config.h"
|
||||
#include "board/led15093.h"
|
||||
|
||||
#include "hooklib/dvd.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
#include "unityhook/config.h"
|
||||
|
||||
struct y3_config {
|
||||
uint8_t enable;
|
||||
uint8_t ws_enable;
|
||||
uint16_t ws_port;
|
||||
uint32_t ws_timeout;
|
||||
};
|
||||
|
||||
struct ekt_hook_config {
|
||||
struct platform_config platform;
|
||||
struct aime_config aime;
|
||||
struct io4_config io4;
|
||||
struct dvd_config dvd;
|
||||
struct led15093_config led15093;
|
||||
struct y3_config y3;
|
||||
struct ekt_dll_config dll;
|
||||
struct unity_config unity;
|
||||
};
|
||||
|
||||
void ekt_hook_config_load(
|
||||
struct ekt_hook_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void y3_config_load(
|
||||
struct y3_config *cfg,
|
||||
const wchar_t *filename);
|
192
games/ekthook/dllmain.c
Normal file
192
games/ekthook/dllmain.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#include "ekt-dll.h"
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/led15093.h"
|
||||
|
||||
#include "hook/process.h"
|
||||
|
||||
#include "hooklib/serial.h"
|
||||
#include "hooklib/spike.h"
|
||||
|
||||
#include "ekthook/config.h"
|
||||
#include "ekthook/io4.h"
|
||||
#include "ekthook/y3.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "unityhook/hook.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
#include "util/env.h"
|
||||
|
||||
/*
|
||||
* Eiketsu Taisen
|
||||
*
|
||||
* IP: 192.168.189.0
|
||||
*
|
||||
* SATELLITE: Model Type 1
|
||||
*
|
||||
* COM2: LED
|
||||
* COM3: AIME
|
||||
* COM3: "TM LED"
|
||||
* COM4: FPR / Y3
|
||||
*
|
||||
* TERMINAL: Model Type 2
|
||||
*
|
||||
* COM1: Aime
|
||||
* COM3: LED
|
||||
*
|
||||
*/
|
||||
|
||||
static HMODULE ekt_hook_mod;
|
||||
static process_entry_t ekt_startup;
|
||||
static struct ekt_hook_config ekt_hook_cfg;
|
||||
|
||||
static const wchar_t *target_modules[] = {
|
||||
L"Y3CodeReaderNE.dll",
|
||||
};
|
||||
|
||||
static const size_t target_modules_len = _countof(target_modules);
|
||||
|
||||
void unity_hook_callback(HMODULE hmodule, const wchar_t* p) {
|
||||
dprintf("Unity: Hook callback: %ls\n", p);
|
||||
|
||||
for (size_t i = 0; i < target_modules_len; i++) {
|
||||
if (_wcsicmp(p, target_modules[i]) == 0) {
|
||||
serial_hook_apply_hooks(hmodule);
|
||||
iohook_apply_hooks(hmodule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD CALLBACK ekt_pre_startup(void)
|
||||
{
|
||||
HMODULE d3dc;
|
||||
HMODULE dbghelp;
|
||||
HRESULT hr;
|
||||
bool is_terminal;
|
||||
|
||||
dprintf("--- Begin ekt_pre_startup ---\n");
|
||||
|
||||
/* Pin the D3D shader compiler. This makes startup much faster. */
|
||||
|
||||
d3dc = LoadLibraryA("d3dcompiler_43.dll");
|
||||
|
||||
if (d3dc != NULL) {
|
||||
dprintf("Pinned shader compiler, hMod=%p\n", d3dc);
|
||||
} else {
|
||||
dprintf("Failed to load shader compiler!\n");
|
||||
}
|
||||
|
||||
/* Pin dbghelp so the path hooks apply to it. */
|
||||
|
||||
dbghelp = LoadLibraryW(L"dbghelp.dll");
|
||||
|
||||
if (dbghelp != NULL) {
|
||||
dprintf("Pinned debug helper library, hMod=%p\n", dbghelp);
|
||||
} else {
|
||||
dprintf("Failed to load debug helper library!\n");
|
||||
}
|
||||
|
||||
/* Load config */
|
||||
|
||||
ekt_hook_config_load(&ekt_hook_cfg, get_config_path());
|
||||
|
||||
/* Hook Win32 APIs */
|
||||
serial_hook_init();
|
||||
|
||||
/* Initialize emulation hooks */
|
||||
|
||||
// Terminal = AAV1, Satellite = AAV2
|
||||
hr = platform_hook_init(
|
||||
&ekt_hook_cfg.platform,
|
||||
"SDGY",
|
||||
"AAV1",
|
||||
ekt_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Initialize Terminal/Satellite hooks */
|
||||
if (strncmp(ekt_hook_cfg.platform.nusec.platform_id, "AAV1", 4) == 0) {
|
||||
// Terminal
|
||||
is_terminal = true;
|
||||
} else if (strncmp(ekt_hook_cfg.platform.nusec.platform_id, "AAV2", 4) == 0) {
|
||||
// Satellite
|
||||
is_terminal = false;
|
||||
} else {
|
||||
// Unknown
|
||||
dprintf("Unknown platform ID: %s\n", ekt_hook_cfg.platform.nusec.platform_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = ekt_dll_init(&ekt_hook_cfg.dll, ekt_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = ekt_io4_hook_init(&ekt_hook_cfg.io4, is_terminal);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
unsigned int led_port_no[2] = {is_terminal ? 3 : 2, 0};
|
||||
hr = led15093_hook_init(&ekt_hook_cfg.led15093,
|
||||
ekt_dll.led_init, ekt_dll.led_set_leds, led_port_no);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
hr = sg_reader_hook_init(&ekt_hook_cfg.aime, is_terminal ? 1 : 3, ekt_hook_cfg.aime.gen, ekt_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
unity_hook_init(&ekt_hook_cfg.unity, ekt_hook_mod, unity_hook_callback);
|
||||
|
||||
y3_hook_init(&ekt_hook_cfg.y3, ekt_hook_mod);
|
||||
|
||||
/* Initialize debug helpers */
|
||||
|
||||
spike_hook_init(get_config_path());
|
||||
|
||||
dprintf("--- End ekt_pre_startup ---\n");
|
||||
|
||||
/* Jump to EXE start address */
|
||||
|
||||
return ekt_startup();
|
||||
|
||||
fail:
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (cause != DLL_PROCESS_ATTACH) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ekt_hook_mod = mod;
|
||||
|
||||
hr = process_hijack_startup(ekt_pre_startup, &ekt_startup);
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
dprintf("Failed to hijack process startup: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
118
games/ekthook/ekt-dll.c
Normal file
118
games/ekthook/ekt-dll.c
Normal file
@ -0,0 +1,118 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ekthook/ekt-dll.h"
|
||||
|
||||
#include "util/dll-bind.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
const struct dll_bind_sym ekt_dll_syms[] = {
|
||||
{
|
||||
.sym = "ekt_io_init",
|
||||
.off = offsetof(struct ekt_dll, init),
|
||||
}, {
|
||||
.sym = "ekt_io_poll",
|
||||
.off = offsetof(struct ekt_dll, poll),
|
||||
}, {
|
||||
.sym = "ekt_io_get_opbtns",
|
||||
.off = offsetof(struct ekt_dll, get_opbtns),
|
||||
}, {
|
||||
.sym = "ekt_io_get_gamebtns",
|
||||
.off = offsetof(struct ekt_dll, get_gamebtns),
|
||||
}, {
|
||||
.sym = "ekt_io_get_trackball_position",
|
||||
.off = offsetof(struct ekt_dll, get_trackball_position),
|
||||
}, {
|
||||
.sym = "ekt_io_led_init",
|
||||
.off = offsetof(struct ekt_dll, led_init),
|
||||
}, {
|
||||
.sym = "ekt_io_led_set_colors",
|
||||
.off = offsetof(struct ekt_dll, led_set_leds),
|
||||
}
|
||||
};
|
||||
|
||||
struct ekt_dll ekt_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 ekt_dll_init(const struct ekt_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("EKT IO: Failed to load IO DLL: %lx: %S\n",
|
||||
hr,
|
||||
cfg->path);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
dprintf("EKT IO: Using custom IO DLL: %S\n", cfg->path);
|
||||
src = owned;
|
||||
} else {
|
||||
owned = NULL;
|
||||
src = self;
|
||||
}
|
||||
|
||||
get_api_version = (void *) GetProcAddress(src, "ekt_io_get_api_version");
|
||||
|
||||
if (get_api_version != NULL) {
|
||||
ekt_dll.api_version = get_api_version();
|
||||
} else {
|
||||
ekt_dll.api_version = 0x0100;
|
||||
dprintf("Custom IO DLL does not expose ekt_io_get_api_version, "
|
||||
"assuming API version 1.0.\n"
|
||||
"Please ask the developer to update their DLL.\n");
|
||||
}
|
||||
|
||||
if (ekt_dll.api_version >= 0x0200) {
|
||||
hr = E_NOTIMPL;
|
||||
dprintf("EKT IO: Custom IO DLL implements an unsupported "
|
||||
"API version (%#04x). Please update Segatools.\n",
|
||||
ekt_dll.api_version);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
sym = ekt_dll_syms;
|
||||
hr = dll_bind(&ekt_dll, src, &sym, _countof(ekt_dll_syms));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (src != self) {
|
||||
dprintf("EKT 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;
|
||||
}
|
24
games/ekthook/ekt-dll.h
Normal file
24
games/ekthook/ekt-dll.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "ektio/ektio.h"
|
||||
|
||||
struct ekt_dll {
|
||||
uint16_t api_version;
|
||||
HRESULT (*init)(void);
|
||||
HRESULT (*poll)(void);
|
||||
void (*get_opbtns)(uint8_t *opbtn);
|
||||
void (*get_gamebtns)(uint32_t *gamebtn);
|
||||
void (*get_trackball_position)(uint8_t *x, uint8_t *y);
|
||||
HRESULT (*led_init)(void);
|
||||
void (*led_set_leds)(uint8_t board, uint8_t *rgb);
|
||||
};
|
||||
|
||||
struct ekt_dll_config {
|
||||
wchar_t path[MAX_PATH];
|
||||
};
|
||||
|
||||
extern struct ekt_dll ekt_dll;
|
||||
|
||||
HRESULT ekt_dll_init(const struct ekt_dll_config *cfg, HINSTANCE self);
|
49
games/ekthook/ekthook.def
Normal file
49
games/ekthook/ekthook.def
Normal file
@ -0,0 +1,49 @@
|
||||
LIBRARY taisenhook
|
||||
|
||||
EXPORTS
|
||||
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
|
||||
API_DLLVersion @1
|
||||
API_GetLastError @2
|
||||
API_GetErrorMessage @3
|
||||
API_Connect @4
|
||||
API_Close @5
|
||||
API_Start @6
|
||||
API_Stop @7
|
||||
API_GetFirmVersion @8
|
||||
API_GetFirmName @9
|
||||
API_GetTargetCode @10
|
||||
API_GetStatus @11
|
||||
API_GetCounter @12
|
||||
API_ClearError @13
|
||||
API_Reset @14
|
||||
API_GetCardInfo @15
|
||||
API_GetCardInfoCharSize @16
|
||||
API_SetDevice @17
|
||||
API_SetCommand @18
|
||||
API_FirmwareUpdate @19
|
||||
API_Calibration @20
|
||||
API_GetCalibrationResult @21
|
||||
API_GetProcTime @22
|
||||
API_GetMemStatus @23
|
||||
API_GetMemCounter @24
|
||||
API_SetSysControl @25
|
||||
API_GetSysControl @26
|
||||
API_SetParameter @27
|
||||
API_GetParameter @28
|
||||
API_TestReset @29
|
||||
API_DebugReset @30
|
||||
API_GetBoardType @31
|
||||
API_GetCardDataSize @32
|
||||
API_GetFirmDate @33
|
||||
API_SystemCommand @34
|
||||
API_CalcCheckSum @35
|
||||
API_GetCheckSumResult @36
|
||||
API_BlockRead @37
|
||||
API_GetBlockReadResult @38
|
||||
API_BlockWrite @39
|
||||
API_GetDebugParam @40
|
208
games/ekthook/io4.c
Normal file
208
games/ekthook/io4.c
Normal file
@ -0,0 +1,208 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
#include "ekthook/ekt-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HRESULT ekt_io4_poll(void *ctx, struct io4_state *state);
|
||||
static uint16_t coins;
|
||||
|
||||
static const struct io4_ops ekt_io4_ops = {
|
||||
.poll = ekt_io4_poll,
|
||||
};
|
||||
|
||||
static bool io_is_terminal;
|
||||
|
||||
HRESULT ekt_io4_hook_init(const struct io4_config *cfg, bool is_terminal)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(ekt_dll.init != NULL);
|
||||
|
||||
hr = io4_hook_init(cfg, &ekt_io4_ops, NULL);
|
||||
|
||||
io_is_terminal = is_terminal;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return ekt_dll.init();
|
||||
}
|
||||
|
||||
static HRESULT ekt_io4_poll(void *ctx, struct io4_state *state)
|
||||
{
|
||||
uint8_t opbtn, x, y;
|
||||
uint32_t gamebtn;
|
||||
HRESULT hr;
|
||||
|
||||
assert(ekt_dll.poll != NULL);
|
||||
assert(ekt_dll.get_opbtns != NULL);
|
||||
assert(ekt_dll.get_gamebtns != NULL);
|
||||
assert(ekt_dll.get_trackball_position != NULL);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
hr = ekt_dll.poll();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
opbtn = 0;
|
||||
gamebtn = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
ekt_dll.get_opbtns(&opbtn);
|
||||
ekt_dll.get_gamebtns(&gamebtn);
|
||||
ekt_dll.get_trackball_position(&x, &y);
|
||||
|
||||
if (opbtn & EKT_IO_OPBTN_TEST) {
|
||||
state->buttons[0] |= IO4_BUTTON_TEST;
|
||||
}
|
||||
|
||||
if (opbtn & EKT_IO_OPBTN_SERVICE) {
|
||||
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||
}
|
||||
|
||||
if (opbtn & EKT_IO_OPBTN_SW1) {
|
||||
state->buttons[0] |= 1 << 0; // TODO
|
||||
}
|
||||
|
||||
if (opbtn & EKT_IO_OPBTN_SW2) {
|
||||
state->buttons[0] |= 1 << 0; // TODO
|
||||
}
|
||||
|
||||
if (opbtn & EKT_IO_OPBTN_COIN) {
|
||||
coins++;
|
||||
}
|
||||
state->chutes[0] = coins << 8;
|
||||
|
||||
// TODO: indexes
|
||||
|
||||
if (!io_is_terminal) {
|
||||
if (gamebtn & EKT_IO_GAMEBTN_HOUGU) {
|
||||
state->buttons[1] |= 1 << 12;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_MENU) {
|
||||
state->buttons[0] |= 1 << 7;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_START) {
|
||||
state->buttons[0] |= 1 << 5;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_STRATAGEM) {
|
||||
state->buttons[0] |= 1 << 2;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_STRATAGEM_LOCK) {
|
||||
state->buttons[0] |= 1 << 2;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_VOL_DOWN) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_VOL_UP) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_0) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_1) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_2) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_3) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_4) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_5) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_6) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_7) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_8) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_9) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_CLEAR) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_NUMPAD_ENTER) {
|
||||
state->buttons[0] |= 1 << (io_is_terminal ? 4 : 4);
|
||||
}
|
||||
|
||||
if (io_is_terminal) {
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_CANCEL) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_DECIDE) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_LEFT) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_UP) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_RIGHT) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_DOWN) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_LEFT_2) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & EKT_IO_GAMEBTN_TERMINAL_RIGHT_2) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
state->adcs[0] = 1;
|
||||
state->adcs[1] = 1;
|
||||
state->adcs[2] = x;
|
||||
state->adcs[3] = y;
|
||||
|
||||
return S_OK;
|
||||
}
|
7
games/ekthook/io4.h
Normal file
7
games/ekthook/io4.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
HRESULT ekt_io4_hook_init(const struct io4_config *cfg, bool is_terminal);
|
32
games/ekthook/meson.build
Normal file
32
games/ekthook/meson.build
Normal file
@ -0,0 +1,32 @@
|
||||
shared_library(
|
||||
'ekthook',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
vs_module_defs : 'ekthook.def',
|
||||
dependencies : [
|
||||
capnhook.get_variable('hook_dep'),
|
||||
capnhook.get_variable('hooklib_dep')
|
||||
],
|
||||
link_with : [
|
||||
aimeio_lib,
|
||||
board_lib,
|
||||
ektio_lib,
|
||||
hooklib_lib,
|
||||
jvs_lib,
|
||||
platform_lib,
|
||||
unityhook_lib,
|
||||
util_lib,
|
||||
],
|
||||
sources : [
|
||||
'config.c',
|
||||
'config.h',
|
||||
'dllmain.c',
|
||||
'ekt-dll.c',
|
||||
'ekt-dll.h',
|
||||
'io4.c',
|
||||
'io4.h',
|
||||
'y3.c',
|
||||
'y3.h'
|
||||
],
|
||||
)
|
510
games/ekthook/y3.c
Normal file
510
games/ekthook/y3.c
Normal file
@ -0,0 +1,510 @@
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
#include "hooklib/dll.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
#include "ekthook/config.h"
|
||||
#include "ekthook/y3.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define CALL __cdecl
|
||||
|
||||
CALL float API_DLLVersion();
|
||||
CALL uint32_t API_GetLastError(int* hDevice);
|
||||
CALL uint32_t API_GetErrorMessage(uint32_t errNo, char* szMessage, int numBytes);
|
||||
CALL int* API_Connect(char* szPortName);
|
||||
CALL int API_Close(int* hDevice);
|
||||
CALL int API_Start(int* hDevice);
|
||||
CALL int API_Stop(int* hDevice);
|
||||
CALL float API_GetFirmVersion(int* hDevice);
|
||||
CALL uint32_t API_GetFirmName(int* hDevice);
|
||||
CALL uint32_t API_GetTargetCode(int* hDevice);
|
||||
CALL uint32_t API_GetStatus(int* hDevice);
|
||||
CALL uint32_t API_GetCounter(int* hDevice);
|
||||
CALL int API_ClearError(int* hDevice);
|
||||
CALL int API_Reset(int* hDevice, bool isHardReset);
|
||||
CALL int API_GetCardInfo(int* hDevice, int numCards, struct CardInfo* pCardInfo);
|
||||
CALL int API_GetCardInfoCharSize();
|
||||
CALL int API_FirmwareUpdate(int* hDevice, uint32_t address, uint32_t size, uint8_t* buffer);
|
||||
CALL int API_Calibration(int* hDevice, int calib);
|
||||
CALL int API_GetCalibrationResult(int* hDevice, int calib, uint32_t* result);
|
||||
CALL uint32_t API_GetProcTime(int* hDevice);
|
||||
CALL uint32_t API_GetMemStatus(int* hDevice);
|
||||
CALL uint32_t API_GetMemCounter(int* hDevice);
|
||||
CALL int API_SetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam);
|
||||
CALL int API_GetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam);
|
||||
|
||||
signed int CALL API_SetDevice(int a1, int a2);
|
||||
signed int CALL API_SetCommand(int a1, int a2, int a3, int *a4);
|
||||
signed int CALL API_SetSysControl(int a1, int a2, int *a3);
|
||||
signed int CALL API_GetSysControl(int a1, int a2, int *a3);
|
||||
int CALL API_TestReset(int a1);
|
||||
signed int API_DebugReset(int a1, ...);
|
||||
int CALL API_GetBoardType(int a1);
|
||||
int CALL API_GetCardDataSize(int a1);
|
||||
int CALL API_GetFirmDate(int a1);
|
||||
int API_SystemCommand(int a1, char a2, ...);
|
||||
int CALL API_CalcCheckSum(DWORD *a1, int a2, int a3);
|
||||
int CALL API_GetCheckSumResult(int a1);
|
||||
int CALL API_BlockRead(int a1, int a2, int a3, SIZE_T dwBytes);
|
||||
int CALL API_GetBlockReadResult(int a1, void *a2);
|
||||
int CALL API_BlockWrite(int a1, int a2, int a3, SIZE_T dwBytes, void *a5);
|
||||
signed int CALL API_GetDebugParam(int a1, int a2, DWORD *a3);
|
||||
|
||||
static const struct hook_symbol Y3_hooks[] = {
|
||||
{
|
||||
.name = "API_DLLVersion",
|
||||
.patch = API_DLLVersion,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetLastError",
|
||||
.patch = API_GetLastError,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetErrorMessage",
|
||||
.patch = API_GetErrorMessage,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Connect",
|
||||
.patch = API_Connect,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Close",
|
||||
.patch = API_Close,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Start",
|
||||
.patch = API_Start,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Stop",
|
||||
.patch = API_Stop,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetFirmVersion",
|
||||
.patch = API_GetFirmVersion,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetFirmName",
|
||||
.patch = API_GetFirmName,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetTargetCode",
|
||||
.patch = API_GetTargetCode,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetStatus",
|
||||
.patch = API_GetStatus,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCounter",
|
||||
.patch = API_GetCounter,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Reset",
|
||||
.patch = API_Reset,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCardInfo",
|
||||
.patch = API_GetCardInfo,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCardInfoCharSize",
|
||||
.patch = API_GetCardInfoCharSize,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_FirmwareUpdate",
|
||||
.patch = API_FirmwareUpdate,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_Calibration",
|
||||
.patch = API_Calibration,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCalibrationResult",
|
||||
.patch = API_GetCalibrationResult,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetProcTime",
|
||||
.patch = API_GetProcTime,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetMemStatus",
|
||||
.patch = API_GetMemStatus,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetMemCounter",
|
||||
.patch = API_GetMemCounter,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_SetParameter",
|
||||
.patch = API_SetParameter,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetParameter",
|
||||
.patch = API_GetParameter,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_SetDevice",
|
||||
.patch = API_SetDevice,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_SetCommand",
|
||||
.patch = API_SetCommand,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_SetSysControl",
|
||||
.patch = API_SetSysControl,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetSysControl",
|
||||
.patch = API_GetSysControl,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_TestReset",
|
||||
.patch = API_TestReset,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_DebugReset",
|
||||
.patch = API_DebugReset,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetBoardType",
|
||||
.patch = API_GetBoardType,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCardDataSize",
|
||||
.patch = API_GetCardDataSize,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetFirmDate",
|
||||
.patch = API_GetFirmDate,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_SystemCommand",
|
||||
.patch = API_SystemCommand,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_CalcCheckSum",
|
||||
.patch = API_CalcCheckSum,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetCheckSumResult",
|
||||
.patch = API_GetCheckSumResult,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_BlockRead",
|
||||
.patch = API_BlockRead,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetBlockReadResult",
|
||||
.patch = API_GetBlockReadResult,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_BlockWrite",
|
||||
.patch = API_BlockWrite,
|
||||
.link = NULL
|
||||
},
|
||||
{
|
||||
.name = "API_GetDebugParam",
|
||||
.patch = API_GetDebugParam,
|
||||
.link = NULL
|
||||
},
|
||||
};
|
||||
|
||||
static struct y3_config y3_config;
|
||||
|
||||
#define MAX_CARD_SIZE 32
|
||||
static struct CardInfo card_data[MAX_CARD_SIZE];
|
||||
|
||||
static const int* Y3_COM_FIELD = (int*)10;
|
||||
static const int* Y3_COM_PRINT = (int*)11;
|
||||
|
||||
|
||||
void y3_hook_init(const struct y3_config *cfg, HINSTANCE self){
|
||||
assert(cfg != NULL);
|
||||
|
||||
if (!cfg->enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&y3_config, cfg, sizeof(*cfg));
|
||||
|
||||
hook_table_apply(NULL, "Y3CodeReaderNE.dll", Y3_hooks, _countof(Y3_hooks));
|
||||
|
||||
if (self != NULL) {
|
||||
dll_hook_push(self, L"Y3CodeReaderNE.dll");
|
||||
}
|
||||
|
||||
memset(card_data, 0, sizeof(card_data));
|
||||
|
||||
dprintf("Y3: enabled\n");
|
||||
}
|
||||
|
||||
CALL float API_DLLVersion(){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
CALL uint32_t API_GetLastError(int* hDevice){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
if (!y3_config.enable) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
CALL uint32_t API_GetErrorMessage(uint32_t errNo, char* szMessage, int numBytes){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
if (!y3_config.enable) {
|
||||
strcpy_s(szMessage, numBytes, "Y3Emu is disabled but emulator DLL is called");
|
||||
} else {
|
||||
strcpy_s(szMessage, numBytes, "No error - Y3Emu");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
CALL int* API_Connect(char* szPortName){
|
||||
dprintf("Y3: %s(%s)\n", __func__, szPortName);
|
||||
if ((GetAsyncKeyState(0x11) & 0x8000) && (GetAsyncKeyState(0x42) & 0x8000)) {
|
||||
dprintf("Y3: Ctrl+B is active!\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!y3_config.enable) {
|
||||
return NULL;
|
||||
} else {
|
||||
char number[2];
|
||||
strncpy(number, szPortName+3, 2);
|
||||
return (int*)(uintptr_t)atoi(number);
|
||||
}
|
||||
}
|
||||
CALL int API_Close(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_Start(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_Stop(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
return 0;
|
||||
}
|
||||
CALL float API_GetFirmVersion(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
return 1;
|
||||
}
|
||||
CALL uint32_t API_GetFirmName(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
if (hDevice == Y3_COM_FIELD){
|
||||
dprintf("This Y3 device is FIELD\n");
|
||||
return 1380992595;
|
||||
} else if (hDevice == Y3_COM_PRINT){
|
||||
dprintf("This Y3 device is PRINTER\n");
|
||||
//DebugBreak();
|
||||
return 1414680659;
|
||||
} else {
|
||||
dprintf("This Y3 device is UNKNOWN\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
CALL uint32_t API_GetTargetCode(int* hDevice){
|
||||
dprintf("Y3: %s(%p)\n", __func__, hDevice);
|
||||
if (hDevice == Y3_COM_FIELD){
|
||||
dprintf("This Y3 device is FIELD\n");
|
||||
return 810698323;
|
||||
} else if (hDevice == Y3_COM_PRINT){
|
||||
dprintf("This Y3 device is PRINTER\n");
|
||||
//DebugBreak();
|
||||
return 810831955;
|
||||
} else {
|
||||
dprintf("This Y3 device is UNKNOWN\n");
|
||||
}
|
||||
return 1162760014;
|
||||
}
|
||||
CALL uint32_t API_GetStatus(int* hDevice){
|
||||
//dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL uint32_t API_GetCounter(int* hDevice){
|
||||
//dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_ClearError(int* hDevice){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_Reset(int* hDevice, bool isHardReset){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_GetCardInfo(int* hDevice, int numCards, struct CardInfo* pCardInfo){
|
||||
//dprintf("Y3: %s(%p), %d\n", __func__, hDevice, numCards);
|
||||
// ret = num cards
|
||||
// numCards = max cards
|
||||
|
||||
if (hDevice == Y3_COM_PRINT){
|
||||
pCardInfo[0].fX = 0;
|
||||
pCardInfo[0].fY = 0;
|
||||
pCardInfo[0].fAngle = 0;
|
||||
pCardInfo[0].eCardType = TYPE0;
|
||||
pCardInfo[0].eCardStatus = MARKER;
|
||||
pCardInfo[0].uID = 0x10;
|
||||
pCardInfo[0].nNumChars = 0;
|
||||
pCardInfo[0].ubChar0.Data = 0;
|
||||
pCardInfo[0].ubChar1.Data = 0x4000;
|
||||
pCardInfo[0].ubChar2.Data = 0;
|
||||
pCardInfo[0].ubChar3.Data = 0x0; // 40
|
||||
pCardInfo[0].ubChar4.Data = 0;
|
||||
pCardInfo[0].ubChar5.Data = 0;
|
||||
return 1;
|
||||
} else if (numCards == MAX_CARD_SIZE){
|
||||
memcpy(pCardInfo, card_data, sizeof(card_data));
|
||||
return MAX_CARD_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
CALL int API_GetCardInfoCharSize(){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_FirmwareUpdate(int* hDevice, uint32_t address, uint32_t size, uint8_t* buffer){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 1; // not supported
|
||||
}
|
||||
CALL int API_Calibration(int* hDevice, int calib){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
CALL int API_GetCalibrationResult(int* hDevice, int calib, uint32_t* result){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
CALL uint32_t API_GetProcTime(int* hDevice){
|
||||
//dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL uint32_t API_GetMemStatus(int* hDevice){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL uint32_t API_GetMemCounter(int* hDevice){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_SetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
CALL int API_GetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
signed int CALL API_SetDevice(int a1, int a2){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
signed int CALL API_SetCommand(int a1, int a2, int a3, int *a4){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
signed int CALL API_SetSysControl(int a1, int a2, int *a3){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
signed int CALL API_GetSysControl(int a1, int a2, int *a3){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_TestReset(int a1){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
signed int API_DebugReset(int a1, ...){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_GetBoardType(int a1){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_GetCardDataSize(int a1){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_GetFirmDate(int a1){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int API_SystemCommand(int a1, char a2, ...){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_CalcCheckSum(DWORD *a1, int a2, int a3){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_GetCheckSumResult(int a1){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_BlockRead(int a1, int a2, int a3, SIZE_T dwBytes){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_GetBlockReadResult(int a1, void *a2){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
int CALL API_BlockWrite(int a1, int a2, int a3, SIZE_T dwBytes, void *a5){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
signed int CALL API_GetDebugParam(int a1, int a2, DWORD *a3){
|
||||
dprintf("Y3: %s\n", __func__);
|
||||
return 0;
|
||||
}
|
57
games/ekthook/y3.h
Normal file
57
games/ekthook/y3.h
Normal file
@ -0,0 +1,57 @@
|
||||
enum Y3WebsocketProtocol {
|
||||
Y3_WS_PROTO_ERROR = 0,
|
||||
Y3_WS_PROTO_CARD_DATA = 2,
|
||||
Y3_WS_PROTO_PING = 1,
|
||||
Y3_WS_PROTO_GAME_TITLE = 3,
|
||||
};
|
||||
|
||||
struct CardByteData {
|
||||
unsigned int Data;
|
||||
};
|
||||
|
||||
struct CardInfo {
|
||||
float fX; // 0x00|0
|
||||
float fY; // 0x04|4
|
||||
float fAngle; // 0x08|8
|
||||
int eCardType; // 0x0C|12
|
||||
int eCardStatus; // 0x10|16
|
||||
unsigned int uID; // 0x14|20
|
||||
int nNumChars; // 0x18|24
|
||||
struct CardByteData ubChar0; // 0x1C|28
|
||||
struct CardByteData ubChar1; // 0x20|32
|
||||
struct CardByteData ubChar2; // 0x24|36
|
||||
struct CardByteData ubChar3; // 0x28|40
|
||||
struct CardByteData ubChar4; // 0x2C|44
|
||||
struct CardByteData ubChar5; // 0x30|48
|
||||
};
|
||||
|
||||
enum Type {
|
||||
// Token: 0x04000084 RID: 132
|
||||
TYPE0 = 0,
|
||||
// Token: 0x04000085 RID: 133
|
||||
TYPE1,
|
||||
// Token: 0x04000086 RID: 134
|
||||
TYPE2,
|
||||
// Token: 0x04000087 RID: 135
|
||||
TYPE3,
|
||||
// Token: 0x04000088 RID: 136
|
||||
TYPE4,
|
||||
// Token: 0x04000089 RID: 137
|
||||
TYPE5,
|
||||
// Token: 0x0400008A RID: 138
|
||||
TYPE6,
|
||||
// Token: 0x0400008B RID: 139
|
||||
TYPE7 = 7
|
||||
};
|
||||
|
||||
enum Status {
|
||||
INVALID = 0,
|
||||
// Token: 0x0400008E RID: 142
|
||||
VALID = 1,
|
||||
// Token: 0x0400008F RID: 143
|
||||
INFERENCE = 2,
|
||||
// Token: 0x04000090 RID: 144
|
||||
MARKER = 3
|
||||
};
|
||||
|
||||
void y3_hook_init(const struct y3_config *cfg, HINSTANCE self);
|
10
games/ektio/backend.h
Normal file
10
games/ektio/backend.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ektio/ektio.h"
|
||||
|
||||
struct ekt_io_backend {
|
||||
void (*get_gamebtns)(uint32_t *gamebtn);
|
||||
void (*get_trackball)(uint8_t *x, uint8_t *y);
|
||||
};
|
76
games/ektio/config.c
Normal file
76
games/ektio/config.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ektio/config.h"
|
||||
|
||||
#include <xinput.h>
|
||||
|
||||
|
||||
void ekt_kb_config_load(
|
||||
struct ekt_kb_config *cfg,
|
||||
const wchar_t *filename) {
|
||||
|
||||
cfg->vk_menu = GetPrivateProfileIntW(L"io4", L"menu", 'A', filename);
|
||||
cfg->vk_start = GetPrivateProfileIntW(L"io4", L"start", 'S', filename);
|
||||
cfg->vk_stratagem = GetPrivateProfileIntW(L"io4", L"stratagem", 'D', filename);
|
||||
cfg->vk_stratagem_lock = GetPrivateProfileIntW(L"io4", L"stratagem_lock", 'F', filename);
|
||||
cfg->vk_hougu = GetPrivateProfileIntW(L"io4", L"hougu", 'G', filename);
|
||||
|
||||
cfg->vk_tenkey_0 = GetPrivateProfileIntW(L"io4", L"tenkey_0", VK_NUMPAD0, filename);
|
||||
cfg->vk_tenkey_1 = GetPrivateProfileIntW(L"io4", L"tenkey_1", VK_NUMPAD1, filename);
|
||||
cfg->vk_tenkey_2 = GetPrivateProfileIntW(L"io4", L"tenkey_2", VK_NUMPAD2, filename);
|
||||
cfg->vk_tenkey_3 = GetPrivateProfileIntW(L"io4", L"tenkey_3", VK_NUMPAD3, filename);
|
||||
cfg->vk_tenkey_4 = GetPrivateProfileIntW(L"io4", L"tenkey_4", VK_NUMPAD4, filename);
|
||||
cfg->vk_tenkey_5 = GetPrivateProfileIntW(L"io4", L"tenkey_5", VK_NUMPAD5, filename);
|
||||
cfg->vk_tenkey_6 = GetPrivateProfileIntW(L"io4", L"tenkey_6", VK_NUMPAD6, filename);
|
||||
cfg->vk_tenkey_7 = GetPrivateProfileIntW(L"io4", L"tenkey_7", VK_NUMPAD7, filename);
|
||||
cfg->vk_tenkey_8 = GetPrivateProfileIntW(L"io4", L"tenkey_8", VK_NUMPAD8, filename);
|
||||
cfg->vk_tenkey_9 = GetPrivateProfileIntW(L"io4", L"tenkey_9", VK_NUMPAD9, filename);
|
||||
cfg->vk_tenkey_clear = GetPrivateProfileIntW(L"io4", L"tenkey_clear", VK_DECIMAL, filename);
|
||||
cfg->vk_tenkey_enter = GetPrivateProfileIntW(L"io4", L"tenkey_enter", VK_RETURN, filename);
|
||||
|
||||
cfg->vk_vol_down = GetPrivateProfileIntW(L"io4", L"vol_down", VK_SUBTRACT, filename);
|
||||
cfg->vk_vol_up = GetPrivateProfileIntW(L"io4", L"vol_up", VK_ADD, filename);
|
||||
|
||||
cfg->vk_terminal_decide = GetPrivateProfileIntW(L"io4", L"decide", 'A', filename);
|
||||
cfg->vk_terminal_cancel = GetPrivateProfileIntW(L"io4", L"cancel", 'S', filename);
|
||||
cfg->vk_terminal_up = GetPrivateProfileIntW(L"io4", L"up", VK_UP, filename);
|
||||
cfg->vk_terminal_right = GetPrivateProfileIntW(L"io4", L"right", VK_RIGHT, filename);
|
||||
cfg->vk_terminal_down = GetPrivateProfileIntW(L"io4", L"down", VK_DOWN, filename);
|
||||
cfg->vk_terminal_left = GetPrivateProfileIntW(L"io4", L"left", VK_LEFT, filename);
|
||||
cfg->vk_terminal_left_2 = GetPrivateProfileIntW(L"io4", L"left2", 'Q', filename);
|
||||
cfg->vk_terminal_right_2 = GetPrivateProfileIntW(L"io4", L"right2", 'W', filename);
|
||||
|
||||
cfg->x_down = GetPrivateProfileIntW(L"io4", L"trackball_left", VK_LEFT, filename);
|
||||
cfg->x_up = GetPrivateProfileIntW(L"io4", L"trackball_right", VK_RIGHT, filename);
|
||||
cfg->y_down = GetPrivateProfileIntW(L"io4", L"trackball_up", VK_UP, filename);
|
||||
cfg->y_up = GetPrivateProfileIntW(L"io4", L"trackball_down", VK_DOWN, filename);
|
||||
cfg->speed = GetPrivateProfileIntW(L"io4", L"speed_modifier", 1, filename);
|
||||
}
|
||||
|
||||
void ekt_io_config_load(
|
||||
struct ekt_io_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
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_sw1 = GetPrivateProfileIntW(L"io4", L"sw1", '4', filename);
|
||||
cfg->vk_sw2 = GetPrivateProfileIntW(L"io4", L"sw2", '5', filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"io4",
|
||||
L"mode",
|
||||
L"keyboard",
|
||||
cfg->mode,
|
||||
_countof(cfg->mode),
|
||||
filename);
|
||||
|
||||
ekt_kb_config_load(&cfg->kb, filename);
|
||||
}
|
61
games/ektio/config.h
Normal file
61
games/ektio/config.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct ekt_kb_config {
|
||||
uint8_t vk_menu;
|
||||
uint8_t vk_start;
|
||||
uint8_t vk_stratagem;
|
||||
uint8_t vk_stratagem_lock;
|
||||
uint8_t vk_hougu;
|
||||
|
||||
uint8_t vk_tenkey_0;
|
||||
uint8_t vk_tenkey_1;
|
||||
uint8_t vk_tenkey_2;
|
||||
uint8_t vk_tenkey_3;
|
||||
uint8_t vk_tenkey_4;
|
||||
uint8_t vk_tenkey_5;
|
||||
uint8_t vk_tenkey_6;
|
||||
uint8_t vk_tenkey_7;
|
||||
uint8_t vk_tenkey_8;
|
||||
uint8_t vk_tenkey_9;
|
||||
uint8_t vk_tenkey_clear;
|
||||
uint8_t vk_tenkey_enter;
|
||||
|
||||
uint8_t vk_vol_down;
|
||||
uint8_t vk_vol_up;
|
||||
|
||||
uint8_t vk_terminal_up;
|
||||
uint8_t vk_terminal_right;
|
||||
uint8_t vk_terminal_down;
|
||||
uint8_t vk_terminal_left;
|
||||
uint8_t vk_terminal_left_2;
|
||||
uint8_t vk_terminal_right_2;
|
||||
uint8_t vk_terminal_cancel;
|
||||
uint8_t vk_terminal_decide;
|
||||
|
||||
uint8_t x_down;
|
||||
uint8_t x_up;
|
||||
uint8_t y_down;
|
||||
uint8_t y_up;
|
||||
uint8_t speed;
|
||||
};
|
||||
|
||||
struct ekt_io_config {
|
||||
uint8_t vk_test;
|
||||
uint8_t vk_service;
|
||||
uint8_t vk_coin;
|
||||
uint8_t vk_sw1;
|
||||
uint8_t vk_sw2;
|
||||
|
||||
wchar_t mode[12];
|
||||
struct ekt_kb_config kb;
|
||||
};
|
||||
|
||||
void ekt_kb_config_load(struct ekt_kb_config *cfg, const wchar_t *filename);
|
||||
void ekt_io_config_load(
|
||||
struct ekt_io_config *cfg,
|
||||
const wchar_t *filename);
|
100
games/ektio/ektio.c
Normal file
100
games/ektio/ektio.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ektio/ektio.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "ektio/config.h"
|
||||
#include "util/dprintf.h"
|
||||
#include "util/env.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static uint8_t ekt_opbtn;
|
||||
static uint32_t ekt_gamebtn;
|
||||
static uint8_t ekt_stick_x;
|
||||
static uint8_t ekt_stick_y;
|
||||
static struct ekt_io_config ekt_io_cfg;
|
||||
static const struct ekt_io_backend* ekt_io_backend;
|
||||
static bool ekt_io_coin;
|
||||
|
||||
uint16_t ekt_io_get_api_version(void) {
|
||||
return 0x0100;
|
||||
}
|
||||
|
||||
HRESULT ekt_io_init(void) {
|
||||
ekt_io_config_load(&ekt_io_cfg, get_config_path());
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (wstr_ieq(ekt_io_cfg.mode, L"keyboard")) {
|
||||
hr = ekt_kb_init(&ekt_io_cfg.kb, &ekt_io_backend);
|
||||
} else {
|
||||
hr = E_INVALIDARG;
|
||||
dprintf("EKT IO: Invalid IO mode \"%S\", use keyboard\n",
|
||||
ekt_io_cfg.mode);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT ekt_io_poll(void) {
|
||||
assert(ekt_io_backend != NULL);
|
||||
|
||||
ekt_opbtn = 0;
|
||||
ekt_gamebtn = 0;
|
||||
ekt_stick_x = 0;
|
||||
ekt_stick_y = 0;
|
||||
|
||||
if (GetAsyncKeyState(ekt_io_cfg.vk_test) & 0x8000) {
|
||||
ekt_opbtn |= EKT_IO_OPBTN_TEST;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(ekt_io_cfg.vk_service) & 0x8000) {
|
||||
ekt_opbtn |= EKT_IO_OPBTN_SERVICE;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(ekt_io_cfg.vk_coin) & 0x8000) {
|
||||
if (!ekt_io_coin) {
|
||||
ekt_io_coin = true;
|
||||
ekt_opbtn |= EKT_IO_OPBTN_COIN;
|
||||
}
|
||||
} else {
|
||||
ekt_io_coin = false;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void ekt_io_get_opbtns(uint8_t* opbtn) {
|
||||
if (opbtn != NULL) {
|
||||
*opbtn = ekt_opbtn;
|
||||
}
|
||||
}
|
||||
|
||||
void ekt_io_get_gamebtns(uint32_t* btn) {
|
||||
assert(ekt_io_backend != NULL);
|
||||
assert(btn != NULL);
|
||||
|
||||
ekt_io_backend->get_gamebtns(btn);
|
||||
}
|
||||
|
||||
void ekt_io_get_trackball_position(uint8_t* stick_x, uint8_t* stick_y) {
|
||||
assert(ekt_io_backend != NULL);
|
||||
assert(stick_x != NULL);
|
||||
assert(stick_y != NULL);
|
||||
|
||||
ekt_io_backend->get_trackball(stick_x, stick_y);
|
||||
}
|
||||
|
||||
HRESULT ekt_io_led_init(void) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void ekt_io_led_set_colors(uint8_t board, uint8_t* rgb) {
|
||||
return;
|
||||
}
|
105
games/ektio/ektio.h
Normal file
105
games/ektio/ektio.h
Normal file
@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
EKT_IO_OPBTN_TEST = 0x01,
|
||||
EKT_IO_OPBTN_SERVICE = 0x02,
|
||||
EKT_IO_OPBTN_COIN = 0x04,
|
||||
EKT_IO_OPBTN_SW1 = 0x08,
|
||||
EKT_IO_OPBTN_SW2 = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
EKT_IO_GAMEBTN_MENU = 0x01,
|
||||
EKT_IO_GAMEBTN_START = 0x02,
|
||||
EKT_IO_GAMEBTN_STRATAGEM = 0x04,
|
||||
EKT_IO_GAMEBTN_STRATAGEM_LOCK = 0x08,
|
||||
EKT_IO_GAMEBTN_HOUGU = 0x10,
|
||||
EKT_IO_GAMEBTN_NUMPAD_0 = 0x100,
|
||||
EKT_IO_GAMEBTN_NUMPAD_1 = 0x200,
|
||||
EKT_IO_GAMEBTN_NUMPAD_2 = 0x400,
|
||||
EKT_IO_GAMEBTN_NUMPAD_3 = 0x800,
|
||||
EKT_IO_GAMEBTN_NUMPAD_4 = 0x1000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_5 = 0x2000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_6 = 0x4000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_7 = 0x8000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_8 = 0x10000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_9 = 0x20000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_CLEAR = 0x40000,
|
||||
EKT_IO_GAMEBTN_NUMPAD_ENTER = 0x80000,
|
||||
EKT_IO_GAMEBTN_VOL_UP = 0x100000,
|
||||
EKT_IO_GAMEBTN_VOL_DOWN = 0x200000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_LEFT = 0x400000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_UP = 0x800000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_RIGHT = 0x1000000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_DOWN = 0x2000000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_LEFT_2 = 0x4000000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_RIGHT_2 = 0x8000000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_DECIDE = 0x10000000,
|
||||
EKT_IO_GAMEBTN_TERMINAL_CANCEL = 0x20000000,
|
||||
};
|
||||
|
||||
/* Get the version of the Eiketsu Taisen 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 ekt_io_get_api_version(void);
|
||||
|
||||
/* Initialize the IO DLL. This is the second function that will be called on
|
||||
your DLL, after ekt_io_get_api_version.
|
||||
|
||||
All subsequent calls to this API may originate from arbitrary threads.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
HRESULT ekt_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 ekt_io_poll(void);
|
||||
|
||||
/* Get the state of the cabinet's operator buttons as of the last poll. See
|
||||
EKT_IO_OPBTN enum above: this contains bit mask definitions for button
|
||||
states returned in *opbtn. All buttons are active-high.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void ekt_io_get_opbtns(uint8_t *opbtn);
|
||||
|
||||
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
|
||||
EKT_IO_GAMEBTN enum above: this contains bit mask definitions for button
|
||||
states returned in *gamebtn. All buttons are active-high.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void ekt_io_get_gamebtns(uint32_t *gamebtn);
|
||||
|
||||
/* Get the position of the trackball as of the last poll.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void ekt_io_get_trackball_position(uint8_t *stick_x, uint8_t *stick_y);
|
||||
|
||||
/* Initialize LED emulation. This function will be called before any
|
||||
other ekt_io_led_*() function calls.
|
||||
|
||||
All subsequent calls may originate from arbitrary threads and some may
|
||||
overlap with each other. Ensuring synchronization inside your IO DLL is
|
||||
your responsibility. */
|
||||
|
||||
HRESULT ekt_io_led_init(void);
|
||||
|
||||
/* Update the RGB LEDs.
|
||||
|
||||
Exact layout is TBD. */
|
||||
|
||||
void ekt_io_led_set_colors(uint8_t board, uint8_t *rgb);
|
172
games/ektio/keyboard.c
Normal file
172
games/ektio/keyboard.c
Normal file
@ -0,0 +1,172 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ektio/backend.h"
|
||||
#include "ektio/config.h"
|
||||
#include "ektio/ektio.h"
|
||||
#include "ektio/keyboard.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void ekt_kb_get_gamebtns(uint32_t* gamebtn_out);
|
||||
static void ekt_kb_get_trackball(uint8_t* x, uint8_t* y);
|
||||
|
||||
static const struct ekt_io_backend ekt_kb_backend = {
|
||||
.get_gamebtns = ekt_kb_get_gamebtns,
|
||||
.get_trackball = ekt_kb_get_trackball
|
||||
};
|
||||
|
||||
static uint8_t current_x;
|
||||
static uint8_t current_y;
|
||||
|
||||
static struct ekt_kb_config config;
|
||||
|
||||
HRESULT ekt_kb_init(const struct ekt_kb_config* cfg, const struct ekt_io_backend** backend) {
|
||||
assert(cfg != NULL);
|
||||
assert(backend != NULL);
|
||||
|
||||
dprintf("Keyboard: Using keyboard input\n");
|
||||
*backend = &ekt_kb_backend;
|
||||
config = *cfg;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void ekt_kb_get_gamebtns(uint32_t* gamebtn_out) {
|
||||
assert(gamebtn_out != NULL);
|
||||
|
||||
uint8_t gamebtn = 0;
|
||||
|
||||
if (GetAsyncKeyState(config.vk_hougu) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_HOUGU;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_menu) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_MENU;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_start) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_START;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_stratagem) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_STRATAGEM;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_stratagem_lock) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_STRATAGEM_LOCK;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_0) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_0;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_1) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_1;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_2) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_2;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_3) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_3;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_4) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_4;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_5) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_5;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_6) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_6;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_7) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_7;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_8) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_8;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_9) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_9;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_clear) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_CLEAR;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_enter) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_NUMPAD_ENTER;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_vol_down) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_VOL_DOWN;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_vol_up) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_VOL_UP;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_cancel) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_CANCEL;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_decide) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_DECIDE;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_up) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_UP;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_right) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_RIGHT;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_down) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_DOWN;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_left) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_LEFT;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_left_2) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_LEFT_2;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_right_2) & 0x8000) {
|
||||
gamebtn |= EKT_IO_GAMEBTN_TERMINAL_RIGHT_2;
|
||||
}
|
||||
|
||||
*gamebtn_out = gamebtn;
|
||||
}
|
||||
|
||||
static void ekt_kb_get_trackball(uint8_t* x, uint8_t* y) {
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
|
||||
if (GetAsyncKeyState(config.x_down) & 0x8000) {
|
||||
current_x -= config.speed;
|
||||
} else if (GetAsyncKeyState(config.x_up) & 0x8000) {
|
||||
current_x += config.speed;
|
||||
}
|
||||
if (GetAsyncKeyState(config.y_down) & 0x8000) {
|
||||
current_y -= config.speed;
|
||||
} else if (GetAsyncKeyState(config.y_up) & 0x8000) {
|
||||
current_y += config.speed;
|
||||
}
|
||||
|
||||
*x = current_x;
|
||||
*y = current_y;
|
||||
}
|
8
games/ektio/keyboard.h
Normal file
8
games/ektio/keyboard.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "ektio/backend.h"
|
||||
#include "ektio/config.h"
|
||||
|
||||
HRESULT ekt_kb_init(const struct ekt_kb_config *cfg, const struct ekt_io_backend **backend);
|
18
games/ektio/meson.build
Normal file
18
games/ektio/meson.build
Normal file
@ -0,0 +1,18 @@
|
||||
ektio_lib = static_library(
|
||||
'ektio',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
dependencies : [
|
||||
xinput_lib,
|
||||
],
|
||||
sources : [
|
||||
'ektio.c',
|
||||
'ektio.h',
|
||||
'config.c',
|
||||
'config.h',
|
||||
'backend.h',
|
||||
'keyboard.c',
|
||||
'keyboard.h',
|
||||
],
|
||||
)
|
@ -125,6 +125,7 @@ subdir('games/tokyoio')
|
||||
subdir('games/fgoio')
|
||||
subdir('games/kemonoio')
|
||||
subdir('games/apm3io')
|
||||
subdir('games/ektio')
|
||||
|
||||
subdir('games/chunihook')
|
||||
subdir('games/divahook')
|
||||
@ -142,3 +143,4 @@ subdir('games/tokyohook')
|
||||
subdir('games/fgohook')
|
||||
subdir('games/kemonohook')
|
||||
subdir('games/apm3hook')
|
||||
subdir('games/ekthook')
|
||||
|
Reference in New Issue
Block a user