From fdd9c2fbc82f101e37143850d0f7ec4ce4f236cc Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Tue, 2 Sep 2025 13:16:35 +0200 Subject: [PATCH] ekt: cleanup and fixes --- dist/ekt/launch_satellite.bat | 10 +- dist/ekt/launch_terminal.bat | 6 +- dist/ekt/segatools_satellite.ini | 60 ++--- dist/ekt/segatools_terminal.ini | 57 ++--- games/ekthook/config.c | 98 ++++++-- games/ekthook/config.h | 20 +- games/ekthook/dllmain.c | 113 ++++----- games/ekthook/y3.c | 383 ++++++++++++++++++++----------- games/ekthook/y3.h | 68 +++--- 9 files changed, 480 insertions(+), 335 deletions(-) diff --git a/dist/ekt/launch_satellite.bat b/dist/ekt/launch_satellite.bat index 3fd68fc..a90b0db 100644 --- a/dist/ekt/launch_satellite.bat +++ b/dist/ekt/launch_satellite.bat @@ -3,8 +3,14 @@ set SEGATOOLS_CONFIG_PATH=.\segatools_satellite.ini pushd %~dp0 -start /min "AM Daemon" inject -d -k ekthook.dll PackageBase\amdaemon.exe -c PackageBase\config_sate.json config_hook.json -inject -d -k ekthook.dll exe\ekt.exe -logfile game.log -screen-fullscreen 0 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes +start "AM Daemon" /min inject -d -k ekthook.dll ..\PackageBase\amdaemon.exe -c ..\PackageBase\config_sate.json config_hook.json + +REM AmCapture +REM pushd ..\PackageBase\am_capture +REM start /min "" %AMCAPTURE_EXE_NAME% >nul 2>&1 +REM popd + +inject -d -k ekthook.dll ekt.exe -logfile satellite.log -screen-fullscreen 1 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes taskkill /f /im amdaemon.exe > nul 2>&1 diff --git a/dist/ekt/launch_terminal.bat b/dist/ekt/launch_terminal.bat index 1c93efb..a49a71c 100644 --- a/dist/ekt/launch_terminal.bat +++ b/dist/ekt/launch_terminal.bat @@ -1,10 +1,10 @@ @echo off -set SEGATOOLS_CONFIG_PATH=..\segatools_terminal.ini +set SEGATOOLS_CONFIG_PATH=.\segatools_terminal.ini pushd %~dp0 -start /min "AM Daemon" inject -d -k ekthook.dll PackageBase\amdaemon.exe -c PackageBase\config_terminal.json config_hook.json -inject -d -k ekthook.dll exe\ekt.exe -logfile game.log -screen-fullscreen 0 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes +start "AM Daemon" /min inject -d -k ekthook.dll ..\PackageBase\amdaemon.exe -c ..\PackageBase\config_terminal.json config_hook.json +inject -d -k ekthook.dll ekt.exe -terminal -logfile terminal.log -screen-fullscreen 1 -screen-width 1920 -screen-height 1080 -screen-quality Ultra -silent-crashes taskkill /f /im amdaemon.exe > nul 2>&1 diff --git a/dist/ekt/segatools_satellite.ini b/dist/ekt/segatools_satellite.ini index b179ceb..c8b2cf8 100644 --- a/dist/ekt/segatools_satellite.ini +++ b/dist/ekt/segatools_satellite.ini @@ -28,10 +28,6 @@ aimePath=DEVICE\aime.txt ; 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 ; ----------------------------------------------------------------------------- @@ -46,10 +42,6 @@ default=127.0.0.1 ; 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 @@ -68,40 +60,35 @@ 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 +; 1 = Terminal (TM) +; 2 = Satellite (ST) +platformId=ACA2 [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 +; this to 0 on exactly one machine and set this to 1 on all others. +dipsw1=0 ; ----------------------------------------------------------------------------- -; Misc. hook settings +; Misc. hooks 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= +; ----------------------------------------------------------------------------- +; LED settings +; ----------------------------------------------------------------------------- + +[led15093] +; Enable the 837-15093-06 board emulation. +enable=1 + ; ----------------------------------------------------------------------------- ; Custom IO settings ; ----------------------------------------------------------------------------- @@ -112,15 +99,15 @@ targetAssembly= 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. +; To use a custom Eiketsu Taisen IO DLL enter its path here. +; Leave empty if you want to use Segatools built-in keyboard/gamepad input. path= ; ----------------------------------------------------------------------------- ; Input settings ; ----------------------------------------------------------------------------- -; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal +; Keyboard bindings are 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 @@ -129,12 +116,13 @@ path= ; 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 +; Test button virtual-key code. Default is the F1 key. +test=0x70 +; Service button virtual-key code. Default is the F2 key. +service=0x71 +; Keyboard button to increment coin counter. Default is the F3 key. +coin=0x72 + ; SW1. Default is the 4 key. sw1=0x34 ; SW2. Default is the 5 key. diff --git a/dist/ekt/segatools_terminal.ini b/dist/ekt/segatools_terminal.ini index 6fe2af9..3873291 100644 --- a/dist/ekt/segatools_terminal.ini +++ b/dist/ekt/segatools_terminal.ini @@ -28,10 +28,6 @@ aimePath=DEVICE\aime.txt ; 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 ; ----------------------------------------------------------------------------- @@ -46,10 +42,6 @@ default=127.0.0.1 ; 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 @@ -68,30 +60,20 @@ 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 +; 1 = Terminal (TM) +; 2 = Satellite (ST) +platformId=ACA1 [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 +; this to 0 on exactly one machine and set this to 1 on all others. +dipsw1=0 ; ----------------------------------------------------------------------------- -; Misc. hook settings +; Misc. hooks settings ; ----------------------------------------------------------------------------- [unity] @@ -102,6 +84,14 @@ enable=1 ; modding frameworks such as BepInEx. targetAssembly= +; ----------------------------------------------------------------------------- +; LED settings +; ----------------------------------------------------------------------------- + +[led15093] +; Enable the 837-15093-06 board emulation. +enable=1 + ; ----------------------------------------------------------------------------- ; Custom IO settings ; ----------------------------------------------------------------------------- @@ -112,15 +102,15 @@ targetAssembly= 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. +; To use a custom Eiketsu Taisen IO DLL enter its path here. +; Leave empty if you want to use Segatools built-in keyboard/gamepad input. path= ; ----------------------------------------------------------------------------- ; Input settings ; ----------------------------------------------------------------------------- -; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal +; Keyboard bindings are 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 @@ -129,12 +119,13 @@ path= ; 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 +; Test button virtual-key code. Default is the F1 key. +test=0x70 +; Service button virtual-key code. Default is the F2 key. +service=0x71 +; Keyboard button to increment coin counter. Default is the F3 key. +coin=0x72 + ; SW1. Default is the 4 key. sw1=0x34 ; SW2. Default is the 5 key. diff --git a/games/ekthook/config.c b/games/ekthook/config.c index a6a7953..1b1f0af 100644 --- a/games/ekthook/config.c +++ b/games/ekthook/config.c @@ -1,7 +1,5 @@ #include - -#include "amex/amex.h" -#include "amex/config.h" +#include #include "board/config.h" @@ -89,6 +87,88 @@ void ekt_dll_config_load( filename); } +void y3_config_load( + struct y3_config *cfg, + const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + wchar_t tmpstr[5]; + + memset(cfg->firm_name_field, ' ', sizeof(cfg->firm_name_field) - 1); + cfg->firm_name_field[sizeof(cfg->firm_name_field) - 1] = '\0'; + + memset(cfg->firm_name_printer, ' ', sizeof(cfg->firm_name_printer) - 1); + cfg->firm_name_printer[sizeof(cfg->firm_name_printer) - 1] = '\0'; + + memset(cfg->target_code_field, ' ', sizeof(cfg->target_code_field) - 1); + cfg->target_code_field[sizeof(cfg->target_code_field) - 1] = '\0'; + + memset(cfg->target_code_printer, ' ', sizeof(cfg->target_code_printer) - 1); + cfg->target_code_printer[sizeof(cfg->target_code_printer) - 1] = '\0'; + + + 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); + + cfg->enable = GetPrivateProfileIntW(L"flatPanelReader", L"enable", 1, filename); + + cfg->dll_version = (float)GetPrivateProfileIntW( + L"flatPanelReader", + L"dllVersion", + 1, + filename); + + cfg->firm_version = (float)GetPrivateProfileIntW( + L"flatPanelReader", + L"firmVersion", + 1, + filename); + + GetPrivateProfileStringW( + L"flatPanelReader", + L"firmNameField", + L"SFPR", + tmpstr, + _countof(tmpstr), + filename); + + wcstombs(cfg->firm_name_field, tmpstr, sizeof(cfg->firm_name_field) - 1); + + GetPrivateProfileStringW( + L"flatPanelReader", + L"firmNamePrinter", + L"SPRT", + tmpstr, + _countof(tmpstr), + filename); + + wcstombs(cfg->firm_name_printer, tmpstr, sizeof(cfg->firm_name_printer) - 1); + + GetPrivateProfileStringW( + L"flatPanelReader", + L"targetCodeField", + L"SFR0", + tmpstr, + _countof(tmpstr), + filename); + + wcstombs(cfg->target_code_field, tmpstr, sizeof(cfg->target_code_field) - 1); + + GetPrivateProfileStringW( + L"flatPanelReader", + L"targetCodePrinter", + L"SPT0", + tmpstr, + _countof(tmpstr), + filename); + + wcstombs(cfg->target_code_printer, tmpstr, sizeof(cfg->target_code_printer) - 1); +} + void ekt_hook_config_load( struct ekt_hook_config *cfg, const wchar_t *filename) @@ -102,16 +182,6 @@ void ekt_hook_config_load( dvd_config_load(&cfg->dvd, filename); led15093_config_load(&cfg->led15093, filename); y3_config_load(&cfg->y3, filename); + unity_config_load(&cfg->unity, 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); -} diff --git a/games/ekthook/config.h b/games/ekthook/config.h index e73c015..a865dfb 100644 --- a/games/ekthook/config.h +++ b/games/ekthook/config.h @@ -2,9 +2,6 @@ #include -#include "ekt-dll.h" -#include "amex/amex.h" - #include "board/sg-reader.h" #include "board/config.h" #include "board/led15093.h" @@ -12,14 +9,11 @@ #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; -}; +#include "ekthook/ekt-dll.h" +#include "ekthook/y3.h" struct ekt_hook_config { struct platform_config platform; @@ -32,10 +26,10 @@ struct ekt_hook_config { struct unity_config unity; }; +void ekt_dll_config_load( + struct ekt_dll_config *cfg, + const wchar_t *filename); + 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); diff --git a/games/ekthook/dllmain.c b/games/ekthook/dllmain.c index f677545..91860e0 100644 --- a/games/ekthook/dllmain.c +++ b/games/ekthook/dllmain.c @@ -1,106 +1,77 @@ +/* + "Eiketsu Taisen" (ekt) hook + + Devices + + USB: 837-15257-01 "Type 4" I/O Board + + [Satellite] + + USB: 630-00011 G-Printec CX-7000 Printer + COM2: 837-15093-06 LED Controller Board + COM3: 837-15396 "Gen 3" Aime Reader + COM4: 601-13160-01 "Flat Panel Reader" Y3CR BD SIE F720MM Board + + [Terminal] + + COM1: 837-15396 "Gen 3" Aime Reader + COM3: 837-15093-06 LED Controller Board +*/ + #include +#include #include "ekt-dll.h" #include "board/sg-reader.h" #include "board/led15093.h" #include "hook/process.h" +#include "hook/iohook.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 - * - * SATELLITE: Model Type 1 - * - * COM2: LED - * COM3: AIME - * 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 */ + + dvd_hook_init(&ekt_hook_cfg.dvd, ekt_hook_mod); serial_hook_init(); + /* Hook external DLL APIs */ + + y3_hook_init(&ekt_hook_cfg.y3, ekt_hook_mod); + /* Initialize emulation hooks */ - // Terminal = AAV1, Satellite = AAV2 hr = platform_hook_init( &ekt_hook_cfg.platform, "SDGY", - "AAV1", + "ACA1", ekt_hook_mod); if (FAILED(hr)) { @@ -110,18 +81,22 @@ static DWORD CALLBACK ekt_pre_startup(void) /* Initialize Terminal/Satellite hooks */ if (strncmp(ekt_hook_cfg.platform.nusec.platform_id, "ACA1", 4) == 0) { // Terminal - is_terminal = false; - dprintf("Mode: Satellite\n"); + is_terminal = true; } else if (strncmp(ekt_hook_cfg.platform.nusec.platform_id, "ACA2", 4) == 0) { // Satellite - is_terminal = true; - dprintf("Mode: Terminal\n"); + is_terminal = false; } else { // Unknown dprintf("Unknown platform ID: %s\n", ekt_hook_cfg.platform.nusec.platform_id); goto fail; } + // LED: terminal uses COM 3 and satellite use COM 2 + unsigned int led_port_no[2] = {is_terminal ? 3 : 2, 0}; + + // AIME: terminal uses COM 1 and satellite use COM 3 + unsigned int aime_port_no = is_terminal ? 1 : 3; + if (FAILED(hr)) { goto fail; } @@ -138,7 +113,6 @@ static DWORD CALLBACK ekt_pre_startup(void) 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); @@ -146,18 +120,19 @@ static DWORD CALLBACK ekt_pre_startup(void) goto fail; } - - hr = sg_reader_hook_init(&ekt_hook_cfg.aime, is_terminal ? 1 : 3, ekt_hook_cfg.aime.gen, ekt_hook_mod); + hr = sg_reader_hook_init(&ekt_hook_cfg.aime, aime_port_no, 3, + ekt_hook_mod); if (FAILED(hr)) { goto fail; } - dvd_hook_init(&ekt_hook_cfg.dvd, ekt_hook_mod); + /* Initialize Unity native plugin DLL hooks - unity_hook_init(&ekt_hook_cfg.unity, ekt_hook_mod, unity_hook_callback); + There seems to be an issue with other DLL hooks if `LoadLibraryW` is + hooked earlier in the `ekthook` initialization. */ - y3_hook_init(&ekt_hook_cfg.y3, ekt_hook_mod); + unity_hook_init(&ekt_hook_cfg.unity, ekt_hook_mod, NULL); /* Initialize debug helpers */ diff --git a/games/ekthook/y3.c b/games/ekthook/y3.c index 77f61ee..b540c5c 100644 --- a/games/ekthook/y3.c +++ b/games/ekthook/y3.c @@ -1,19 +1,16 @@ #include -#include #include #include -#include -#include +#include +#include -#include "hook/table.h" -#include "hooklib/dll.h" -#include "util/dprintf.h" - -#include "ekthook/config.h" #include "ekthook/y3.h" -#include +#include "hook/table.h" +#include "hook/procaddr.h" + +#include "util/dprintf.h" #define CALL __cdecl @@ -43,21 +40,23 @@ 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); +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_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); +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); + +uint32_t convert_string_to_uint(const char* firmName); static const struct hook_symbol Y3_hooks[] = { { @@ -265,8 +264,7 @@ 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){ +void y3_hook_init(const struct y3_config* cfg, HINSTANCE self) { assert(cfg != NULL); if (!cfg->enable) { @@ -275,117 +273,196 @@ void y3_hook_init(const struct y3_config *cfg, HINSTANCE self){ 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"); - } + y3_insert_hooks(NULL); memset(card_data, 0, sizeof(card_data)); - dprintf("Y3: enabled\n"); + dprintf("Y3: hook enabled\n"); } -CALL float API_DLLVersion(){ +void y3_insert_hooks(HMODULE target) { + hook_table_apply( + target, + "Y3CodeReaderNE.dll", + Y3_hooks, + _countof(Y3_hooks)); + + proc_addr_table_push( + target, + "Y3CodeReaderNE.dll", + Y3_hooks, + _countof(Y3_hooks)); +} + +CALL float API_DLLVersion() { dprintf("Y3: %s\n", __func__); return 1; } -CALL uint32_t API_GetLastError(int* hDevice){ + +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){ + +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"); + 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){ + +CALL int* API_Connect(char* szPortName) { dprintf("Y3: %s(%s)\n", __func__, szPortName); -if ((GetAsyncKeyState(0x11) & 0x8000) && (GetAsyncKeyState(0x42) & 0x8000)) { + + 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); + strncpy(number, szPortName + 3, 2); return (int*)(uintptr_t)atoi(number); } } -CALL int API_Close(int* hDevice){ + +CALL int API_Close(int* hDevice) { dprintf("Y3: %s(%p)\n", __func__, hDevice); return 0; } -CALL int API_Start(int* hDevice){ + +CALL int API_Start(int* hDevice) { dprintf("Y3: %s(%p)\n", __func__, hDevice); return 0; } -CALL int API_Stop(int* hDevice){ + +CALL int API_Stop(int* hDevice) { dprintf("Y3: %s(%p)\n", __func__, hDevice); return 0; } -CALL float API_GetFirmVersion(int* hDevice){ + +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){ +CALL uint32_t API_GetFirmName(int* hDevice) { + uint32_t result = 0; + dprintf("Y3: %s(%p)\n", __func__, hDevice); + + if (hDevice == Y3_COM_FIELD) { + result = convert_string_to_uint(y3_config.firm_name_field); + dprintf("This Y3 device is a FIELD: %s\n", y3_config.firm_name_field); + } else if (hDevice == Y3_COM_PRINT) { + result = convert_string_to_uint(y3_config.firm_name_printer); + dprintf("This Y3 device is PRINTER: %s\n", y3_config.firm_name_printer); + // DebugBreak(); + } else { + dprintf("This Y3 device is UNKNOWN\n"); + } + + return result; +} + +CALL uint32_t API_GetTargetCode(int* hDevice) { + uint32_t result = 1162760014; + dprintf("Y3: %s(%p)\n", __func__, hDevice); + + if (hDevice == Y3_COM_FIELD) { + result = convert_string_to_uint(y3_config.target_code_field); + dprintf("This Y3 device is FIELD: %s\n", y3_config.target_code_field); + } else if (hDevice == Y3_COM_PRINT) { + result = convert_string_to_uint(y3_config.target_code_printer); + dprintf("This Y3 device is PRINTER: %s\n", y3_config.target_code_printer); + // DebugBreak(); + } else { + dprintf("This Y3 device is UNKNOWN\n"); + } + + return result; +} + +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_FIELD) { + memset(pCardInfo, 0, sizeof(struct CardInfo) * numCards); + + const float paddingX = 86.0f; + const float paddingY = 54.0f; + + // Dimensions of the flat panel + const float panelHeight = 1232.0f; + const float panelWidth = 1160.0f; + + // Number of cards in each row and column + const int numRows = 4; + const int numCols = 4; + int activeCards = numRows * numCols; + + if (numCards < activeCards) { + activeCards = numCards; + } + + // Calculate spacing between cards + const float cardWidth = (panelWidth - paddingY * 2) / (numCols - 1); + const float cardHeight = (panelHeight - paddingX * 2) / (numRows - 1); + + // Create example card info + for (int i = 0; i < activeCards; i++) { + int row = i / numCols; + int col = i % numCols; + + pCardInfo[i].fX = paddingX + (col * cardHeight); + pCardInfo[i].fY = paddingY + (row * cardWidth); + pCardInfo[i].fAngle = 0.0f; + pCardInfo[i].eCardType = TYPE0; + pCardInfo[i].eCardStatus = MARKER; + pCardInfo[i].uID = 1000 + i; + pCardInfo[i].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 activeCards; + } else if (hDevice == Y3_COM_PRINT) { pCardInfo[0].fX = 0; pCardInfo[0].fY = 0; pCardInfo[0].fAngle = 0; @@ -396,115 +473,147 @@ CALL int API_GetCardInfo(int* hDevice, int numCards, struct CardInfo* pCardInfo) pCardInfo[0].ubChar0.Data = 0; pCardInfo[0].ubChar1.Data = 0x4000; pCardInfo[0].ubChar2.Data = 0; - pCardInfo[0].ubChar3.Data = 0x0; // 40 + 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){ + +CALL int API_GetCardInfoCharSize() { dprintf("Y3: %s\n", __func__); return 0; } -signed int CALL API_SetDevice(int a1, int a2){ +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; } -signed int CALL API_SetCommand(int a1, int a2, int a3, int *a4){ +CALL uint32_t API_GetMemCounter(int* hDevice) { dprintf("Y3: %s\n", __func__); return 0; } -signed int CALL API_SetSysControl(int a1, int a2, int *a3){ + +CALL int API_SetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam) { dprintf("Y3: %s\n", __func__); return 0; } -signed int CALL API_GetSysControl(int a1, int a2, int *a3){ + +CALL int API_GetParameter(int* hDevice, uint32_t uParam, uint32_t* pParam) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_TestReset(int a1){ + +signed int CALL API_SetDevice(int a1, int a2) { dprintf("Y3: %s\n", __func__); return 0; } -signed int API_DebugReset(int a1, ...){ + +signed int CALL API_SetCommand(int a1, int a2, int a3, int* a4) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_GetBoardType(int a1){ + +signed int CALL API_SetSysControl(int a1, int a2, int* a3) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_GetCardDataSize(int a1){ + +signed int CALL API_GetSysControl(int a1, int a2, int* a3) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_GetFirmDate(int a1){ + +int CALL API_TestReset(int a1) { dprintf("Y3: %s\n", __func__); return 0; } -int API_SystemCommand(int a1, char a2, ...){ + +signed int API_DebugReset(int a1, ...) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_CalcCheckSum(DWORD *a1, int a2, int a3){ + +int CALL API_GetBoardType(int a1) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_GetCheckSumResult(int a1){ + +int CALL API_GetCardDataSize(int a1) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_BlockRead(int a1, int a2, int a3, SIZE_T dwBytes){ + +int CALL API_GetFirmDate(int a1) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_GetBlockReadResult(int a1, void *a2){ + +int API_SystemCommand(int a1, char a2, ...) { dprintf("Y3: %s\n", __func__); return 0; } -int CALL API_BlockWrite(int a1, int a2, int a3, SIZE_T dwBytes, void *a5){ + +int CALL API_CalcCheckSum(DWORD* a1, int a2, int a3) { dprintf("Y3: %s\n", __func__); return 0; } -signed int CALL API_GetDebugParam(int a1, int a2, DWORD *a3){ + +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; +} + +uint32_t convert_string_to_uint(const char* firmName) { + uint32_t result = 0; + + // Iterate over each character in the string and construct the uint32_t + for (int i = 0; i < 4; i++) { + result |= ((uint32_t)firmName[i] << (i * 8)); + } + + return result; +} diff --git a/games/ekthook/y3.h b/games/ekthook/y3.h index 73d2b66..b250d01 100644 --- a/games/ekthook/y3.h +++ b/games/ekthook/y3.h @@ -1,3 +1,8 @@ +#include +#include + +#pragma pack(push, 1) + enum Y3WebsocketProtocol { Y3_WS_PROTO_ERROR = 0, Y3_WS_PROTO_CARD_DATA = 2, @@ -9,12 +14,30 @@ struct CardByteData { unsigned int Data; }; +enum CardType { + TYPE0 = 0, + TYPE1, + TYPE2, + TYPE3, + TYPE4, + TYPE5, + TYPE6, + TYPE7 = 7 +}; + +enum CardStatus { + INVALID = 0, + VALID = 1, + INFERENCE = 2, + MARKER = 3 +}; + struct CardInfo { float fX; // 0x00|0 float fY; // 0x04|4 float fAngle; // 0x08|8 - int eCardType; // 0x0C|12 - int eCardStatus; // 0x10|16 + enum CardType eCardType; // 0x0C|12 + enum CardStatus eCardStatus; // 0x10|16 unsigned int uID; // 0x14|20 int nNumChars; // 0x18|24 struct CardByteData ubChar0; // 0x1C|28 @@ -25,33 +48,22 @@ struct CardInfo { 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 -}; +#pragma pack(pop) -enum Status { - INVALID = 0, - // Token: 0x0400008E RID: 142 - VALID = 1, - // Token: 0x0400008F RID: 143 - INFERENCE = 2, - // Token: 0x04000090 RID: 144 - MARKER = 3 +struct y3_config { + bool enable; + uint8_t ws_enable; + uint16_t ws_port; + uint32_t ws_timeout; + + float dll_version; + float firm_version; + char firm_name_field[5]; + char firm_name_printer[5]; + char target_code_field[5]; + char target_code_printer[5]; }; void y3_hook_init(const struct y3_config *cfg, HINSTANCE self); + +void y3_insert_hooks(HMODULE target);