diff --git a/board/config.c b/board/config.c index 191425a..9d015e9 100644 --- a/board/config.c +++ b/board/config.c @@ -30,6 +30,7 @@ void aime_config_load(struct aime_config *cfg, const wchar_t *filename) aime_dll_config_load(&cfg->dll, filename); cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename); + cfg->high_baudrate = GetPrivateProfileIntW(L"aime", L"highbaud", 1, filename); } void io4_config_load(struct io4_config *cfg, const wchar_t *filename) diff --git a/board/sg-reader.c b/board/sg-reader.c index dbf0392..e8fbfba 100644 --- a/board/sg-reader.c +++ b/board/sg-reader.c @@ -70,6 +70,10 @@ HRESULT sg_reader_hook_init( InitializeCriticalSection(&sg_reader_lock); + if (!cfg->high_baudrate) { + sg_reader_uart.baud.BaudRate = 38400; + } + uart_init(&sg_reader_uart, port_no); sg_reader_uart.written.bytes = sg_reader_written_bytes; sg_reader_uart.written.nbytes = sizeof(sg_reader_written_bytes); diff --git a/board/sg-reader.h b/board/sg-reader.h index 673a8bd..b9f19c5 100644 --- a/board/sg-reader.h +++ b/board/sg-reader.h @@ -9,6 +9,7 @@ struct aime_config { struct aime_dll_config dll; bool enable; + bool high_baudrate; }; HRESULT sg_reader_hook_init( diff --git a/cmhook/dllmain.c b/cmhook/dllmain.c index 5d78ace..9fd12cd 100644 --- a/cmhook/dllmain.c +++ b/cmhook/dllmain.c @@ -89,7 +89,7 @@ static DWORD CALLBACK cm_pre_startup(void) spike_hook_init(L".\\segatools.ini"); - dprintf("--- End cm_pre_startup ---\n"); + dprintf("--- End cm_pre_startup ---\n"); /* Jump to EXE start address */ diff --git a/dist/chusan/segatools.ini b/dist/chusan/segatools.ini index 196766f..a2189f9 100644 --- a/dist/chusan/segatools.ini +++ b/dist/chusan/segatools.ini @@ -36,6 +36,18 @@ enable=1 ; that subnet must start with 192.168. subnet=192.168.100.0 +[gpio] +; ALLS DIP switches. +enable=1 + +; 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 +; Monitor type: 0 = 120FPS, 1 = 60FPS +dipsw2=1 +; Aime reader hardware type: 0 = SP, 1 = CVT +dipsw3=1 + [gfx] ; Force the game to run windowed. windowed=1 diff --git a/dist/chusan/start.bat b/dist/chusan/start.bat index dbd1a8b..9a91cd2 100644 --- a/dist/chusan/start.bat +++ b/dist/chusan/start.bat @@ -2,8 +2,8 @@ pushd %~dp0 -start /min inject_x64.exe -d -k chusanhook_x64.dll amdaemon.exe -f -c config_common.json config_server.json config_sp.json -inject_x86.exe -d -k chusanhook_x86.dll chusanApp.exe +start /min inject_x64 -d -k chusanhook_x64.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json config_cvt.json config_sp.json +inject_x86 -d -k chusanhook_x86.dll chusanApp.exe taskkill /f /im amdaemon.exe > nul 2>&1 echo. diff --git a/dist/cm/segatools.ini b/dist/cm/segatools.ini index f2b4ca3..0097e7e 100644 --- a/dist/cm/segatools.ini +++ b/dist/cm/segatools.ini @@ -8,11 +8,10 @@ option= ; NOTE: This has nothing to do with Windows %APPDATA%. appdata= - [aime] ; Enable aime reader emulation. enable=1 -aimePath=C:\SEGA\DEVICE\aime.txt +aimePath=DEVICE\aime.txt felicaGen=0 [dns] @@ -32,6 +31,18 @@ enable=1 ; that subnet must start with 192.168. subnet=192.168.100.0 +[gpio] +; ALLS DIP switches. +enable=1 + +; 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 + +[touch] +; Enable/Disable WinTouch emulation +enable=0 + ; ----------------------------------------------------------------------------- ; Input settings ; ----------------------------------------------------------------------------- @@ -50,4 +61,4 @@ 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 \ No newline at end of file +coin=0x33 diff --git a/dist/cm/start.bat b/dist/cm/start.bat index b51c839..d4e6b66 100644 --- a/dist/cm/start.bat +++ b/dist/cm/start.bat @@ -2,8 +2,8 @@ pushd %~dp0 -start /min inject -d -k cmhook.dll amdaemon.exe -f -c config_server.json config_common.json -inject.exe -d -k cmhook.dll CardMaker.exe -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920 +start /min inject -d -k cmhook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json +inject -d -k cmhook.dll CardMaker.exe -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920 taskkill /f /im amdaemon.exe > nul 2>&1 diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini index 8676568..a86bee4 100644 --- a/dist/mai2/segatools.ini +++ b/dist/mai2/segatools.ini @@ -15,7 +15,7 @@ enable=1 [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= +default=127.0.0.1 [netenv] ; Simulate an ideal LAN environment. This may interfere with head-to-head play. @@ -29,6 +29,14 @@ enable=1 ; that subnet must start with 192.168. subnet=192.168.100.0 +[gpio] +; ALLS DIP switches. +enable=1 + +; 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 + ; ----------------------------------------------------------------------------- ; Input settings ; ----------------------------------------------------------------------------- diff --git a/dist/mu3/segatools.ini b/dist/mu3/segatools.ini index ef6df83..9c8f46f 100644 --- a/dist/mu3/segatools.ini +++ b/dist/mu3/segatools.ini @@ -1,25 +1,24 @@ [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= -option= + +[aime] +; Controls emulation of the Aime card reader assembly. +enable=1 +aimePath=DEVICE\aime.txt +felicaGen=0 [dns] ; Insert the hostname or IP address of the server you wish to use here. ; Note that 127.0.0.1, localhost etc are specifically rejected. default=127.0.0.1 -[ds] -; Region code on the emulated AMEX board DS EEPROM. -; 1: Japan -; 4: Export (some UI elements in English) -; -; NOTE: Changing this setting causes a factory reset. -region=1 - [netenv] ; Simulate an ideal LAN environment. This may interfere with head-to-head play. ; SEGA games are somewhat picky about their LAN environment, so leaving this @@ -30,16 +29,33 @@ enable=1 ; 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.250.0 +subnet=192.168.100.0 + +[gpio] +; ALLS DIP switches. +enable=1 + +; 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 [gfx] enable=1 +; ----------------------------------------------------------------------------- +; 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] ; Input API selection for JVS input emulator. -; Set "1" to use a xinput gamepad and set "2" to use keyboard. -mode=2 - ; Test button virtual-key code. Default is the 1 key. test=0x31 ; Service button virtual-key code. Default is the 2 key. @@ -47,18 +63,20 @@ service=0x32 ; Keyboard button to increment coin counter. Default is the 3 key. coin=0x33 -[dinput] -LEFT_A=0x53 -LEFT_B=0x44 -LEFT_C=0x46 -LEFT_MENU=0x51 -LEFT_SIDE=0x52 -RIGHT_A=0x4A -RIGHT_B=0x4B -RIGHT_C=0x4C -RIGHT_MENU=0x50 -RIGHT_SIDE=0x55 -SLIDER_LEFT=0x54 -SLIDER_RIGHT=0x59 -;Change move speed of slider when use dinput -SLIDER_SPEED=1000 \ No newline at end of file +; Set "1" to enable mouse lever emulation, "0" to use XInput +mouse=1 + +; Keyboard input bindings +left1=0x41 ; A +left2=0x53 ; S +left3=0x44 ; D + +leftSide=0x01 ; Mouse Left +rightSide=0x02 ; Mouse Right + +right1=0x4A ; J +right1=0x4B ; K +right3=0x4C ; L + +leftMenu=0x55 ; U +rightMenu=0x4F ; O diff --git a/dist/mu3/start.bat b/dist/mu3/start.bat index c00f2ea..8058daf 100644 --- a/dist/mu3/start.bat +++ b/dist/mu3/start.bat @@ -1,15 +1,11 @@ @echo off + pushd %~dp0 +start /min inject -d -k mu3hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json +inject -d -k mu3hook.dll mu3 -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920 taskkill /f /im amdaemon.exe > nul 2>&1 -REM USA -REM start inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json - -REM JP -start inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_jpn.json -inject -d -k mercuryhook.dll ../WindowsNoEditor/Mercury/Binaries/Win64/Mercury-Win64-Shipping.exe - -taskkill /f /im amdaemon.exe > nul 2>&1 - -echo Game processes have terminated \ No newline at end of file +echo. +echo Game processes have terminated +pause \ No newline at end of file diff --git a/doc/config/common.md b/doc/config/common.md index 7dc14c1..de6f267 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -31,6 +31,13 @@ Default: `1` Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime reader (COM port number varies by game). +### `highbaud` + +Default: `1` + +Enables the high baudrate of the Aime card reader to be 115200 (instead of 38400). +This is required for some games (e.g. Chunithm) but not others (e.g. WACCA). + ### `aimePath` Default: `DEVICE\aime.txt` @@ -270,6 +277,33 @@ Default `1` Enable JVS port emulation. Disable to use the JVS port on a real AMEX. +## `[io4]` + +Configure emulation of the IO4 board. Same settings also apply to `[io3]`. + +### `enable` + +Default `1` + +Enable IO4 port emulation. Disable to use the IO4 port on a real ALLS. + +### `test` +Default `0x31` + +Test button virtual-key code. Default is the 1 key. + +### `service` + +Default `0x32` + +Service button virtual-key code. Default is the 2 key. + +### `coin` + +Default `0x33` + +Keyboard button to increment coin counter. Default is the 3 key. + ## `[keychip]` Configure keychip emulation. diff --git a/hooklib/touch.c b/hooklib/touch.c index ca0b8a9..9911514 100644 --- a/hooklib/touch.c +++ b/hooklib/touch.c @@ -19,6 +19,12 @@ This means there can be some license issues if you do use this code in some othe /* API hooks */ +static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + +static ATOM WINAPI hook_RegisterClassExA( + WNDCLASSEXA* wndClass +); + static int WINAPI hook_GetSystemMetrics( int nIndex ); @@ -35,8 +41,14 @@ static BOOL WINAPI hook_GetTouchInputInfo( int cbSize ); +static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor); + /* Link pointers */ +static ATOM (WINAPI *next_RegisterClassExA)( + const WNDCLASSEXA* wndClass +); + static int (WINAPI *next_GetSystemMetrics)( int nIndex ); @@ -53,10 +65,20 @@ static BOOL (WINAPI *next_GetTouchInputInfo)( int cbSize ); +static HCURSOR(WINAPI *next_SetCursor)(HCURSOR cursor); + static bool touch_hook_initted; +static bool touch_held; +static HWND registered_hWnd; static struct touch_screen_config touch_config; +static WNDPROC orig_wndProc; static const struct hook_symbol touch_hooks[] = { + { + .name = "RegisterClassExA", + .patch = hook_RegisterClassExA, + .link = (void**)&next_RegisterClassExA + }, { .name = "GetSystemMetrics", .patch = hook_GetSystemMetrics, @@ -72,6 +94,11 @@ static const struct hook_symbol touch_hooks[] = { .patch = hook_GetTouchInputInfo, .link = (void **) &next_GetTouchInputInfo }, + { + .name = "SetCursor", + .patch = hook_SetCursor, + .link = (void **) &next_SetCursor + }, }; void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self) @@ -93,6 +120,34 @@ void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE sel dprintf("TOUCH: hook enabled.\n"); } +static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) { + if (cursor == 0 && touch_config.cursor) + return 0; + + return next_SetCursor(cursor); +} + +// remap mouse events to touch events + +static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { + if (hWnd == registered_hWnd && (Msg == WM_LBUTTONDOWN || Msg == WM_LBUTTONUP || (touch_held && Msg == WM_MOUSEMOVE))) { + orig_wndProc(hWnd, WM_TOUCH, 1, 1); + } + + return orig_wndProc(hWnd, Msg, wParam, lParam); +} + +static ATOM WINAPI hook_RegisterClassExA( + WNDCLASSEXA* wndClass +) { + if (wndClass->lpfnWndProc) { + orig_wndProc = wndClass->lpfnWndProc; + wndClass->lpfnWndProc = (WNDPROC) hook_wndProc; + } + + return next_RegisterClassExA(wndClass); +} + // Spicetools misc/wintouchemu.cpp static int WINAPI hook_GetSystemMetrics( @@ -111,11 +166,11 @@ static BOOL WINAPI hook_RegisterTouchWindow( ULONG ulFlags ) { + registered_hWnd = hwnd; return true; } // Converting mouse event to touch event -// Does not work at current stage static BOOL WINAPI hook_GetTouchInputInfo( HANDLE hTouchInput, UINT cInputs, @@ -124,7 +179,15 @@ static BOOL WINAPI hook_GetTouchInputInfo( ) { bool result = false; + int sw, sh, cw, ch; + RECT cRect; + sw = GetSystemMetrics(SM_CXSCREEN); + sh = GetSystemMetrics(SM_CYSCREEN); + GetClientRect(registered_hWnd, &cRect); + cw = cRect.right - cRect.left; + ch = cRect.bottom - cRect.top; static bool mouse_state_old = false; + for (UINT input = 0; input < cInputs; input++) { TOUCHINPUT *touch_input = &pInputs[input]; @@ -143,8 +206,15 @@ static BOOL WINAPI hook_GetTouchInputInfo( if (mouse_state || mouse_state_old) { POINT cursorPos; + GetCursorPos(&cursorPos); + if (touch_config.remap) { + ScreenToClient(registered_hWnd, &cursorPos); + cursorPos.x = (long)(cursorPos.x * ((double)sw / cw)); + cursorPos.y = (long)(cursorPos.y * ((double)sh / ch)); + } + result = true; touch_input->x = cursorPos.x * 100; touch_input->y = cursorPos.y * 100; @@ -153,10 +223,12 @@ static BOOL WINAPI hook_GetTouchInputInfo( touch_input->dwFlags = 0; if (mouse_state && !mouse_state_old) { touch_input->dwFlags |= TOUCHEVENTF_DOWN; + touch_held = true; } else if (mouse_state && mouse_state_old) { touch_input->dwFlags |= TOUCHEVENTF_MOVE; } else if (!mouse_state && mouse_state_old) { touch_input->dwFlags |= TOUCHEVENTF_UP; + touch_held = false; } touch_input->dwMask = 0; touch_input->dwTime = 0; @@ -168,4 +240,4 @@ static BOOL WINAPI hook_GetTouchInputInfo( } return result; -} \ No newline at end of file +} diff --git a/hooklib/touch.h b/hooklib/touch.h index f80a25e..dad00ad 100644 --- a/hooklib/touch.h +++ b/hooklib/touch.h @@ -6,9 +6,11 @@ struct touch_screen_config { bool enable; + bool remap; + bool cursor; }; /* Init is not thread safe because API hook init is not thread safe blah blah blah you know the drill by now. */ -void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self); \ No newline at end of file +void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self);