diff --git a/.vscode/settings.json b/.vscode/settings.json index 9f1bd80..187dfff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,9 @@ "platform.h": "c", "stdbool.h": "c", "dprintf.h": "c", - "slider-frame.h": "c" + "slider-frame.h": "c", + "aime-dll.h": "c", + "sg-reader.h": "c", + "reg.h": "c" } } \ No newline at end of file diff --git a/Package.mk b/Package.mk index 06765bb..3c51378 100644 --- a/Package.mk +++ b/Package.mk @@ -1,142 +1,33 @@ -$(BUILD_DIR_ZIP)/chuni.zip: +$(BUILD_DIR_ZIP)/siva.zip: $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/chuni - $(V)mkdir -p $(BUILD_DIR_ZIP)/chuni/DEVICE + $(V)mkdir -p $(BUILD_DIR_ZIP)/siva + $(V)mkdir -p $(BUILD_DIR_ZIP)/siva/DEVICE $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_32)/chunihook/chunihook.dll \ - $(DIST_DIR)/chuni/taitools.ini \ - $(DIST_DIR)/chuni/start.bat \ - $(BUILD_DIR_ZIP)/chuni - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/chuni/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/chuni/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/chuni ; zip -r ../chuni.zip * - -$(BUILD_DIR_ZIP)/cxb.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/cxb - $(V)mkdir -p $(BUILD_DIR_ZIP)/cxb/DEVICE - $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_32)/cxbhook/cxbhook.dll \ - $(DIST_DIR)/cxb/taitools.ini \ - $(DIST_DIR)/cxb/start.bat \ - $(BUILD_DIR_ZIP)/cxb - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/cxb/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/cxb/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/cxb ; zip -r ../cxb.zip * - -$(BUILD_DIR_ZIP)/diva.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/diva - $(V)mkdir -p $(BUILD_DIR_ZIP)/diva/DEVICE + $(BUILD_DIR_32)/sivahook/sivahook.dll \ + $(BUILD_DIR_ZIP)/siva + $(V)mv $(BUILD_DIR_ZIP)/siva/inject.exe \ + $(BUILD_DIR_ZIP)/siva/inject_32.exe + $(V)mv $(BUILD_DIR_ZIP)/siva/sivahook.dll \ + $(BUILD_DIR_ZIP)/siva/sivahook_32.dll $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_64)/divahook/divahook.dll \ - $(DIST_DIR)/diva/taitools.ini \ - $(DIST_DIR)/diva/start.bat \ - $(BUILD_DIR_ZIP)/diva + $(BUILD_DIR_64)/sivahook/sivahook.dll \ + $(DIST_DIR)/siva/taitools.ini \ + $(DIST_DIR)/siva/start.bat \ + $(BUILD_DIR_ZIP)/siva $(V)cp pki/billing.pub \ pki/ca.crt \ - $(BUILD_DIR_ZIP)/diva/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/diva/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/diva ; zip -r ../diva.zip * - -$(BUILD_DIR_ZIP)/carol.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/carol - $(V)mkdir -p $(BUILD_DIR_ZIP)/carol/DEVICE - $(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_32)/carolhook/carolhook.dll \ - $(DIST_DIR)/carol/taitools.ini \ - $(DIST_DIR)/carol/start.bat \ - $(BUILD_DIR_ZIP)/carol - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/carol/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/carol/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/carol ; zip -r ../carol.zip * - -$(BUILD_DIR_ZIP)/idz.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/idz - $(V)mkdir -p $(BUILD_DIR_ZIP)/idz/DEVICE - $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_64)/idzhook/idzhook.dll \ - $(DIST_DIR)/idz/taitools.ini \ - $(DIST_DIR)/idz/start.bat \ - $(BUILD_DIR_ZIP)/idz - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/idz/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/idz/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/idz ; zip -r ../idz.zip * - -$(BUILD_DIR_ZIP)/mercury.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/mercury - $(V)mkdir -p $(BUILD_DIR_ZIP)/mercury/DEVICE - $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_64)/mercuryhook/mercuryhook.dll \ - $(DIST_DIR)/mercury/taitools.ini \ - $(DIST_DIR)/mercury/start.bat \ - $(BUILD_DIR_ZIP)/mercury - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/mercury/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/mercury/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/mercury ; zip -r ../mercury.zip * - - -$(BUILD_DIR_ZIP)/mu3.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/mu3 - $(V)mkdir -p $(BUILD_DIR_ZIP)/mu3/DEVICE - $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_64)/mu3hook/mu3hook.dll \ - $(DIST_DIR)/mu3/taitools.ini \ - $(DIST_DIR)/mu3/start.bat \ - $(BUILD_DIR_ZIP)/mu3 - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/mu3/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/mu3/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/mu3 ; zip -r ../mu3.zip * - -$(BUILD_DIR_ZIP)/mai2.zip: - $(V)echo ... $@ - $(V)mkdir -p $(BUILD_DIR_ZIP)/mai2 - $(V)mkdir -p $(BUILD_DIR_ZIP)/mai2/DEVICE - $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ - $(BUILD_DIR_64)/mai2hook/mai2hook.dll \ - $(DIST_DIR)/mai2/taitools.ini \ - $(DIST_DIR)/mai2/start.bat \ - $(BUILD_DIR_ZIP)/mai2 - $(V)cp pki/billing.pub \ - pki/ca.crt \ - $(BUILD_DIR_ZIP)/mai2/DEVICE - $(V)strip $(BUILD_DIR_ZIP)/mai2/*.{exe,dll} - $(V)cd $(BUILD_DIR_ZIP)/mai2 ; zip -r ../mai2.zip * + $(BUILD_DIR_ZIP)/siva/DEVICE + $(V)strip $(BUILD_DIR_ZIP)/siva/*.{exe,dll} + $(V)cd $(BUILD_DIR_ZIP)/siva ; zip -r ../siva.zip * $(BUILD_DIR_ZIP)/doc.zip: \ $(DOC_DIR)/config \ - $(DOC_DIR)/chunihook.md \ - $(DOC_DIR)/idzhook.md \ | $(zipdir)/ $(V)echo ... $@ $(V)zip -r $@ $^ $(BUILD_DIR_ZIP)/taitools.zip: \ - $(BUILD_DIR_ZIP)/chuni.zip \ - $(BUILD_DIR_ZIP)/cxb.zip \ - $(BUILD_DIR_ZIP)/carol.zip \ - $(BUILD_DIR_ZIP)/diva.zip \ - $(BUILD_DIR_ZIP)/doc.zip \ - $(BUILD_DIR_ZIP)/idz.zip \ - $(BUILD_DIR_ZIP)/mercury.zip \ - $(BUILD_DIR_ZIP)/mu3.zip \ - $(BUILD_DIR_ZIP)/mai2.zip \ + $(BUILD_DIR_ZIP)/siva.zip \ CHANGELOG.md \ README.md \ diff --git a/board/aime-dll.c b/board/aime-dll.c deleted file mode 100644 index de8eb1e..0000000 --- a/board/aime-dll.c +++ /dev/null @@ -1,112 +0,0 @@ -#include - -#include -#include - -#include "board/aime-dll.h" - -#include "util/dll-bind.h" -#include "util/dprintf.h" - -const struct dll_bind_sym aime_dll_syms[] = { - { - .sym = "aime_io_init", - .off = offsetof(struct aime_dll, init), - }, { - .sym = "aime_io_nfc_poll", - .off = offsetof(struct aime_dll, nfc_poll), - }, { - .sym = "aime_io_nfc_get_aime_id", - .off = offsetof(struct aime_dll, nfc_get_aime_id), - }, { - .sym = "aime_io_nfc_get_felica_id", - .off = offsetof(struct aime_dll, nfc_get_felica_id), - }, { - .sym = "aime_io_led_set_color", - .off = offsetof(struct aime_dll, led_set_color), - } -}; - -struct aime_dll aime_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 aime_dll_init(const struct aime_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("NFC Assembly: Failed to load IO DLL: %lx: %S\n", - hr, - cfg->path); - - goto end; - } - - dprintf("NFC Assembly: Using custom IO DLL: %S\n", cfg->path); - src = owned; - } else { - owned = NULL; - src = self; - } - - get_api_version = (void *) GetProcAddress(src, "aime_io_get_api_version"); - - if (get_api_version != NULL) { - aime_dll.api_version = get_api_version(); - } else { - aime_dll.api_version = 0x0100; - dprintf("Custom IO DLL does not expose aime_io_get_api_version, " - "assuming API version 1.0.\n" - "Please ask the developer to update their DLL.\n"); - } - - if (aime_dll.api_version >= 0x0200) { - hr = E_NOTIMPL; - dprintf("NFC Assembly: Custom IO DLL implements an unsupported " - "API version (%#04x). Please update Taitools.\n", - aime_dll.api_version); - - goto end; - } - - sym = aime_dll_syms; - hr = dll_bind(&aime_dll, src, &sym, _countof(aime_dll_syms)); - - if (FAILED(hr)) { - if (src != self) { - dprintf("NFC Assembly: 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; -} diff --git a/board/aime-dll.h b/board/aime-dll.h deleted file mode 100644 index 354516b..0000000 --- a/board/aime-dll.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include "aimeio/aimeio.h" - -struct aime_dll { - uint16_t api_version; - HRESULT (*init)(void); - HRESULT (*nfc_poll)(uint8_t unit_no); - HRESULT (*nfc_get_aime_id)( - uint8_t unit_no, - uint8_t *luid, - size_t luid_size); - HRESULT (*nfc_get_felica_id)(uint8_t unit_no, uint64_t *IDm); - void (*led_set_color)(uint8_t unit_no, uint8_t r, uint8_t g, uint8_t b); -}; - -struct aime_dll_config { - wchar_t path[MAX_PATH]; -}; - -extern struct aime_dll aime_dll; - -HRESULT aime_dll_init(const struct aime_dll_config *cfg, HINSTANCE self); diff --git a/board/config.c b/board/config.c index 191425a..3e0156b 100644 --- a/board/config.c +++ b/board/config.c @@ -5,32 +5,7 @@ #include #include -#include "board/aime-dll.h" #include "board/config.h" -#include "board/sg-reader.h" - -static void aime_dll_config_load(struct aime_dll_config *cfg, const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - GetPrivateProfileStringW( - L"aimeio", - L"path", - L"", - cfg->path, - _countof(cfg->path), - filename); -} - -void aime_config_load(struct aime_config *cfg, const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - aime_dll_config_load(&cfg->dll, filename); - cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename); -} void io4_config_load(struct io4_config *cfg, const wchar_t *filename) { diff --git a/board/config.h b/board/config.h index f436a82..9a4f07f 100644 --- a/board/config.h +++ b/board/config.h @@ -4,7 +4,5 @@ #include #include "board/io4.h" -#include "board/sg-reader.h" -void aime_config_load(struct aime_config *cfg, const wchar_t *filename); void io4_config_load(struct io4_config *cfg, const wchar_t *filename); diff --git a/board/meson.build b/board/meson.build index a710ef6..c051a4a 100644 --- a/board/meson.build +++ b/board/meson.build @@ -10,8 +10,6 @@ board_lib = static_library( iccard_lib, ], sources : [ - 'aime-dll.c', - 'aime-dll.h', 'config.c', 'config.h', 'guid.c', @@ -30,7 +28,5 @@ board_lib = static_library( 'sg-nfc.c', 'sg-nfc.h', 'sg-nfc-cmd.h', - 'sg-reader.c', - 'sg-reader.h', ], ) diff --git a/board/sg-reader.c b/board/sg-reader.c deleted file mode 100644 index dbf0392..0000000 --- a/board/sg-reader.c +++ /dev/null @@ -1,186 +0,0 @@ -#include - -#include -#include -#include - -#include "board/aime-dll.h" -#include "board/sg-led.h" -#include "board/sg-nfc.h" -#include "board/sg-reader.h" - -#include "hook/iohook.h" - -#include "hooklib/uart.h" - -#include "util/dprintf.h" -#include "util/dump.h" - -static HRESULT sg_reader_handle_irp(struct irp *irp); -static HRESULT sg_reader_handle_irp_locked(struct irp *irp); -static HRESULT sg_reader_nfc_poll(void *ctx); -static HRESULT sg_reader_nfc_get_aime_id( - void *ctx, - uint8_t *luid, - size_t luid_size); -static HRESULT sg_reader_nfc_get_felica_id(void *ctx, uint64_t *IDm); -static void sg_reader_led_set_color(void *ctx, uint8_t r, uint8_t g, uint8_t b); - -static const struct sg_nfc_ops sg_reader_nfc_ops = { - .poll = sg_reader_nfc_poll, - .get_aime_id = sg_reader_nfc_get_aime_id, - .get_felica_id = sg_reader_nfc_get_felica_id, -}; - -static const struct sg_led_ops sg_reader_led_ops = { - .set_color = sg_reader_led_set_color, -}; - -static CRITICAL_SECTION sg_reader_lock; -static bool sg_reader_started; -static HRESULT sg_reader_start_hr; -static struct uart sg_reader_uart; -static uint8_t sg_reader_written_bytes[520]; -static uint8_t sg_reader_readable_bytes[520]; -static struct sg_nfc sg_reader_nfc; -static struct sg_led sg_reader_led; - -HRESULT sg_reader_hook_init( - const struct aime_config *cfg, - unsigned int port_no, - HINSTANCE self) -{ - HRESULT hr; - - assert(cfg != NULL); - assert(self != NULL); - - if (!cfg->enable) { - return S_FALSE; - } - - hr = aime_dll_init(&cfg->dll, self); - - if (FAILED(hr)) { - return hr; - } - - sg_nfc_init(&sg_reader_nfc, 0x00, &sg_reader_nfc_ops, NULL); - sg_led_init(&sg_reader_led, 0x08, &sg_reader_led_ops, NULL); - - InitializeCriticalSection(&sg_reader_lock); - - 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); - sg_reader_uart.readable.bytes = sg_reader_readable_bytes; - sg_reader_uart.readable.nbytes = sizeof(sg_reader_readable_bytes); - - return iohook_push_handler(sg_reader_handle_irp); -} - -static HRESULT sg_reader_handle_irp(struct irp *irp) -{ - HRESULT hr; - - assert(irp != NULL); - - if (!uart_match_irp(&sg_reader_uart, irp)) { - return iohook_invoke_next(irp); - } - - EnterCriticalSection(&sg_reader_lock); - hr = sg_reader_handle_irp_locked(irp); - LeaveCriticalSection(&sg_reader_lock); - - return hr; -} - -static HRESULT sg_reader_handle_irp_locked(struct irp *irp) -{ - HRESULT hr; - -#if 0 - if (irp->op == IRP_OP_WRITE) { - dprintf("WRITE:\n"); - dump_const_iobuf(&irp->write); - } -#endif - -#if 0 - if (irp->op == IRP_OP_READ) { - dprintf("READ:\n"); - dump_iobuf(&sg_reader_uart.readable); - } -#endif - - if (irp->op == IRP_OP_OPEN) { - /* Unfortunately the card reader UART gets opened and closed - repeatedly */ - - if (!sg_reader_started) { - dprintf("NFC Assembly: Starting backend DLL\n"); - hr = aime_dll.init(); - - sg_reader_started = true; - sg_reader_start_hr = hr; - - if (FAILED(hr)) { - dprintf("NFC Assembly: Backend error: %x\n", (int) hr); - - return hr; - } - } else { - hr = sg_reader_start_hr; - - if (FAILED(hr)) { - return hr; - } - } - } - - hr = uart_handle_irp(&sg_reader_uart, irp); - - if (FAILED(hr) || irp->op != IRP_OP_WRITE) { - return hr; - } - - sg_nfc_transact( - &sg_reader_nfc, - &sg_reader_uart.readable, - sg_reader_uart.written.bytes, - sg_reader_uart.written.pos); - - sg_led_transact( - &sg_reader_led, - &sg_reader_uart.readable, - sg_reader_uart.written.bytes, - sg_reader_uart.written.pos); - - sg_reader_uart.written.pos = 0; - - return hr; -} - -static HRESULT sg_reader_nfc_poll(void *ctx) -{ - return aime_dll.nfc_poll(0); -} - -static HRESULT sg_reader_nfc_get_aime_id( - void *ctx, - uint8_t *luid, - size_t luid_size) -{ - return aime_dll.nfc_get_aime_id(0, luid, luid_size); -} - -static HRESULT sg_reader_nfc_get_felica_id(void *ctx, uint64_t *IDm) -{ - return aime_dll.nfc_get_felica_id(0, IDm); -} - -static void sg_reader_led_set_color(void *ctx, uint8_t r, uint8_t g, uint8_t b) -{ - aime_dll.led_set_color(0, r, g, b); -} diff --git a/board/sg-reader.h b/board/sg-reader.h deleted file mode 100644 index 673a8bd..0000000 --- a/board/sg-reader.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -#include - -#include "board/aime-dll.h" - -struct aime_config { - struct aime_dll_config dll; - bool enable; -}; - -HRESULT sg_reader_hook_init( - const struct aime_config *cfg, - unsigned int port_no, - HINSTANCE self); diff --git a/dist/carol/segatools.ini b/dist/carol/segatools.ini deleted file mode 100644 index b0c1d0d..0000000 --- a/dist/carol/segatools.ini +++ /dev/null @@ -1,48 +0,0 @@ -[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= - -[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. -enable=1 - -[gpio] -dipsw1=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.126.0 - -[gfx] -; Force the game to run windowed. -windowed=1 -; Add a frame to the game window if running windowed. -framed=1 -; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) -monitor=0 - -[aimeio] -; To use a custom card reader IO DLL enter its path here. -; Leave empty if you want to use Taitools built-in keyboard input. -path= - -[io3] -; 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 diff --git a/dist/carol/start.bat b/dist/carol/start.bat deleted file mode 100644 index 0fab950..0000000 --- a/dist/carol/start.bat +++ /dev/null @@ -1,13 +0,0 @@ -@echo off - -pushd %~dp0 - -taskkill /f /im aimeReaderHost.exe > nul 2>&1 - -start /min inject -d -k carolhook.dll aimeReaderHost.exe -p 10 -inject -d -k carolhook.dll carol_nu.exe -taskkill /f /im aimeReaderHost.exe > nul 2>&1 - -echo. -echo Game processes have terminated -pause \ No newline at end of file diff --git a/dist/chuni/segatools.ini b/dist/chuni/segatools.ini deleted file mode 100644 index 0a9939e..0000000 --- a/dist/chuni/segatools.ini +++ /dev/null @@ -1,80 +0,0 @@ -[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= - -[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. -; Chunithm is extremely picky about its LAN environment, so leaving this -; setting enabled is strongly recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.139.0 - -[gfx] -; Force the game to run windowed. -windowed=1 -; Add a frame to the game window if running windowed. -framed=1 -; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) -monitor=0 - -[aimeio] -; To use a custom card reader IO DLL enter its path here. -; Leave empty if you want to use Taitools built-in keyboard input. -path= - -[chuniio] -; To use a custom Chunithm IO DLL enter its path here. -; Leave empty if you want to use Taitools built-in keyboard 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. - -[io3] -; 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 - -; Key bindings for each of the 32 touch cells. The default key map, depicted -; in left-to-right order, is as follows: -; -; SSSSDDDDFFFFGGGGHHHHJJJJKKKKLLLL -; -; Touch cells are numbered FROM RIGHT TO LEFT! starting from 1. This is in -; order to match the numbering used in the operator menu and service manual. -; -; Uncomment and complete the following sequence of settings to configure a -; custom high-precision touch strip controller if you have one. -[slider] -;cell32=0x53 -;cell31=0x53 -;cell30=0x53 -; ... etc ... diff --git a/dist/chuni/start.bat b/dist/chuni/start.bat deleted file mode 100644 index 0c942e9..0000000 --- a/dist/chuni/start.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off - -pushd %~dp0 - -start /min inject -d -k chunihook.dll aimeReaderHost.exe -p 12 -inject -d -k chunihook.dll chuniApp.exe -taskkill /f /im aimeReaderHost.exe > nul 2>&1 - -echo. -echo Game processes have terminated -pause \ No newline at end of file diff --git a/dist/cxb/resource/segatools.ini b/dist/cxb/resource/segatools.ini deleted file mode 100644 index a214976..0000000 --- a/dist/cxb/resource/segatools.ini +++ /dev/null @@ -1,4 +0,0 @@ -[aime] -; CXB is stupid, so we have to make the paths go back one -aimePath=../DEVICE/aime.txt -felicaPath=../DEVICE/felica.txt \ No newline at end of file diff --git a/dist/cxb/segatools.ini b/dist/cxb/segatools.ini deleted file mode 100644 index e0491ff..0000000 --- a/dist/cxb/segatools.ini +++ /dev/null @@ -1,75 +0,0 @@ -[vfs] -; Make sure theses are full paths and not relative or you will have a bad time -; 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= - -[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. -; Crossbeats is extremely picky about its LAN environment, so leaving this -; setting enabled is strongly recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.100.0 -billingCa=../DEVICE/ca.crt -billingPub=../DEVICE/billing.pub -billingType=2 - -[gfx] -; Force the game to run windowed. -windowed=1 -; Add a frame to the game window if running windowed. -framed=1 -; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) -monitor=0 - -[aime] -; Aime reader emulation -; CXB is stupid, so we have to make the paths go back one -enable=1 -aimePath=../DEVICE/aime.txt -felicaPath=../DEVICE/felica.txt - -[eeprom] -; See above -path=../DEVICE/eeprom.bin - -[sram] -; See above -path=../DEVICE/sram.bin - -[led] -; Emulation for the LED board. Currently it's just dummy responses, -; but if somebody wants to make their keyboard or whatever light -; up with the game they can -enable=1 - -[revio] -; Enable emulation of the rev IO board -enabe=1 -; 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 -; Menu up key. Default is up arrow. -up=0x26 -; Menu down key. Default is down arrow. -down=0x28 -; Menu cancel key. Default is the 4 key. -cancel=0x34 diff --git a/dist/cxb/start.bat b/dist/cxb/start.bat deleted file mode 100644 index af92b2d..0000000 --- a/dist/cxb/start.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -pushd %~dp0 - -inject -d -k cxbhook.dll Rev_v11.exe - -echo. -echo Game processes have terminated -pause \ No newline at end of file diff --git a/dist/diva/segatools.ini b/dist/diva/segatools.ini deleted file mode 100644 index e2608c0..0000000 --- a/dist/diva/segatools.ini +++ /dev/null @@ -1,54 +0,0 @@ -[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= - -[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. -; Chunithm is extremely picky about its LAN environment, so leaving this -; setting enabled is strongly recommended. -enable=1 - -[gpio] -dipsw1=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.150.0 - -[slider] -cell1=0x51 -cell2=0x57 -cell3=0x45 -cell4=0x52 -cell5=0x55 -cell6=0x49 -cell7=0x4F -cell8=0x50 - -[buttons] -key1=0x27 -key2=0x28 -key3=0x25 -key4=0x26 -key5=0x20 - -; Sliders : <- QWER UIOP -> -; Triangle : Up arrow -; Square : Left Arrow -; Cross : Down Arrow -; Circle : Right arrow -; Enter : Space - diff --git a/dist/diva/start.bat b/dist/diva/start.bat deleted file mode 100644 index 72934f6..0000000 --- a/dist/diva/start.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -pushd %~dp0 - -inject -d -k divahook.dll diva.exe - -echo. -echo Game processes have terminated -pause \ No newline at end of file diff --git a/dist/idz/segatools.ini b/dist/idz/segatools.ini deleted file mode 100644 index 4634ab4..0000000 --- a/dist/idz/segatools.ini +++ /dev/null @@ -1,116 +0,0 @@ -[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 OPxx 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= - -[dns] -; Insert the hostname or IP address of the server you wish to use here. -; Note that 127.0.0.1, localhost etc are specifically rejected. -default=127.0.0.1 - -[ds] -; Region code on the emulated AMEX board DS EEPROM. -; 1: Japan -; 4: Export (some UI elements in English) -; -; NOTE: Changing this setting causes a factory reset. -region=1 - -[netenv] -; Simulate an ideal LAN environment. This may interfere with head-to-head play. -; SEGA games are somewhat picky about their LAN environment, so leaving this -; setting enabled is recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.100.0 - -[gpio] -; Emulated Nu DIP switch for Distribution Server setting. -; -; 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 - -[aimeio] -; To use a custom card reader IO DLL enter its path here. -; Leave empty if you want to use Taitools built-in keyboard input. -path= - -[idzio] -; To use a custom Initial D Zero IO DLL enter its path here. -; Leave empty if you want to use Taitools built-in gamepad/wheel input. -path= - -[io3] -; Input API selection for JVS input emulator. -; Set "xinput" to use a gamepad and "dinput" to use a steering wheel. -mode=xinput -; Automatically reset the simulated shifter to Neutral when XInput Start is -; pressed (e.g. when navigating menus between races). -autoNeutral=1 -; Use the left thumbstick for steering instead of both on XInput Controllers. -; Not recommended as it will not give you the precision needed for this game -singleStickSteering=0 -; Adjust scaling for steering wheel input. -; -; This setting scales the steering wheel input so that the maximum positive -; and minimum negative steering inputs reported in the operator menu's input -; test screen do not exceed the value below. The maximum possible value is 128, -; and the value that matches the input range of a real cabinet is 97. -; -; NOTE: This is not the same thing as DirectInput steering wheel movement -; range! Taitools cannot control the maximum angle of your physical steering -; wheel controller, this setting is vendor-specific and can only be adjusted -; in the Control Panel. -restrict=97 - -[dinput] -; Name of the DirectInput wheel to use (or any text that occurs in its name) -; Example: TMX -; -; If this is left blank then the first DirectInput device will be used. -deviceName= -; Name of the positional shifter to use (or any subset thereof). -; Leave blank if you do not have a positional shifter; a positional shifter -; will be simulated using the configured Shift Down and Shift Up buttons -; in this case. -; -; Can be the same device as the wheel. -; -; Example: T500 -shifterName= -; Pedal mappings. Valid axis names are: -; -; X, Y, Z, RX, RY, RZ, U, V -; -; (U and V are old names for Slider 1 and Slider 2). -; The examples below are valid for a Thrustmaster TMX. -brakeAxis=RZ -accelAxis=Y -; DirectInput button numbers to map to menu inputs. Note that buttons are -; numbered from 1; some software numbers buttons from 0. -start=3 -viewChg=10 -; Button mappings for the simulated six-speed shifter. -shiftDn=1 -shiftUp=2 -; Button mappings for the positional shifter, if present. -gear1=1 -gear2=2 -gear3=3 -gear4=4 -gear5=5 -gear6=6 -; Invert the accelerator and or brake axis -; (Needed when using DirectInput for the Dualshock 4 for example) -reverseAccelAxis=0 -reverseBrakeAxis=0 diff --git a/dist/idz/start.bat b/dist/idz/start.bat deleted file mode 100644 index b8d6b18..0000000 --- a/dist/idz/start.bat +++ /dev/null @@ -1,10 +0,0 @@ -@echo off - -pushd %~dp0 - -.\inject.exe -k .\idzhook.dll .\InitialD0_DX11_Nu.exe -.\inject.exe -d -k .\idzhook.dll .\amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json - -echo. -echo Game processes have terminated -pause \ No newline at end of file diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini deleted file mode 100644 index 25fdc31..0000000 --- a/dist/mai2/segatools.ini +++ /dev/null @@ -1,44 +0,0 @@ -[vfs] -; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) -amfs=amfs -; Create an empty directory somewhere and insert the path here. -; This directory may be shared between multiple SEGA games. -; NOTE: This has nothing to do with Windows %APPDATA%. -appdata=appdata -option=option - -[dns] -; Insert the hostname or IP address of the server you wish to use here. -; Note that 127.0.0.1, localhost etc are specifically rejected. -default=127.0.0.1 - -[ds] -; Region code on the emulated AMEX board DS EEPROM. -; 1: Japan -; 4: Export (some UI elements in English) -; -; NOTE: Changing this setting causes a factory reset. -region=1 - -[netenv] -; Simulate an ideal LAN environment. This may interfere with head-to-head play. -; SEGA games are somewhat picky about their LAN environment, so leaving this -; setting enabled is recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.172.0 - -[gfx] -enable=1 - -[io4] -; Delete -test=0x2E -; End -service=0x23 -; Insert -coin=0x2D diff --git a/dist/mai2/start.bat b/dist/mai2/start.bat deleted file mode 100644 index 2d6bd8f..0000000 --- a/dist/mai2/start.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -pushd %~dp0 - -taskkill /f /im amdaemon.exe > nul 2>&1 - -start inject -d -k mai2hook.dll amdaemon.exe -f -c config_client.json config_common.json config_server.json -inject.exe -d -k mai2hook.dll Sinmai.exe -screen-fullscreen 0 -screen-width 2160 -screen-height 1920 - -taskkill /f /im amdaemon.exe > nul 2>&1 - -echo Game processes have terminated \ No newline at end of file diff --git a/dist/mercury/segatools.ini b/dist/mercury/segatools.ini deleted file mode 100644 index f231c66..0000000 --- a/dist/mercury/segatools.ini +++ /dev/null @@ -1,56 +0,0 @@ -[vfs] -; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) -amfs=amfs -; Create an empty directory somewhere and insert the path here. -; This directory may be shared between multiple SEGA games. -; NOTE: This has nothing to do with Windows %APPDATA%. -appdata=appdata -option=option - -[dns] -; Insert the hostname or IP address of the server you wish to use here. -; Note that 127.0.0.1, localhost etc are specifically rejected. -default=127.0.0.1 - -[ds] -; Region code on the emulated AMEX board DS EEPROM. -; 1: Japan -; 4: Export (some UI elements in English) -; -; NOTE: Changing this setting causes a factory reset. -region=1 - -[netenv] -; Simulate an ideal LAN environment. This may interfere with head-to-head play. -; SEGA games are somewhat picky about their LAN environment, so leaving this -; setting enabled is recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.174.0 - -[gfx] -enable=1 - -[io4] -; Input API selection for JVS input emulator. -test=0x2D -service=0x2E -coin=0x24 -volup=0x26 -voldown=0x28 - -; Hooks related to the touch boards -[touch] -enable=1 - -; Hooks related to the LED board (codenamed Elisabeth) -[elisabeth] -enable=1 - -;[mercuryio] -; Use mercuryio.dll -;path=mercuryio.dll diff --git a/dist/mercury/start.bat b/dist/mercury/start.bat deleted file mode 100644 index c00f2ea..0000000 --- a/dist/mercury/start.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -pushd %~dp0 - -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 diff --git a/dist/mu3/segatools.ini b/dist/mu3/segatools.ini deleted file mode 100644 index 98cdb31..0000000 --- a/dist/mu3/segatools.ini +++ /dev/null @@ -1,60 +0,0 @@ -[vfs] -; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) -amfs=amfs -; Create an empty directory somewhere and insert the path here. -; This directory may be shared between multiple SEGA games. -; NOTE: This has nothing to do with Windows %APPDATA%. -appdata=appdata -option=option - -[dns] -; Insert the hostname or IP address of the server you wish to use here. -; Note that 127.0.0.1, localhost etc are specifically rejected. -default=127.0.0.1 - -[ds] -; Region code on the emulated AMEX board DS EEPROM. -; 1: Japan -; 4: Export (some UI elements in English) -; -; NOTE: Changing this setting causes a factory reset. -region=1 - -[netenv] -; Simulate an ideal LAN environment. This may interfere with head-to-head play. -; SEGA games are somewhat picky about their LAN environment, so leaving this -; setting enabled is recommended. -enable=1 - -[keychip] -; The /24 LAN subnet that the emulated keychip will tell the game to expect. -; If you disable netenv then you must set this to your LAN's IP subnet, and -; that subnet must start with 192.168. -subnet=192.168.162.0 - -[gfx] -enable=1 - -[io4] -; Input API selection for JVS input emulator. -; Set "1" to use a xinput gamepad and set "2" to use keyboard. -mode=2 - -test=0x31 -service=0x32 - -[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 diff --git a/dist/mu3/start.bat b/dist/mu3/start.bat deleted file mode 100644 index 3aceffb..0000000 --- a/dist/mu3/start.bat +++ /dev/null @@ -1,11 +0,0 @@ -@echo off -pushd %~dp0 - -taskkill /f /im amdaemon.exe > nul 2>&1 - -start inject -d -k mu3hook.dll amdaemon.exe -f -c config_client.json config_common.json config_server.json -inject -d -k mu3hook.dll mu3.exe - -taskkill /f /im amdaemon.exe > nul 2>&1 - -echo Game processes have terminated \ No newline at end of file diff --git a/dist/siva/start.bat b/dist/siva/start.bat new file mode 100644 index 0000000..e69de29 diff --git a/dist/siva/taitools.ini b/dist/siva/taitools.ini new file mode 100644 index 0000000..e69de29 diff --git a/hooklib/path.c b/hooklib/path.c index 1d1d4d2..eed458a 100644 --- a/hooklib/path.c +++ b/hooklib/path.c @@ -101,6 +101,17 @@ static BOOL WINAPI hook_PathFileExistsA(LPCSTR pszPath); static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath); +static UINT WINAPI hook_GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName); + +static DWORD WINAPI hook_GetPrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + /* Link pointers */ static BOOL (WINAPI *next_CreateDirectoryA)( @@ -185,6 +196,17 @@ static BOOL (WINAPI *next_PathFileExistsA)(LPCSTR pszPath); static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath); +static UINT (WINAPI *next_GetPrivateProfileIntW)(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName); + +static DWORD (WINAPI *next_GetPrivateProfileStringW)( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +); + /* Hook table */ static const struct hook_symbol path_hook_syms[] = { @@ -260,7 +282,15 @@ static const struct hook_symbol path_hook_syms[] = { .name = "PathFileExistsW", .patch = hook_PathFileExistsW, .link = (void **) &next_PathFileExistsW, - } + }, { + .name = "GetPrivateProfileIntW", + .patch = hook_GetPrivateProfileIntW, + .link = (void **) &next_GetPrivateProfileIntW, + }, { + .name = "GetPrivateProfileStringW", + .patch = hook_GetPrivateProfileStringW, + .link = (void **) &next_GetPrivateProfileStringW, + }, }; static bool path_hook_initted; @@ -906,3 +936,46 @@ static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath) return ok; } + +static UINT WINAPI hook_GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName) +{ + wchar_t *trans; + UINT ok; + + ok = path_transform_w(&trans, lpFileName); + + if (!ok) { + return FALSE; + } + + ok = next_GetPrivateProfileIntW(lpAppName, lpKeyName, nDefault, trans ? trans : lpFileName); + + free(trans); + + return ok; +} + +static DWORD WINAPI hook_GetPrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName +) +{ + wchar_t *trans; + DWORD ok; + + ok = path_transform_w(&trans, lpFileName); + + if (!ok) { + return FALSE; + } + + ok = next_GetPrivateProfileStringW(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, trans ? trans : lpFileName); + + free(trans); + + return ok; +} \ No newline at end of file diff --git a/iccard/nesica.c b/iccard/nesica.c index bbef9be..ef40009 100644 --- a/iccard/nesica.c +++ b/iccard/nesica.c @@ -36,9 +36,9 @@ HRESULT aime_card_populate( mifare->sectors[0].blocks[0].bytes[14] = 'T'; mifare->sectors[0].blocks[0].bytes[15] = 'U'; - memcpy_s(mifare->sectors[0].blocks[1].bytes, 4, 'T053', 4); - memcpy_s(mifare->sectors[0].blocks[1].bytes[4], 12, card_sn, 12); - memcpy_s(mifare->sectors[0].blocks[2].bytes, 16, card_sn[12], 4); + memcpy_s(mifare->sectors[0].blocks[1].bytes, 4, (uint8_t *)"T053", 4); + memcpy_s(mifare->sectors[0].blocks[1].bytes + 4, 12, card_sn, 12); + memcpy_s(mifare->sectors[0].blocks[2].bytes, 16, card_sn + 12, 4); return S_OK; } diff --git a/ll3hook/dllmain.c b/ll3hook/dllmain.c new file mode 100644 index 0000000..9b15ffa --- /dev/null +++ b/ll3hook/dllmain.c @@ -0,0 +1,113 @@ +#include + +#include "board/io4.h" + +#include "hook/process.h" + +#include "hooklib/serial.h" +#include "hooklib/spike.h" + +#include "gfxhook/gfx.h" +#include "gfxhook/d3d11.h" + +#include "ll3hook/config.h" +#include "ll3hook/ll3-dll.h" + +#include "platform/platform.h" + +#include "util/dprintf.h" + +static HMODULE ll3_hook_mod; +static process_entry_t ll3_startup; +static struct ll3_hook_config ll3_hook_cfg; + +/* This hook is based on mu3hook, with leaked ll3hook i/o codes. */ + +static DWORD CALLBACK ll3_pre_startup(void) +{ + HRESULT hr; + + dprintf("--- Begin ll3_pre_startup ---\n"); + + /* Load config */ + + ll3_hook_config_load(&ll3_hook_cfg, L".\\taitools.ini"); + + /* Hook Win32 APIs */ + serial_hook_init(); + + gfx_hook_init(&ll3_hook_cfg.gfx); + gfx_d3d11_hook_init(&ll3_hook_cfg.gfx, ll3_hook_mod); + + /* Initialize emulation hooks */ + + hr = platform_hook_init( + &ll3_hook_cfg.platform, + 3800, + ll3_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + hr = sg_reader_hook_init(&ll3_hook_cfg.aime, 1, ll3_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + hr = vfd_hook_init(2); + + if (FAILED(hr)) { + goto fail; + } + + hr = ll3_dll_init(&ll3_hook_cfg.dll, ll3_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + hr = ll3_io4_hook_init(&ll3_hook_cfg.io4); + + if (FAILED(hr)) { + goto fail; + } + + /* Start elisabeth Hooks for the LED and IO Board DLLs */ + elisabeth_hook_init(&ll3_hook_cfg.elisabeth); + + touch_hook_init(&ll3_hook_cfg.touch); + + /* Initialize debug helpers */ + + spike_hook_init(L".\\taitools.ini"); + + dprintf("--- End ll3_pre_startup ---\n"); + + /* Jump to EXE start address */ + + return ll3_startup(); + +fail: + ExitProcess(EXIT_FAILURE); +} + +BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) +{ + HRESULT hr; + + if (cause != DLL_PROCESS_ATTACH) { + return TRUE; + } + + ll3_hook_mod = mod; + + hr = process_hijack_startup(ll3_pre_startup, &ll3_startup); + + if (!SUCCEEDED(hr)) { + dprintf("Failed to hijack process startup: %x\n", (int) hr); + } + + return SUCCEEDED(hr); +} diff --git a/mercuryhook/meson.build b/ll3hook/meson.build similarity index 63% rename from mercuryhook/meson.build rename to ll3hook/meson.build index 7a676b2..37eda2f 100644 --- a/mercuryhook/meson.build +++ b/ll3hook/meson.build @@ -1,20 +1,19 @@ shared_library( - 'mercuryhook', + 'll3hook', name_prefix : '', include_directories : inc, implicit_include_directories : false, - vs_module_defs : 'mercuryhook.def', + vs_module_defs : 'll3hook.def', c_pch : '../precompiled.h', dependencies : [ capnhook.get_variable('hook_dep'), capnhook.get_variable('hooklib_dep'), ], link_with : [ - aimeio_lib, gfxhook_lib, board_lib, hooklib_lib, - mercuryio_lib, + ll3io_lib, platform_lib, util_lib, ], @@ -22,13 +21,7 @@ shared_library( 'config.c', 'config.h', 'dllmain.c', - 'io4.c', - 'io4.h', - 'mercury-dll.c', - 'mercury-dll.h', - 'elisabeth.h', - 'elisabeth.c', - 'touch.h', - 'touch.c' + 'll3-dll.c', + 'll3-dll.h', ], ) diff --git a/mercuryhook/config.c b/mercuryhook/config.c deleted file mode 100644 index f087942..0000000 --- a/mercuryhook/config.c +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "board/config.h" - -#include "hooklib/config.h" -#include "hooklib/dvd.h" -#include "gfxhook/config.h" - -#include "mercuryhook/config.h" - -#include "platform/config.h" - -void mercury_dll_config_load( - struct mercury_dll_config *cfg, - const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - GetPrivateProfileStringW( - L"mercuryio", - L"path", - L"", - cfg->path, - _countof(cfg->path), - filename); -} - -void touch_config_load( - struct touch_config *cfg, - const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - cfg->enable = GetPrivateProfileIntW( - L"touch", - L"enable", - 1, - filename); -} - -void elisabeth_config_load( - struct elisabeth_config *cfg, - const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - cfg->enable = GetPrivateProfileIntW( - L"elisabeth", - L"enable", - 1, - filename); -} - - -void mercury_hook_config_load( - struct mercury_hook_config *cfg, - const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - platform_config_load(&cfg->platform, filename); - aime_config_load(&cfg->aime, filename); - dvd_config_load(&cfg->dvd, filename); - io4_config_load(&cfg->io4, filename); - gfx_config_load(&cfg->gfx, filename); - mercury_dll_config_load(&cfg->dll, filename); - touch_config_load(&cfg->touch, filename); - elisabeth_config_load(&cfg->elisabeth, filename); -} diff --git a/mercuryhook/config.h b/mercuryhook/config.h deleted file mode 100644 index d5bf463..0000000 --- a/mercuryhook/config.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -#include "board/config.h" - -#include "hooklib/dvd.h" -#include "gfxhook/gfx.h" - -#include "mercuryhook/mercury-dll.h" -#include "mercuryhook/touch.h" -#include "mercuryhook/elisabeth.h" - -#include "platform/config.h" - -struct mercury_hook_config { - struct platform_config platform; - struct aime_config aime; - struct dvd_config dvd; - struct io4_config io4; - struct gfx_config gfx; - struct mercury_dll_config dll; - struct touch_config touch; - struct elisabeth_config elisabeth; -}; - -void mercury_dll_config_load( - struct mercury_dll_config *cfg, - const wchar_t *filename); - -void mercury_hook_config_load( - struct mercury_hook_config *cfg, - const wchar_t *filename); diff --git a/mercuryhook/dllmain.c b/mercuryhook/dllmain.c deleted file mode 100644 index 14726aa..0000000 --- a/mercuryhook/dllmain.c +++ /dev/null @@ -1,121 +0,0 @@ -#include - -#include "board/io4.h" -#include "board/sg-reader.h" -#include "board/vfd.h" - -#include "hook/process.h" - -#include "hooklib/serial.h" -#include "hooklib/spike.h" - -#include "gfxhook/gfx.h" -#include "gfxhook/d3d11.h" - -#include "mercuryhook/config.h" -#include "mercuryhook/io4.h" -#include "mercuryhook/mercury-dll.h" -#include "mercuryhook/elisabeth.h" -#include "mercuryhook/touch.h" - -#include "platform/platform.h" - -#include "util/dprintf.h" - -static HMODULE mercury_hook_mod; -static process_entry_t mercury_startup; -static struct mercury_hook_config mercury_hook_cfg; - -/* This hook is based on mu3hook, with leaked mercuryhook i/o codes. */ - -static DWORD CALLBACK mercury_pre_startup(void) -{ - HRESULT hr; - - dprintf("--- Begin mercury_pre_startup ---\n"); - - /* Load config */ - - mercury_hook_config_load(&mercury_hook_cfg, L".\\taitools.ini"); - - /* Hook Win32 APIs */ - - dvd_hook_init(&mercury_hook_cfg.dvd, mercury_hook_mod); - serial_hook_init(); - - gfx_hook_init(&mercury_hook_cfg.gfx); - gfx_d3d11_hook_init(&mercury_hook_cfg.gfx, mercury_hook_mod); - - /* Initialize emulation hooks */ - - hr = platform_hook_init( - &mercury_hook_cfg.platform, - "SDFE", - "ACA1", - mercury_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = sg_reader_hook_init(&mercury_hook_cfg.aime, 1, mercury_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = vfd_hook_init(2); - - if (FAILED(hr)) { - goto fail; - } - - hr = mercury_dll_init(&mercury_hook_cfg.dll, mercury_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = mercury_io4_hook_init(&mercury_hook_cfg.io4); - - if (FAILED(hr)) { - goto fail; - } - - /* Start elisabeth Hooks for the LED and IO Board DLLs */ - elisabeth_hook_init(&mercury_hook_cfg.elisabeth); - - touch_hook_init(&mercury_hook_cfg.touch); - - /* Initialize debug helpers */ - - spike_hook_init(L".\\taitools.ini"); - - dprintf("--- End mercury_pre_startup ---\n"); - - /* Jump to EXE start address */ - - return mercury_startup(); - -fail: - ExitProcess(EXIT_FAILURE); -} - -BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) -{ - HRESULT hr; - - if (cause != DLL_PROCESS_ATTACH) { - return TRUE; - } - - mercury_hook_mod = mod; - - hr = process_hijack_startup(mercury_pre_startup, &mercury_startup); - - if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); - } - - return SUCCEEDED(hr); -} diff --git a/mercuryhook/elisabeth.c b/mercuryhook/elisabeth.c deleted file mode 100644 index 7078a21..0000000 --- a/mercuryhook/elisabeth.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -#include -#include -#include - -#include "mercuryhook/elisabeth.h" -#include "mercuryhook/mercury-dll.h" - -#include "hook/table.h" - -#include "hooklib/uart.h" -#include "hooklib/dll.h" -#include "hooklib/path.h" -#include "hooklib/setupapi.h" - -#include "util/dprintf.h" - -/* Hooks targeted DLLs dynamically loaded by elisabeth. */ - -static void dll_hook_insert_hooks(HMODULE target); -static FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name); -static FARPROC (WINAPI *next_GetProcAddress)(HMODULE hModule, const char *name); -static int my_USBIntLED_Init(); -static int my_USBIntLED_set(); - -static const struct hook_symbol win32_hooks[] = { - { - .name = "GetProcAddress", - .patch = my_GetProcAddress, - .link = (void **) &next_GetProcAddress - } -}; - -HRESULT elisabeth_hook_init(struct elisabeth_config *cfg) -{ - if (!cfg->enable) { - return S_OK; - } - dll_hook_insert_hooks(NULL); - dprintf("Elisabeth: Init\n"); - return S_OK; -} - -static void dll_hook_insert_hooks(HMODULE target) -{ - hook_table_apply( - target, - "kernel32.dll", - win32_hooks, - _countof(win32_hooks)); -} - -FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name) -{ - uintptr_t ordinal = (uintptr_t) name; - - FARPROC result = next_GetProcAddress(hModule, name); - - if (ordinal > 0xFFFF) { - /* Import by name */ - if (strcmp(name, "USBIntLED_Init") == 0) { - result = (FARPROC) my_USBIntLED_Init; - } - - if (strcmp(name, "USBIntLED_set") == 0) { - result = (FARPROC) my_USBIntLED_set; - } - } - - return result; -} - -/* Intercept the call to initialize the LED board. */ -static int my_USBIntLED_Init() -{ - dprintf("Elisabeth: my_USBIntLED_Init hit!\n"); - return 1; -} - -static int my_USBIntLED_set(int data1, struct led_data data2) -{ - assert(mercury_dll.set_leds != NULL); - mercury_dll.set_leds(data2); - return 1; -} diff --git a/mercuryhook/elisabeth.h b/mercuryhook/elisabeth.h deleted file mode 100644 index 5806c99..0000000 --- a/mercuryhook/elisabeth.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include - -struct led_data { - DWORD unitCount; - uint8_t rgba[480 * 4]; -}; - -struct elisabeth_config { - bool enable; -}; - -HRESULT elisabeth_hook_init(struct elisabeth_config *cfg); diff --git a/mercuryhook/io4.c b/mercuryhook/io4.c deleted file mode 100644 index df22656..0000000 --- a/mercuryhook/io4.c +++ /dev/null @@ -1,91 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "board/io4.h" - -#include "mercuryhook/mercury-dll.h" - -#include "util/dprintf.h" - -bool mercury_io_coin = false; -uint16_t mercury_io_coins = 0; - -static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state); - -static const struct io4_ops mercury_io4_ops = { - .poll = mercury_io4_poll, -}; - -HRESULT mercury_io4_hook_init(const struct io4_config *cfg) -{ - HRESULT hr; - - assert(mercury_dll.init != NULL); - - hr = io4_hook_init(cfg, &mercury_io4_ops, NULL); - - if (FAILED(hr)) { - return hr; - } - - return mercury_dll.init(); -} - -static HRESULT mercury_io4_poll(void *ctx, struct io4_state *state) -{ - uint8_t opbtn; - uint8_t gamebtn; - HRESULT hr; - - assert(mercury_dll.poll != NULL); - assert(mercury_dll.get_opbtns != NULL); - assert(mercury_dll.get_gamebtns != NULL); - - memset(state, 0, sizeof(*state)); - - hr = mercury_dll.poll(); - - if (FAILED(hr)) { - return hr; - } - - opbtn = 0; - gamebtn = 0; - - mercury_dll.get_opbtns(&opbtn); - mercury_dll.get_gamebtns(&gamebtn); - - if (opbtn & MERCURY_IO_OPBTN_TEST) { - state->buttons[0] |= IO4_BUTTON_TEST; - } - - if (opbtn & MERCURY_IO_OPBTN_SERVICE) { - state->buttons[0] |= IO4_BUTTON_SERVICE; - } - - if (opbtn & MERCURY_IO_OPBTN_COIN) { - if (!mercury_io_coin) { - mercury_io_coin = true; - mercury_io_coins++; - } - } - else { - mercury_io_coin = false; - } - - state->chutes[0] = 128 + 256 * mercury_io_coins; - - if (gamebtn & MERCURY_IO_GAMEBTN_VOL_UP) { - state->buttons[0] |= 1 << 1; - } - - if (gamebtn & MERCURY_IO_GAMEBTN_VOL_DOWN) { - state->buttons[0] |= 1 << 0; - } - - return S_OK; -} diff --git a/mercuryhook/io4.h b/mercuryhook/io4.h deleted file mode 100644 index 87dc6d7..0000000 --- a/mercuryhook/io4.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#include "board/io4.h" - -HRESULT mercury_io4_hook_init(const struct io4_config *cfg); diff --git a/mercuryhook/mercury-dll.c b/mercuryhook/mercury-dll.c deleted file mode 100644 index bf21d30..0000000 --- a/mercuryhook/mercury-dll.c +++ /dev/null @@ -1,118 +0,0 @@ -#include - -#include -#include - -#include "mercuryhook/mercury-dll.h" - -#include "util/dll-bind.h" -#include "util/dprintf.h" - -const struct dll_bind_sym mercury_dll_syms[] = { - { - .sym = "mercury_io_init", - .off = offsetof(struct mercury_dll, init), - }, { - .sym = "mercury_io_poll", - .off = offsetof(struct mercury_dll, poll), - }, { - .sym = "mercury_io_get_opbtns", - .off = offsetof(struct mercury_dll, get_opbtns), - }, { - .sym = "mercury_io_get_gamebtns", - .off = offsetof(struct mercury_dll, get_gamebtns), - }, { - .sym = "mercury_io_touch_init", - .off = offsetof(struct mercury_dll, touch_init), - }, { - .sym = "mercury_io_touch_start", - .off = offsetof(struct mercury_dll, touch_start), - }, { - .sym = "mercury_io_touch_set_leds", - .off = offsetof(struct mercury_dll, set_leds), - } -}; - -struct mercury_dll mercury_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 mercury_dll_init(const struct mercury_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("Wacca IO: Failed to load IO DLL: %lx: %S\n", - hr, - cfg->path); - - goto end; - } - - dprintf("Wacca IO: Using custom IO DLL: %S\n", cfg->path); - src = owned; - } else { - owned = NULL; - src = self; - } - - get_api_version = (void *) GetProcAddress(src, "mercury_io_get_api_version"); - - if (get_api_version != NULL) { - mercury_dll.api_version = get_api_version(); - } else { - mercury_dll.api_version = 0x0100; - dprintf("Custom IO DLL does not expose mercury_io_get_api_version, " - "assuming API version 1.0.\n" - "Please ask the developer to update their DLL.\n"); - } - - if (mercury_dll.api_version >= 0x0200) { - hr = E_NOTIMPL; - dprintf("Wacca IO: Custom IO DLL implements an unsupported " - "API version (%#04x). Please update Taitools.\n", - mercury_dll.api_version); - - goto end; - } - - sym = mercury_dll_syms; - hr = dll_bind(&mercury_dll, src, &sym, _countof(mercury_dll_syms)); - - if (FAILED(hr)) { - if (src != self) { - dprintf("Wacca 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; -} diff --git a/mercuryhook/mercury-dll.h b/mercuryhook/mercury-dll.h deleted file mode 100644 index fa27edb..0000000 --- a/mercuryhook/mercury-dll.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include "mercuryio/mercuryio.h" -#include "mercuryhook/elisabeth.h" - -struct mercury_dll { - uint16_t api_version; - HRESULT (*init)(void); - HRESULT (*poll)(void); - void (*get_opbtns)(uint8_t *opbtn); - void (*get_gamebtns)(uint8_t *gamebtn); - HRESULT (*touch_init)(void); - void (*touch_start)(mercury_io_touch_callback_t callback); - void (*set_leds)(struct led_data data); -}; - -struct mercury_dll_config { - wchar_t path[MAX_PATH]; -}; - -extern struct mercury_dll mercury_dll; - -HRESULT mercury_dll_init(const struct mercury_dll_config *cfg, HINSTANCE self); diff --git a/mercuryhook/mercuryhook.def b/mercuryhook/mercuryhook.def deleted file mode 100644 index 32f33c1..0000000 --- a/mercuryhook/mercuryhook.def +++ /dev/null @@ -1,21 +0,0 @@ -LIBRARY mercuryhook - -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 - amDllVideoClose @2 - amDllVideoGetVBiosVersion @4 - amDllVideoOpen @1 - amDllVideoSetResolution @3 - mercury_io_get_api_version - mercury_io_get_gamebtns - mercury_io_get_opbtns - mercury_io_touch_init - mercury_io_touch_start - mercury_io_touch_set_leds - mercury_io_init - mercury_io_poll diff --git a/mercuryhook/touch.c b/mercuryhook/touch.c deleted file mode 100644 index 87ba6d5..0000000 --- a/mercuryhook/touch.c +++ /dev/null @@ -1,518 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "board/slider-cmd.h" -#include "board/slider-frame.h" - -#include "mercuryhook/mercury-dll.h" -#include "mercuryhook/touch.h" - -#include "hook/iobuf.h" -#include "hook/iohook.h" - -#include "hooklib/uart.h" -#include "hooklib/fdshark.h" - -#include "util/dprintf.h" -#include "util/dump.h" - -const char SYNC_BOARD_VER[6] = "190523"; -const char UNIT_BOARD_VER[6] = "190514"; - -static HRESULT touch_handle_irp(struct irp *irp); -static HRESULT touch0_handle_irp_locked(struct irp *irp); -static HRESULT touch1_handle_irp_locked(struct irp *irp); - -static HRESULT touch_req_dispatch(const struct touch_req *req); - -static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side); -static uint8_t calc_checksum(const void *ptr, size_t nbytes); - -static HRESULT touch_handle_get_sync_board_ver(const struct touch_req *req); -static HRESULT touch_handle_next_read(const struct touch_req *req); -static HRESULT touch_handle_get_unit_board_ver(const struct touch_req *req); -static HRESULT touch_handle_mystery1(const struct touch_req *req); -static HRESULT touch_handle_mystery2(const struct touch_req *req); -static HRESULT touch_handle_start_auto_scan(const struct touch_req *req); -static void touch_res_auto_scan(const bool *state); - -uint8_t input_frame_count_0 = 0x7b; -uint8_t input_frame_count_1 = 0x7b; -bool touch0_auto = false; -bool touch1_auto = false; - -static CRITICAL_SECTION touch0_lock; -static struct uart touch0_uart; -static uint8_t touch0_written_bytes[520]; -static uint8_t touch0_readable_bytes[520]; - -static CRITICAL_SECTION touch1_lock; -static struct uart touch1_uart; -static uint8_t touch1_written_bytes[520]; -static uint8_t touch1_readable_bytes[520]; - -HRESULT touch_hook_init(const struct touch_config *cfg) -{ - assert(cfg != NULL); - assert(mercury_dll.touch_init != NULL); - - if (!cfg->enable) { - return S_FALSE; - } - - InitializeCriticalSection(&touch0_lock); - InitializeCriticalSection(&touch1_lock); - dprintf("Wacca touch: Init\n"); - - uart_init(&touch0_uart, 3); - touch0_uart.written.bytes = touch0_written_bytes; - touch0_uart.written.nbytes = sizeof(touch0_written_bytes); - touch0_uart.readable.bytes = touch0_readable_bytes; - touch0_uart.readable.nbytes = sizeof(touch0_readable_bytes); - - uart_init(&touch1_uart, 4); - touch1_uart.written.bytes = touch1_written_bytes; - touch1_uart.written.nbytes = sizeof(touch1_written_bytes); - touch1_uart.readable.bytes = touch1_readable_bytes; - touch1_uart.readable.nbytes = sizeof(touch1_readable_bytes); - - return iohook_push_handler(touch_handle_irp); -} - -static HRESULT touch_handle_irp(struct irp *irp) -{ - HRESULT hr; - - assert(irp != NULL); - - if (uart_match_irp(&touch0_uart, irp)) { - EnterCriticalSection(&touch0_lock); - hr = touch0_handle_irp_locked(irp); - LeaveCriticalSection(&touch0_lock); - } - else if (uart_match_irp(&touch1_uart, irp)) { - EnterCriticalSection(&touch1_lock); - hr = touch1_handle_irp_locked(irp); - LeaveCriticalSection(&touch1_lock); - } - else { - return iohook_invoke_next(irp); - } - - return hr; -} - -static HRESULT touch0_handle_irp_locked(struct irp *irp) -{ - struct touch_req req; - HRESULT hr; - - if (irp->op == IRP_OP_OPEN) { - dprintf("Wacca touch0: Starting backend\n"); - hr = mercury_dll.touch_init(); - - if (FAILED(hr)) { - dprintf("Wacca touch: Backend error: %x\n", (int) hr); - - return hr; - } - } - - hr = uart_handle_irp(&touch0_uart, irp); - - if (FAILED(hr) || irp->op != IRP_OP_WRITE) { - return hr; - } - - for (;;) { -#if 0 - dprintf("TX0 Buffer:\n"); - dump_iobuf(&touch0_uart.written); -#endif - hr = touch_frame_decode(&req, &touch0_uart.written, 0); - - if (hr != S_OK) { - if (FAILED(hr)) { - dprintf("Wacca touch: Deframe error: %x\n", (int) hr); - } - - return hr; - } - - hr = touch_req_dispatch(&req); - - if (FAILED(hr)) { - dprintf("Wacca touch: Processing error: %x\n", (int) hr); - } - - return hr; - } -} - -static HRESULT touch1_handle_irp_locked(struct irp *irp) -{ - struct touch_req req; - HRESULT hr; - - if (irp->op == IRP_OP_OPEN) { - dprintf("Wacca touch1: Starting backend\n"); - hr = mercury_dll.touch_init(); - - if (FAILED(hr)) { - dprintf("Wacca touch: Backend error: %x\n", (int) hr); - - return hr; - } - } - - hr = uart_handle_irp(&touch1_uart, irp); - - if (FAILED(hr) || irp->op != IRP_OP_WRITE) { - return hr; - } - - for (;;) { -#if 0 - dprintf("TX1 Buffer:\n"); - dump_iobuf(&touch1_uart.written); -#endif - - hr = touch_frame_decode(&req, &touch1_uart.written, 1); - - if (hr != S_OK) { - if (FAILED(hr)) { - dprintf("Wacca touch: Deframe error: %x\n", (int) hr); - } - - return hr; - } - - hr = touch_req_dispatch(&req); - - if (FAILED(hr)) { - dprintf("Wacca touch: Processing error: %x\n", (int) hr); - } - - return hr; - } -} - -static HRESULT touch_req_dispatch(const struct touch_req *req) -{ - switch (req->cmd) { - case CMD_GET_SYNC_BOARD_VER: - return touch_handle_get_sync_board_ver(req); - case CMD_NEXT_READ: - return touch_handle_next_read(req); - case CMD_GET_UNIT_BOARD_VER: - return touch_handle_get_unit_board_ver(req); - case CMD_MYSTERY1: - return touch_handle_mystery1(req); - case CMD_MYSTERY2: - return touch_handle_mystery2(req); - case CMD_START_AUTO_SCAN: - return touch_handle_start_auto_scan(req); - case CMD_BEGIN_WRITE: - dprintf("Wacca touch: Begin write for side %d\n", req->side); - return S_OK; - case CMD_NEXT_WRITE: - dprintf("Wacca touch: continue write for side %d\n", req->side); - return S_OK; - default: - dprintf("Wacca touch: Unhandled command %02x\n", req->cmd); - return S_OK; - } -} - -static HRESULT touch_handle_get_sync_board_ver(const struct touch_req *req) -{ - struct touch_resp_get_sync_board_ver resp; - HRESULT hr; - memset(&resp, 0, sizeof(resp)); - dprintf("Wacca Touch%d: Get sync board version\n", req->side); - - resp.cmd = 0xa0; - memcpy(resp.version, SYNC_BOARD_VER, sizeof(SYNC_BOARD_VER)); - resp.checksum = 0; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - if (req->side == 0) { - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - } - else { - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - } - - return hr; -} - -static HRESULT touch_handle_next_read(const struct touch_req *req) -{ - struct touch_resp_startup resp; - HRESULT hr; - char *rev; - memset(&resp, 0, sizeof(resp)); - dprintf("Wacca Touch%d: Read section %2hx\n", req->side, req->data[2]); - - - switch (req->data[2]) { - // These can be found in the config file - case 0x30: - rev = " 0 0 1 2 3 4 5 15 15 15 15 15 15 11 11 11"; - break; - case 0x31: - rev = " 11 11 11 128 103 103 115 138 127 103 105 111 126 113 95 100"; - break; - case 0x33: - rev = " 101 115 98 86 76 67 68 48 117 0 82 154 0 6 35 4"; - break; - default: - dprintf("Wacca touch: BAD READ REQUEST %2hx\n", req->data[2]); - return 1; - } - - memcpy(resp.data, rev, 80 * sizeof(char)); - resp.checksum = 0; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - if (req->side == 0) { - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - } - else { - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - } - return hr; -} - -static HRESULT touch_handle_get_unit_board_ver(const struct touch_req *req) -{ - struct touch_resp_get_unit_board_ver resp; - HRESULT hr; - memset(&resp, 0, sizeof(resp)); - dprintf("Wacca Touch%d: get unit board version\n", req->side); - - memset(resp.version, 0, sizeof(resp.version)); - memcpy(resp.version, SYNC_BOARD_VER, sizeof(SYNC_BOARD_VER)); - - for (int i = 0; i < 6; i++ ) - memcpy(&resp.version[7 + (6 * i)], UNIT_BOARD_VER, sizeof(UNIT_BOARD_VER)); - - resp.cmd = 0xa8; - resp.checksum = 0; - - if (req->side == 0) { - resp.version[6] = 'R'; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - #if 0 - for (int i = 0; i < sizeof(resp.version); i++) { - dprintf("0x%02x ", resp.version[i]); - } - dprintf("\n"); - #endif - - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - } - else { - resp.version[6] = 'L'; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - #if 0 - for (int i = 0; i < sizeof(resp.version); i++) { - dprintf("0x%02x ", resp.version[i]); - } - dprintf("\n"); - #endif - - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - } - - return hr; -} - -static HRESULT touch_handle_mystery1(const struct touch_req *req) -{ - struct touch_resp_mystery1 resp; - HRESULT hr; - memset(&resp, 0, sizeof(resp)); - dprintf("Wacca Touch%d: Command A2\n", req->side); - - resp.cmd = 0xa2; - resp.data = 0x3f; - resp.checksum = 0; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - if (req->side == 0) { - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - } - else { - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - } - return hr; -} - -static HRESULT touch_handle_mystery2(const struct touch_req *req) -{ - struct touch_resp_mystery2 resp; - HRESULT hr; - memset(&resp, 0, sizeof(resp)); - dprintf("Wacca Touch%d: Command 94\n", req->side); - - resp.cmd = 0x94; - resp.data = 0; - resp.checksum = 0; - resp.checksum = calc_checksum(&resp, sizeof(resp)); - - if (req->side == 0) { - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - } - else { - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - } - return hr; -} - -static HRESULT touch_handle_start_auto_scan(const struct touch_req *req) -{ - struct touch_resp_start_auto resp; - HRESULT hr; - uint8_t data1[24] = { 0 }; - // Unsure what this does. It seems to change every request on a real board, - // but the game doesn't seem to mind that it's the same - uint8_t data2[9] = { 0x0d, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00 }; - - dprintf("Wacca Touch%d: Start Auto", req->side); - - #if 0 - for (int i = 0; i < req->data_length; i++) - dprintf("0x%02x ", req->data[i]); - #endif - dprintf("\n"); - - resp.cmd = 0x9c; - resp.data = 0; - resp.checksum = 0x49; - - resp.frame.cmd= 0x81; - memcpy(resp.frame.data1, data1, sizeof(data1)); - memcpy(resp.frame.data2, data2, sizeof(data2)); - resp.frame.checksum = 0; - resp.frame.checksum = calc_checksum(&resp.frame, sizeof(resp.frame)); - - if (req->side == 0) { - resp.frame.count = input_frame_count_0++; - hr = iobuf_write(&touch0_uart.readable, &resp, sizeof(resp)); - touch0_auto = true; - } - else { - resp.frame.count = input_frame_count_1++; - hr = iobuf_write(&touch1_uart.readable, &resp, sizeof(resp)); - touch1_auto = true; - } - - mercury_dll.touch_start(touch_res_auto_scan); - return hr; -} - -static void touch_res_auto_scan(const bool *state) -{ - struct touch_input_frame frame0; - struct touch_input_frame frame1; - memset(&frame0, 0, sizeof(frame0)); - memset(&frame1, 0, sizeof(frame1)); - uint8_t dataR[24] = { 0 }; - uint8_t dataL[24] = { 0 }; - // this changes every input on a real board but - // the game doesn't seem to care about it... - uint8_t data2[9] = { 0x0d, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00 }; - uint8_t counter = 0; - - frame0.cmd = 0x81; - frame0.count = input_frame_count_0++; - input_frame_count_0 %= 0x7f; - - frame1.cmd = 0x81; - frame1.count = input_frame_count_1++; - input_frame_count_1 %= 0x7f; - - for (int i = 0; i < 24; i++) { - for (int j = 0; j < 5; j++) { - if (state[counter]) { - dataR[i] |= (1 << j); - } - if (state[counter+120]) { - dataL[i] |= (1 << j); - } - counter++; - } - } - - memcpy(frame0.data1, dataR, sizeof(dataR)); - memcpy(frame0.data2, data2, sizeof(data2)); - - memcpy(frame1.data1, dataL, sizeof(dataL)); - memcpy(frame1.data2, data2, sizeof(data2)); - - frame0.checksum = 0; - frame0.checksum = calc_checksum(&frame0, sizeof(frame0)); - - frame1.checksum = 0; - frame1.checksum = calc_checksum(&frame1, sizeof(frame1)); - - if (touch0_auto) { - //dprintf("Wacca touch: Touch0 auto frame #%2hx sent\n", frame0.count); - EnterCriticalSection(&touch0_lock); - iobuf_write(&touch0_uart.readable, &frame0, sizeof(frame0)); - LeaveCriticalSection(&touch0_lock); - } - - if (touch1_auto) { - //dprintf("Wacca touch: Touch1 auto frame #%2hx sent\n", frame0.count); - EnterCriticalSection(&touch1_lock); - iobuf_write(&touch1_uart.readable, &frame1, sizeof(frame1)); - LeaveCriticalSection(&touch1_lock); - } -} - -/* Decodes the response into a struct that's easier to work with. */ -static HRESULT touch_frame_decode(struct touch_req *dest, struct iobuf *iobuf, int side) -{ - dest->side = side; - dest->cmd = iobuf->bytes[0]; - iobuf->pos--; - dest->data_length = iobuf->pos; - - if (dest->data_length > 0) { - for (int i = 1; i < dest->data_length; i++) { - dest->data[i-1] = iobuf->bytes[i]; - } - } - iobuf->pos -= dest->data_length; - - return S_OK; -} - -/* The last byte of every response is a checksum. - * This checksum is calculated by bitwise XORing - * every byte in the response, then dropping the MSB. - * Thanks the CrazyRedMachine for figuring that out!! - */ -static uint8_t calc_checksum(const void *ptr, size_t nbytes) -{ - const uint8_t *src; - uint8_t checksum = 0; - - src = ptr; - - for (size_t i = 0; i < nbytes; i++) { - //dprintf("Wacca touch: Calculating %2hx\n", src[i]); - checksum = checksum^(src[i]); - } - //dprintf("Wacca touch: Checksum is %2hx\n", checksum&0x7f); - return checksum&0x7f; -} diff --git a/mercuryhook/touch.h b/mercuryhook/touch.h deleted file mode 100644 index cc665c8..0000000 --- a/mercuryhook/touch.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include - -#include - -struct touch_config { - bool enable; -}; - -enum touch_cmd { - CMD_GET_SYNC_BOARD_VER = 0xa0, - CMD_NEXT_READ = 0x72, - CMD_GET_UNIT_BOARD_VER = 0xa8, - CMD_MYSTERY1 = 0xa2, - CMD_MYSTERY2 = 0x94, - CMD_START_AUTO_SCAN = 0xc9, - CMD_BEGIN_WRITE = 0x77, - CMD_NEXT_WRITE = 0x20 -}; - -struct touch_req { - uint8_t side; // COM3 or COM4 - uint8_t cmd; // First byte is the command byte - uint8_t data[256]; // rest of the data goes here - uint8_t data_length; // Size of the data including command byte -}; - -struct touch_input_frame { - uint8_t cmd; - uint8_t data1[24]; - uint8_t data2[9]; - uint8_t count; - uint8_t checksum; -}; - -struct touch_resp_get_sync_board_ver { - uint8_t cmd; - char version[6]; - uint8_t checksum; -}; - -struct touch_resp_startup { - char data[80]; - uint8_t checksum; -}; - -struct touch_resp_get_unit_board_ver { - uint8_t cmd; - uint8_t version[43]; - uint8_t checksum; -}; - -struct touch_resp_mystery1 { - uint8_t cmd; - uint8_t data; - uint8_t checksum; -}; - -struct touch_resp_mystery2 { - uint8_t cmd; - uint8_t data; - uint8_t checksum; -}; - -struct touch_resp_start_auto { - uint8_t cmd; - uint8_t data; - uint8_t checksum; - struct touch_input_frame frame; -}; - -HRESULT touch_hook_init(const struct touch_config *cfg); diff --git a/mercuryio/config.c b/mercuryio/config.c deleted file mode 100644 index f3c8e54..0000000 --- a/mercuryio/config.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include -#include -#include - -#include "mercuryio/config.h" - -static const int mercury_io_default_cells[] = { - '1','1','1','2','2','2','3','3','3','4','4','4','5','5','5','6','6','6','7','7','7','8','8','8','9','9','9','0','0','0', - '1','1','1','2','2','2','3','3','3','4','4','4','5','5','5','6','6','6','7','7','7','8','8','8','9','9','9','0','0','0', - 'Q','Q','Q','W','W','W','E','E','E','R','R','R','T','T','T','Y','Y','Y','U','U','U','I','I','I','O','O','O','P','P','P', - 'Q','Q','Q','W','W','W','E','E','E','R','R','R','T','T','T','Y','Y','Y','U','U','U','I','I','I','O','O','O','P','P','P', - 'A','A','A','S','S','S','D','D','D','F','F','F','G','G','G','H','H','H','J','J','J','K','K','K','L','L','L',VK_OEM_1,VK_OEM_1,VK_OEM_1, - 'A','A','A','S','S','S','D','D','D','F','F','F','G','G','G','H','H','H','J','J','J','K','K','K','L','L','L',VK_OEM_1,VK_OEM_1,VK_OEM_1, - 'Z','Z','Z','X','X','X','C','C','C','V','V','V','B','B','B','N','N','N','M','M','M',VK_OEM_COMMA,VK_OEM_COMMA,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_PERIOD,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_2,VK_OEM_2, - 'Z','Z','Z','X','X','X','C','C','C','V','V','V','B','B','B','N','N','N','M','M','M',VK_OEM_COMMA,VK_OEM_COMMA,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_PERIOD,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_2,VK_OEM_2, -}; - -void mercury_io_config_load( - struct mercury_io_config *cfg, - const wchar_t *filename) -{ - wchar_t key[240]; - int i; - - assert(cfg != NULL); - assert(filename != NULL); - - cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", 0x2D, filename); - cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", 0x2E, filename); - cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", 0x24, filename); - cfg->vk_vol_up = GetPrivateProfileIntW(L"io4", L"volup", 0x26, filename); - cfg->vk_vol_down = GetPrivateProfileIntW(L"io4", L"voldown", 0x28, filename); - - for (i = 0 ; i < 240 ; i++) { - swprintf_s(key, _countof(key), L"cell%i", i + 1); - cfg->vk_cell[i] = GetPrivateProfileIntW( - L"touch", - key, - mercury_io_default_cells[i], - filename); - } -} diff --git a/mercuryio/config.h b/mercuryio/config.h deleted file mode 100644 index c925764..0000000 --- a/mercuryio/config.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include - -#include - -struct mercury_io_config { - uint8_t vk_test; - uint8_t vk_service; - uint8_t vk_coin; - uint8_t vk_vol_up; - uint8_t vk_vol_down; - uint8_t vk_cell[240]; -}; - -void mercury_io_config_load( - struct mercury_io_config *cfg, - const wchar_t *filename); diff --git a/mercuryio/mercuryio.c b/mercuryio/mercuryio.c deleted file mode 100644 index 96d4ac0..0000000 --- a/mercuryio/mercuryio.c +++ /dev/null @@ -1,121 +0,0 @@ -#include - -#include -#include -#include - -#include "mercuryio/mercuryio.h" -#include "mercuryio/config.h" -#include "mercuryhook/elisabeth.h" - -static unsigned int __stdcall mercury_io_touch_thread_proc(void *ctx); - -static uint8_t mercury_opbtn; -static uint8_t mercury_gamebtn; -static struct mercury_io_config mercury_io_cfg; -static bool mercury_io_touch_stop_flag; -static HANDLE mercury_io_touch_thread; - -uint16_t mercury_io_get_api_version(void) -{ - return 0x0100; -} - -HRESULT mercury_io_init(void) -{ - mercury_io_config_load(&mercury_io_cfg, L".\\taitools.ini"); - - return S_OK; -} - -HRESULT mercury_io_poll(void) -{ - mercury_opbtn = 0; - mercury_gamebtn = 0; - - if (GetAsyncKeyState(mercury_io_cfg.vk_test)) { - mercury_opbtn |= MERCURY_IO_OPBTN_TEST; - } - - if (GetAsyncKeyState(mercury_io_cfg.vk_service)) { - mercury_opbtn |= MERCURY_IO_OPBTN_SERVICE; - } - - if (GetAsyncKeyState(mercury_io_cfg.vk_coin)) { - mercury_opbtn |= MERCURY_IO_OPBTN_COIN; - } - - if (GetAsyncKeyState(mercury_io_cfg.vk_vol_up)) { - mercury_gamebtn |= MERCURY_IO_GAMEBTN_VOL_UP; - } - - if (GetAsyncKeyState(mercury_io_cfg.vk_vol_down)) { - mercury_gamebtn |= MERCURY_IO_GAMEBTN_VOL_DOWN; - } - - return S_OK; -} - -void mercury_io_get_opbtns(uint8_t *opbtn) -{ - if (opbtn != NULL) { - *opbtn = mercury_opbtn; - } -} - -void mercury_io_get_gamebtns(uint8_t *gamebtn) -{ - if (gamebtn != NULL) { - *gamebtn = mercury_gamebtn; - } -} - -HRESULT mercury_io_touch_init(void) -{ - return S_OK; -} - -void mercury_io_touch_start(mercury_io_touch_callback_t callback) -{ - if (mercury_io_touch_thread != NULL) { - return; - } - - mercury_io_touch_thread = (HANDLE) _beginthreadex( - NULL, - 0, - mercury_io_touch_thread_proc, - callback, - 0, - NULL - ); -} - -void mercury_io_touch_set_leds(struct led_data data) -{ - -} - -static unsigned int __stdcall mercury_io_touch_thread_proc(void *ctx) -{ - mercury_io_touch_callback_t callback; - bool cellPressed[240]; - size_t i; - - callback = ctx; - - while (!mercury_io_touch_stop_flag) { - for (i = 0 ; i < _countof(cellPressed) ; i++) { - if (GetAsyncKeyState(mercury_io_cfg.vk_cell[i])) { - cellPressed[i] = true; - } else { - cellPressed[i] = false; - } - } - - callback(cellPressed); - Sleep(1); - } - - return 0; -} diff --git a/mercuryio/mercuryio.def b/mercuryio/mercuryio.def deleted file mode 100644 index 167d1cf..0000000 --- a/mercuryio/mercuryio.def +++ /dev/null @@ -1,11 +0,0 @@ -LIBRARY mercuryio - -EXPORTS - mercury_io_get_api_version - mercury_io_init - mercury_io_poll - mercury_io_get_opbtns - mercury_io_get_gamebtns - mercury_io_touch_init - mercury_io_touch_start - mercury_io_touch_set_leds \ No newline at end of file diff --git a/mercuryio/mercuryio.h b/mercuryio/mercuryio.h deleted file mode 100644 index 4d029ca..0000000 --- a/mercuryio/mercuryio.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "mercuryhook/elisabeth.h" - -enum { - MERCURY_IO_OPBTN_TEST = 0x01, - MERCURY_IO_OPBTN_SERVICE = 0x02, - MERCURY_IO_OPBTN_COIN = 0x04, -}; - -enum { - MERCURY_IO_GAMEBTN_VOL_UP = 0x01, - MERCURY_IO_GAMEBTN_VOL_DOWN = 0x02, -}; - -typedef void (*mercury_io_touch_callback_t)(const bool *state); -/* Get the version of the Wacca 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 mercury_io_get_api_version(void); - -/* Initialize the IO DLL. This is the second function that will be called on - your DLL, after mercury_io_get_api_version. - - All subsequent calls to this API may originate from arbitrary threads. - - Minimum API version: 0x0100 */ - -HRESULT mercury_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 mercury_io_poll(void); - -/* Get the state of the cabinet's operator buttons as of the last poll. See - MERCURY_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 mercury_io_get_opbtns(uint8_t *opbtn); - -/* Get the state of the cabinet's gameplay buttons as of the last poll. See - MERCURY_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into - a left hand side set of inputs and a right hand side set of inputs: the bit - mappings are the same in both cases. - - All buttons are active-high, even though some buttons' electrical signals - on a real cabinet are active-low. - - Minimum API version: 0x0100 */ - -void mercury_io_get_gamebtns(uint8_t *gamebtn); - -HRESULT mercury_io_touch_init(void); - -void mercury_io_touch_start(mercury_io_touch_callback_t callback); - -void mercury_io_touch_set_leds(struct led_data data); diff --git a/mercuryio/meson.build b/mercuryio/meson.build deleted file mode 100644 index 2970fa9..0000000 --- a/mercuryio/meson.build +++ /dev/null @@ -1,13 +0,0 @@ -mercuryio_lib = static_library( - 'mercuryio', - name_prefix : '', - include_directories : inc, - implicit_include_directories : false, - c_pch : '../precompiled.h', - sources : [ - 'mercuryio.c', - 'mercuryio.h', - 'config.c', - 'config.h', - ], -) \ No newline at end of file diff --git a/meson.build b/meson.build index c28fe54..efd9209 100644 --- a/meson.build +++ b/meson.build @@ -53,9 +53,7 @@ subdir('util') subdir('gfxhook') -subdir('mu3io') -subdir('mercuryio') +subdir('sivaio') subdir('minihook') -subdir('mu3hook') -subdir('mercuryhook') +subdir('sivahook') diff --git a/mu3hook/config.h b/mu3hook/config.h deleted file mode 100644 index 58af239..0000000 --- a/mu3hook/config.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -#include "board/config.h" - -#include "gfxhook/gfx.h" - -#include "hooklib/dvd.h" - -#include "mu3hook/mu3-dll.h" - -#include "platform/config.h" - -struct mu3_hook_config { - struct platform_config platform; - struct aime_config aime; - struct dvd_config dvd; - struct io4_config io4; - struct gfx_config gfx; - struct mu3_dll_config dll; -}; - -void mu3_dll_config_load( - struct mu3_dll_config *cfg, - const wchar_t *filename); - -void mu3_hook_config_load( - struct mu3_hook_config *cfg, - const wchar_t *filename); diff --git a/mu3hook/dllmain.c b/mu3hook/dllmain.c deleted file mode 100644 index 23ded9d..0000000 --- a/mu3hook/dllmain.c +++ /dev/null @@ -1,126 +0,0 @@ -#include - -#include - -#include "board/io4.h" -#include "board/sg-reader.h" -#include "board/vfd.h" - -#include "gfxhook/d3d9.h" -#include "gfxhook/d3d11.h" -#include "gfxhook/dxgi.h" -#include "gfxhook/gfx.h" - -#include "hook/process.h" - -#include "hooklib/dvd.h" -#include "hooklib/serial.h" -#include "hooklib/spike.h" - -#include "mu3hook/config.h" -#include "mu3hook/io4.h" -#include "mu3hook/mu3-dll.h" -#include "mu3hook/unity.h" - -#include "platform/platform.h" - -#include "util/dprintf.h" - -static HMODULE mu3_hook_mod; -static process_entry_t mu3_startup; -static struct mu3_hook_config mu3_hook_cfg; - -static DWORD CALLBACK mu3_pre_startup(void) -{ - HRESULT hr; - - dprintf("--- Begin mu3_pre_startup ---\n"); - - /* Load config */ - - mu3_hook_config_load(&mu3_hook_cfg, L".\\taitools.ini"); - - /* Hook Win32 APIs */ - - dvd_hook_init(&mu3_hook_cfg.dvd, mu3_hook_mod); - gfx_hook_init(&mu3_hook_cfg.gfx); - gfx_d3d9_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); - gfx_d3d11_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); - gfx_dxgi_hook_init(&mu3_hook_cfg.gfx, mu3_hook_mod); - serial_hook_init(); - - /* Initialize emulation hooks */ - - hr = platform_hook_init( - &mu3_hook_cfg.platform, - "SDDT", - "ACA1", - mu3_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = sg_reader_hook_init(&mu3_hook_cfg.aime, 1, mu3_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = vfd_hook_init(2); - - if (FAILED(hr)) { - goto fail; - } - - hr = mu3_dll_init(&mu3_hook_cfg.dll, mu3_hook_mod); - - if (FAILED(hr)) { - goto fail; - } - - hr = mu3_io4_hook_init(&mu3_hook_cfg.io4); - - if (FAILED(hr)) { - goto fail; - } - - /* Initialize Unity native plugin DLL hooks - - There seems to be an issue with other DLL hooks if `LoadLibraryW` is - hooked earlier in the `mu3hook` initialization. */ - - unity_hook_init(); - - /* Initialize debug helpers */ - - spike_hook_init(L".\\taitools.ini"); - - dprintf("--- End mu3_pre_startup ---\n"); - - /* Jump to EXE start address */ - - return mu3_startup(); - -fail: - ExitProcess(EXIT_FAILURE); -} - -BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) -{ - HRESULT hr; - - if (cause != DLL_PROCESS_ATTACH) { - return TRUE; - } - - mu3_hook_mod = mod; - - hr = process_hijack_startup(mu3_pre_startup, &mu3_startup); - - if (!SUCCEEDED(hr)) { - dprintf("Failed to hijack process startup: %x\n", (int) hr); - } - - return SUCCEEDED(hr); -} diff --git a/mu3hook/io4.c b/mu3hook/io4.c deleted file mode 100644 index 7edcb0c..0000000 --- a/mu3hook/io4.c +++ /dev/null @@ -1,120 +0,0 @@ -#include - -#include -#include -#include - -#include "board/io4.h" - -#include "mu3hook/mu3-dll.h" - -#include "util/dprintf.h" - -static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state); - -static const struct io4_ops mu3_io4_ops = { - .poll = mu3_io4_poll, -}; - -HRESULT mu3_io4_hook_init(const struct io4_config *cfg) -{ - HRESULT hr; - - assert(mu3_dll.init != NULL); - - hr = io4_hook_init(cfg, &mu3_io4_ops, NULL); - - if (FAILED(hr)) { - return hr; - } - - return mu3_dll.init(); -} - -static HRESULT mu3_io4_poll(void *ctx, struct io4_state *state) -{ - uint8_t opbtn; - uint8_t left; - uint8_t right; - int16_t lever; - HRESULT hr; - - assert(mu3_dll.poll != NULL); - assert(mu3_dll.get_opbtns != NULL); - assert(mu3_dll.get_gamebtns != NULL); - assert(mu3_dll.get_lever != NULL); - - memset(state, 0, sizeof(*state)); - - hr = mu3_dll.poll(); - - if (FAILED(hr)) { - return hr; - } - - opbtn = 0; - left = 0; - right = 0; - lever = 0; - - mu3_dll.get_opbtns(&opbtn); - mu3_dll.get_gamebtns(&left, &right); - mu3_dll.get_lever(&lever); - - if (opbtn & MU3_IO_OPBTN_TEST) { - state->buttons[0] |= IO4_BUTTON_TEST; - } - - if (opbtn & MU3_IO_OPBTN_SERVICE) { - state->buttons[0] |= IO4_BUTTON_SERVICE; - } - - if (left & MU3_IO_GAMEBTN_1) { - state->buttons[0] |= 1 << 0; - } - - if (left & MU3_IO_GAMEBTN_2) { - state->buttons[0] |= 1 << 5; - } - - if (left & MU3_IO_GAMEBTN_3) { - state->buttons[0] |= 1 << 4; - } - - if (right & MU3_IO_GAMEBTN_1) { - state->buttons[0] |= 1 << 1; - } - - if (right & MU3_IO_GAMEBTN_2) { - state->buttons[1] |= 1 << 0; - } - - if (right & MU3_IO_GAMEBTN_3) { - state->buttons[0] |= 1 << 15; - } - - if (left & MU3_IO_GAMEBTN_MENU) { - state->buttons[1] |= 1 << 14; - } - - if (right & MU3_IO_GAMEBTN_MENU) { - state->buttons[0] |= 1 << 13; - } - - if (!(left & MU3_IO_GAMEBTN_SIDE)) { - state->buttons[1] |= 1 << 15; /* L-Side, active-low */ - } - - if (!(right & MU3_IO_GAMEBTN_SIDE)) { - state->buttons[0] |= 1 << 14; /* R-Side, active-low */ - } - - /* Lever increases right-to-left, not left-to-right. - - Use 0x7FFF as the center point instead of 0x8000; the latter would - overflow when the lever pos is INT16_MIN. */ - - state->adcs[0] = 0x7FFF - lever; - - return S_OK; -} diff --git a/mu3hook/io4.h b/mu3hook/io4.h deleted file mode 100644 index acb53b3..0000000 --- a/mu3hook/io4.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#include "board/io4.h" - -HRESULT mu3_io4_hook_init(const struct io4_config *cfg); diff --git a/mu3hook/mu3-dll.c b/mu3hook/mu3-dll.c deleted file mode 100644 index 84e785c..0000000 --- a/mu3hook/mu3-dll.c +++ /dev/null @@ -1,112 +0,0 @@ -#include - -#include -#include - -#include "mu3hook/mu3-dll.h" - -#include "util/dll-bind.h" -#include "util/dprintf.h" - -const struct dll_bind_sym mu3_dll_syms[] = { - { - .sym = "mu3_io_init", - .off = offsetof(struct mu3_dll, init), - }, { - .sym = "mu3_io_poll", - .off = offsetof(struct mu3_dll, poll), - }, { - .sym = "mu3_io_get_opbtns", - .off = offsetof(struct mu3_dll, get_opbtns), - }, { - .sym = "mu3_io_get_gamebtns", - .off = offsetof(struct mu3_dll, get_gamebtns), - }, { - .sym = "mu3_io_get_lever", - .off = offsetof(struct mu3_dll, get_lever), - } -}; - -struct mu3_dll mu3_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 mu3_dll_init(const struct mu3_dll_config *cfg, HINSTANCE self) -{ - uint16_t (*get_api_version)(void); - const struct dll_bind_sym *sym; - HINSTANCE owned; - HINSTANCE src; - HRESULT hr; - - assert(cfg != NULL); - assert(self != NULL); - - if (cfg->path[0] != L'\0') { - owned = LoadLibraryW(cfg->path); - - if (owned == NULL) { - hr = HRESULT_FROM_WIN32(GetLastError()); - dprintf("Ongeki IO: Failed to load IO DLL: %lx: %S\n", - hr, - cfg->path); - - goto end; - } - - dprintf("Ongeki IO: Using custom IO DLL: %S\n", cfg->path); - src = owned; - } else { - owned = NULL; - src = self; - } - - get_api_version = (void *) GetProcAddress(src, "mu3_io_get_api_version"); - - if (get_api_version != NULL) { - mu3_dll.api_version = get_api_version(); - } else { - mu3_dll.api_version = 0x0100; - dprintf("Custom IO DLL does not expose mu3_io_get_api_version, " - "assuming API version 1.0.\n" - "Please ask the developer to update their DLL.\n"); - } - - if (mu3_dll.api_version >= 0x0200) { - hr = E_NOTIMPL; - dprintf("Ongeki IO: Custom IO DLL implements an unsupported " - "API version (%#04x). Please update Taitools.\n", - mu3_dll.api_version); - - goto end; - } - - sym = mu3_dll_syms; - hr = dll_bind(&mu3_dll, src, &sym, _countof(mu3_dll_syms)); - - if (FAILED(hr)) { - if (src != self) { - dprintf("Ongeki IO: Custom IO DLL does not provide function " - "\"%s\". Please contact your IO DLL's developer for " - "further assistance.\n", - sym->sym); - - goto end; - } else { - dprintf("Internal error: could not reflect \"%s\"\n", sym->sym); - } - } - - owned = NULL; - -end: - if (owned != NULL) { - FreeLibrary(owned); - } - - return hr; -} diff --git a/mu3hook/mu3-dll.h b/mu3hook/mu3-dll.h deleted file mode 100644 index 41f280f..0000000 --- a/mu3hook/mu3-dll.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -#include "mu3io/mu3io.h" - -struct mu3_dll { - uint16_t api_version; - HRESULT (*init)(void); - HRESULT (*poll)(void); - void (*get_opbtns)(uint8_t *opbtn); - void (*get_gamebtns)(uint8_t *left, uint8_t *right); - void (*get_lever)(int16_t *pos); -}; - -struct mu3_dll_config { - wchar_t path[MAX_PATH]; -}; - -extern struct mu3_dll mu3_dll; - -HRESULT mu3_dll_init(const struct mu3_dll_config *cfg, HINSTANCE self); diff --git a/mu3hook/mu3hook.def b/mu3hook/mu3hook.def deleted file mode 100644 index d90abd5..0000000 --- a/mu3hook/mu3hook.def +++ /dev/null @@ -1,25 +0,0 @@ -LIBRARY mu3hook - -EXPORTS - CreateDXGIFactory - CreateDXGIFactory1 - CreateDXGIFactory2 - D3D11CreateDevice - D3D11CreateDeviceAndSwapChain - Direct3DCreate9 - aime_io_get_api_version - aime_io_init - aime_io_led_set_color - aime_io_nfc_get_aime_id - aime_io_nfc_get_felica_id - aime_io_nfc_poll - amDllVideoClose @2 - amDllVideoGetVBiosVersion @4 - amDllVideoOpen @1 - amDllVideoSetResolution @3 - mu3_io_get_api_version - mu3_io_get_gamebtns - mu3_io_get_lever - mu3_io_get_opbtns - mu3_io_init - mu3_io_poll diff --git a/mu3io/mu3io.c b/mu3io/mu3io.c deleted file mode 100644 index 0bbd37f..0000000 --- a/mu3io/mu3io.c +++ /dev/null @@ -1,148 +0,0 @@ -#include -#include - -#include -#include - -#include "mu3io/mu3io.h" - -static uint8_t mu3_opbtn; -static uint8_t mu3_left_btn; -static uint8_t mu3_right_btn; -static int16_t mu3_lever_pos; -static int16_t mu3_lever_xpos; - -uint16_t mu3_io_get_api_version(void) -{ - return 0x0100; -} - -HRESULT mu3_io_init(void) -{ - return S_OK; -} - -HRESULT mu3_io_poll(void) -{ - int lever; - int xlever; - XINPUT_STATE xi; - WORD xb; - - mu3_opbtn = 0; - mu3_left_btn = 0; - mu3_right_btn = 0; - - if (GetAsyncKeyState('1') & 0x8000) { - mu3_opbtn |= MU3_IO_OPBTN_TEST; - } - - if (GetAsyncKeyState('2') & 0x8000) { - mu3_opbtn |= MU3_IO_OPBTN_SERVICE; - } - - memset(&xi, 0, sizeof(xi)); - XInputGetState(0, &xi); - xb = xi.Gamepad.wButtons; - - if (xb & XINPUT_GAMEPAD_DPAD_LEFT) { - mu3_left_btn |= MU3_IO_GAMEBTN_1; - } - - if (xb & XINPUT_GAMEPAD_DPAD_UP) { - mu3_left_btn |= MU3_IO_GAMEBTN_2; - } - - if (xb & XINPUT_GAMEPAD_DPAD_RIGHT) { - mu3_left_btn |= MU3_IO_GAMEBTN_3; - } - - if (xb & XINPUT_GAMEPAD_X) { - mu3_right_btn |= MU3_IO_GAMEBTN_1; - } - - if (xb & XINPUT_GAMEPAD_Y) { - mu3_right_btn |= MU3_IO_GAMEBTN_2; - } - - if (xb & XINPUT_GAMEPAD_B) { - mu3_right_btn |= MU3_IO_GAMEBTN_3; - } - - if (xb & XINPUT_GAMEPAD_BACK) { - mu3_left_btn |= MU3_IO_GAMEBTN_MENU; - } - - if (xb & XINPUT_GAMEPAD_START) { - mu3_right_btn |= MU3_IO_GAMEBTN_MENU; - } - - if (xb & XINPUT_GAMEPAD_LEFT_SHOULDER) { - mu3_left_btn |= MU3_IO_GAMEBTN_SIDE; - } - - if (xb & XINPUT_GAMEPAD_RIGHT_SHOULDER) { - mu3_right_btn |= MU3_IO_GAMEBTN_SIDE; - } - - lever = mu3_lever_pos; - - if (abs(xi.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) { - lever += xi.Gamepad.sThumbLX / 24; - } - - if (abs(xi.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) { - lever += xi.Gamepad.sThumbRX / 24; - } - - if (lever < INT16_MIN) { - lever = INT16_MIN; - } - - if (lever > INT16_MAX) { - lever = INT16_MAX; - } - - mu3_lever_pos = lever; - - xlever = mu3_lever_pos - - xi.Gamepad.bLeftTrigger * 64 - + xi.Gamepad.bRightTrigger * 64; - - if (xlever < INT16_MIN) { - xlever = INT16_MIN; - } - - if (xlever > INT16_MAX) { - xlever = INT16_MAX; - } - - mu3_lever_xpos = xlever; - - return S_OK; -} - -void mu3_io_get_opbtns(uint8_t *opbtn) -{ - if (opbtn != NULL) { - *opbtn = mu3_opbtn; - } -} - -void mu3_io_get_gamebtns(uint8_t *left, uint8_t *right) -{ - if (left != NULL) { - *left = mu3_left_btn; - } - - if (right != NULL ){ - *right = mu3_right_btn; - } -} - -void mu3_io_get_lever(int16_t *pos) -{ - if (pos != NULL) { - *pos = mu3_lever_xpos; - } -} diff --git a/mu3io/mu3io.h b/mu3io/mu3io.h deleted file mode 100644 index d46a475..0000000 --- a/mu3io/mu3io.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include - -#include - -enum { - MU3_IO_OPBTN_TEST = 0x01, - MU3_IO_OPBTN_SERVICE = 0x02, -}; - -enum { - MU3_IO_GAMEBTN_1 = 0x01, - MU3_IO_GAMEBTN_2 = 0x02, - MU3_IO_GAMEBTN_3 = 0x04, - MU3_IO_GAMEBTN_SIDE = 0x08, - MU3_IO_GAMEBTN_MENU = 0x10, -}; - -/* Get the version of the Ongeki IO API that this DLL supports. This - function should return a positive 16-bit integer, where the high byte is - the major version and the low byte is the minor version (as defined by the - Semantic Versioning standard). - - The latest API version as of this writing is 0x0100. */ - -uint16_t mu3_io_get_api_version(void); - -/* Initialize the IO DLL. This is the second function that will be called on - your DLL, after mu3_io_get_api_version. - - All subsequent calls to this API may originate from arbitrary threads. - - Minimum API version: 0x0100 */ - -HRESULT mu3_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 mu3_io_poll(void); - -/* Get the state of the cabinet's operator buttons as of the last poll. See - MU3_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 mu3_io_get_opbtns(uint8_t *opbtn); - -/* Get the state of the cabinet's gameplay buttons as of the last poll. See - MU3_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into - a left hand side set of inputs and a right hand side set of inputs: the bit - mappings are the same in both cases. - - All buttons are active-high, even though some buttons' electrical signals - on a real cabinet are active-low. - - Minimum API version: 0x0100 */ - -void mu3_io_get_gamebtns(uint8_t *left, uint8_t *right); - -/* Get the position of the cabinet lever as of the last poll. The center - position should be equal to or close to zero. - - The operator will be required to calibrate the lever's range of motion on - first power-on, so the lever position reported through this API does not - need to perfectly centered or cover every single position value possible, - but it should be reasonably close in order to make things easier for the - operator. - - The calibration screen displays the leftmost and rightmost position signal - returned from the cabinet's ADC encoder as a pair of raw two's complement - hexadecimal values. On a real cabinet these leftmost and rightmost - positions are somewhere around 0xB000 and 0x5000 respectively (remember - that negative values i.e. left positions have a high most-significant bit), - although these values can easily vary by +/- 0x1000 across different - cabinets. - - Minimum API version: 0x0100 */ - -void mu3_io_get_lever(int16_t *pos); diff --git a/pki/billing.pub b/pki/billing.pub new file mode 100644 index 0000000..e69de29 diff --git a/pki/ca.crt b/pki/ca.crt new file mode 100644 index 0000000..e69de29 diff --git a/platform/platform.h b/platform/platform.h index 65b1898..4ce9e7d 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -22,6 +22,5 @@ struct platform_config { HRESULT platform_hook_init( const struct platform_config *cfg, - const char *game_id, - const char *platform_id, + const uint32_t game_id, HMODULE redir_mod); diff --git a/platform/syscfg.c b/platform/syscfg.c index 740c689..83fbac2 100644 --- a/platform/syscfg.c +++ b/platform/syscfg.c @@ -71,6 +71,8 @@ HRESULT syscfg_hook_init(const struct syscfg_config *cfg, const uint32_t gid) L"SOFTWARE\\taito\\typex", fake_com_keys, _countof(fake_com_keys)); + + return hr; } static HRESULT syscfg_game_kind(void *bytes, uint32_t *nbytes) diff --git a/platform/vfs.c b/platform/vfs.c index 98f1f77..555b775 100644 --- a/platform/vfs.c +++ b/platform/vfs.c @@ -23,7 +23,6 @@ static struct vfs_config vfs_config; HRESULT vfs_hook_init(const struct vfs_config *config) { - wchar_t temp[MAX_PATH]; size_t nthome_len; DWORD home_ok; HRESULT hr; @@ -52,14 +51,6 @@ HRESULT vfs_hook_init(const struct vfs_config *config) (int) hr); } - /* Need to create the temp subdirectory, not just nthome itself */ - - hr = vfs_mkdir_rec(temp); - - if (FAILED(hr)) { - dprintf("Vfs: Failed to create %S: %x\n", temp, (int) hr); - } - /* Not auto-creating option directory as it is normally a read-only mount */ hr = path_hook_push(vfs_path_hook); diff --git a/mu3hook/config.c b/sivahook/config.c similarity index 51% rename from mu3hook/config.c rename to sivahook/config.c index 6e3991d..9e49872 100644 --- a/mu3hook/config.c +++ b/sivahook/config.c @@ -1,26 +1,19 @@ #include #include -#include "board/config.h" - -#include "gfxhook/config.h" - -#include "hooklib/config.h" -#include "hooklib/dvd.h" - -#include "mu3hook/config.h" +#include "sivahook/config.h" #include "platform/config.h" -void mu3_dll_config_load( - struct mu3_dll_config *cfg, +void siva_dll_config_load( + struct siva_dll_config *cfg, const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); GetPrivateProfileStringW( - L"mu3io", + L"sivaio", L"path", L"", cfg->path, @@ -28,17 +21,14 @@ void mu3_dll_config_load( filename); } -void mu3_hook_config_load( - struct mu3_hook_config *cfg, +void siva_hook_config_load( + struct siva_hook_config *cfg, const wchar_t *filename) { assert(cfg != NULL); assert(filename != NULL); platform_config_load(&cfg->platform, filename); - aime_config_load(&cfg->aime, filename); - dvd_config_load(&cfg->dvd, filename); - io4_config_load(&cfg->io4, filename); + siva_dll_config_load(&cfg->dll, filename); gfx_config_load(&cfg->gfx, filename); - mu3_dll_config_load(&cfg->dll, filename); -} +} \ No newline at end of file diff --git a/sivahook/config.h b/sivahook/config.h new file mode 100644 index 0000000..1813ac3 --- /dev/null +++ b/sivahook/config.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "sivahook/siva-dll.h" + +#include "platform/config.h" +#include "gfxhook/config.h" +#include "board/config.h" + +struct siva_hook_config { + struct platform_config platform; + struct siva_dll_config dll; + struct gfx_config gfx; +}; + +void siva_hook_config_load( + struct siva_hook_config *cfg, + const wchar_t *filename); diff --git a/sivahook/dllmain.c b/sivahook/dllmain.c new file mode 100644 index 0000000..7478107 --- /dev/null +++ b/sivahook/dllmain.c @@ -0,0 +1,91 @@ +#include + +#include "board/io4.h" + +#include "hook/process.h" + +#include "hooklib/serial.h" +#include "hooklib/spike.h" + +#include "gfxhook/gfx.h" +#include "gfxhook/d3d11.h" + +#include "sivahook/config.h" +#include "sivahook/siva-dll.h" +#include "sivahook/unity.h" + +#include "platform/platform.h" + +#include "util/dprintf.h" + +static HMODULE siva_hook_mod; +static process_entry_t siva_startup; +static struct siva_hook_config siva_hook_cfg; + +/* This hook is based on mu3hook, with leaked sivahook i/o codes. */ + +static DWORD CALLBACK siva_pre_startup(void) +{ + HRESULT hr; + + dprintf("--- Begin siva_pre_startup ---\n"); + + /* Load config */ + + siva_hook_config_load(&siva_hook_cfg, L".\\taitools.ini"); + + /* Hook Win32 APIs */ + serial_hook_init(); + + gfx_hook_init(&siva_hook_cfg.gfx); + gfx_d3d11_hook_init(&siva_hook_cfg.gfx, siva_hook_mod); + + /* Initialize emulation hooks */ + + hr = platform_hook_init( + &siva_hook_cfg.platform, + 3000, + siva_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + hr = siva_dll_init(&siva_hook_cfg.dll, siva_hook_mod); + + if (FAILED(hr)) { + goto fail; + } + + unity_hook_init(); + /* Initialize debug helpers */ + + spike_hook_init(L".\\taitools.ini"); + + dprintf("--- End siva_pre_startup ---\n"); + + /* Jump to EXE start address */ + + return siva_startup(); + +fail: + ExitProcess(EXIT_FAILURE); +} + +BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx) +{ + HRESULT hr; + + if (cause != DLL_PROCESS_ATTACH) { + return TRUE; + } + + siva_hook_mod = mod; + + hr = process_hijack_startup(siva_pre_startup, &siva_startup); + + if (!SUCCEEDED(hr)) { + dprintf("Failed to hijack process startup: %x\n", (int) hr); + } + + return SUCCEEDED(hr); +} diff --git a/mu3hook/meson.build b/sivahook/meson.build similarity index 73% rename from mu3hook/meson.build rename to sivahook/meson.build index 27ba7f7..1331d71 100644 --- a/mu3hook/meson.build +++ b/sivahook/meson.build @@ -1,21 +1,19 @@ shared_library( - 'mu3hook', + 'sivahook', name_prefix : '', include_directories : inc, implicit_include_directories : false, - vs_module_defs : 'mu3hook.def', + vs_module_defs : 'sivahook.def', c_pch : '../precompiled.h', dependencies : [ capnhook.get_variable('hook_dep'), capnhook.get_variable('hooklib_dep'), - xinput_lib, ], link_with : [ - aimeio_lib, - board_lib, gfxhook_lib, + board_lib, hooklib_lib, - mu3io_lib, + sivaio_lib, platform_lib, util_lib, ], @@ -23,11 +21,9 @@ shared_library( 'config.c', 'config.h', 'dllmain.c', - 'io4.c', - 'io4.h', - 'mu3-dll.c', - 'mu3-dll.h', - 'unity.h', + 'siva-dll.c', + 'siva-dll.h', 'unity.c', + 'unity.h', ], ) diff --git a/sivahook/siva-dll.c b/sivahook/siva-dll.c new file mode 100644 index 0000000..d001710 --- /dev/null +++ b/sivahook/siva-dll.c @@ -0,0 +1,100 @@ +#include + +#include +#include + +#include "sivahook/siva-dll.h" + +#include "util/dll-bind.h" +#include "util/dprintf.h" + +const struct dll_bind_sym siva_dll_syms[] = { + { + .sym = "siva_io_init", + .off = offsetof(struct siva_dll, init), + }, { + .sym = "siva_io_read_coin_counter", + .off = offsetof(struct siva_dll, read_coin_counter), + }, { + .sym = "siva_io_get_btns", + .off = offsetof(struct siva_dll, get_btns), + }, +}; + +struct siva_dll siva_dll; + +HRESULT siva_dll_init(const struct siva_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("Siva IO: Failed to load IO DLL: %lx: %S\n", + hr, + cfg->path); + + goto end; + } + + dprintf("Siva IO: Using custom IO DLL: %S\n", cfg->path); + src = owned; + } else { + owned = NULL; + src = self; + } + + get_api_version = (void *) GetProcAddress(src, "siva_io_get_api_version"); + + if (get_api_version != NULL) { + siva_dll.api_version = get_api_version(); + } else { + siva_dll.api_version = 0x0100; + dprintf("Custom IO DLL does not expose siva_io_get_api_version, " + "assuming API version 1.0.\n" + "Please ask the developer to update their DLL.\n"); + } + + if (siva_dll.api_version >= 0x0200) { + hr = E_NOTIMPL; + dprintf("Siva IO: Custom IO DLL implements an unsupported " + "API version (%#04x). Please update Segatools.\n", + siva_dll.api_version); + + goto end; + } + + sym = siva_dll_syms; + hr = dll_bind(&siva_dll, src, &sym, _countof(siva_dll_syms)); + + if (FAILED(hr)) { + if (src != self) { + dprintf("Siva 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; +} \ No newline at end of file diff --git a/sivahook/siva-dll.h b/sivahook/siva-dll.h new file mode 100644 index 0000000..d903236 --- /dev/null +++ b/sivahook/siva-dll.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "sivaio/sivaio.h" + +struct siva_dll { + uint16_t api_version; + HRESULT (*init)(void); + void (*read_coin_counter)(uint16_t *coins, uint16_t *services); + void (*get_btns)(uint8_t *btn, uint8_t *stick); +}; + +struct siva_dll_config { + wchar_t path[MAX_PATH]; +}; + +extern struct siva_dll siva_dll; + +HRESULT siva_dll_init(const struct siva_dll_config *cfg, HINSTANCE self); diff --git a/sivahook/sivahook.def b/sivahook/sivahook.def new file mode 100644 index 0000000..4040499 --- /dev/null +++ b/sivahook/sivahook.def @@ -0,0 +1,7 @@ +LIBRARY sivahook + +EXPORTS + siva_io_get_api_version + siva_io_init + siva_io_read_coin_counter + siva_io_get_btns \ No newline at end of file diff --git a/mu3hook/unity.c b/sivahook/unity.c similarity index 73% rename from mu3hook/unity.c rename to sivahook/unity.c index efefc32..5c719be 100644 --- a/mu3hook/unity.c +++ b/sivahook/unity.c @@ -3,9 +3,13 @@ #include #include "hook/table.h" +#include "hook/iohook.h" #include "hooklib/dll.h" #include "hooklib/path.h" +#include "hooklib/serial.h" +#include "hooklib/reg.h" +#include "hook/procaddr.h" #include "util/dprintf.h" @@ -25,8 +29,15 @@ static const struct hook_symbol unity_kernel32_syms[] = { static const wchar_t *target_modules[] = { L"mono.dll", L"cri_ware_unity.dll", + L"SimpleNesys.dll", + L"ismACIO.dll", + L"NESiCAReader.dll", }; + +static const wchar_t *dep_hooks[] = {}; + static const size_t target_modules_len = _countof(target_modules); +static const size_t dep_hooks_len = _countof(dep_hooks); void unity_hook_init(void) { @@ -46,10 +57,13 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) { const wchar_t *name_end; const wchar_t *target_module; + const wchar_t *target_dep; bool already_loaded; HMODULE result; + HMODULE dep_mod; size_t name_len; size_t target_module_len; + size_t dep_len; if (name == NULL) { SetLastError(ERROR_INVALID_PARAMETER); @@ -88,6 +102,20 @@ static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name) dll_hook_insert_hooks(result); path_hook_insert_hooks(result); + reg_hook_insert_hooks(result); + proc_addr_insert_hooks(result); + } + + for (size_t i = 0; i < dep_hooks_len; i++) { + target_dep = dep_hooks[i]; + + dep_mod = GetModuleHandleW(target_dep); + if (dep_mod != NULL) { + dprintf("Unity: Hook dependency %ls\n", target_dep); + iohook_apply_hooks(dep_mod); + serial_hook_apply_hooks(dep_mod); + reg_hook_insert_hooks(dep_mod); + } } } diff --git a/mu3hook/unity.h b/sivahook/unity.h similarity index 100% rename from mu3hook/unity.h rename to sivahook/unity.h diff --git a/sivaio/config.c b/sivaio/config.c new file mode 100644 index 0000000..aa2cbf3 --- /dev/null +++ b/sivaio/config.c @@ -0,0 +1,30 @@ +#include + +#include +#include +#include + +#include "sivaio/config.h" + +void siva_io_config_load(struct siva_input_config *cfg, const wchar_t *filename) +{ + cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename); + cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename); + cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename); + + cfg->is_xinput = GetPrivateProfileIntW(L"deck", L"deck", 0, filename); + cfg->xinput_player = GetPrivateProfileIntW(L"deck", L"controller_num", 0, filename); + + cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename); + cfg->btn_r = GetPrivateProfileIntW(L"deck", L"right_button", 'N', filename); + + cfg->stick_l_up = GetPrivateProfileIntW(L"deck", L"left_stick_up", 'W', filename); + cfg->stick_l_right = GetPrivateProfileIntW(L"deck", L"left_stick_right", 'D', filename); + cfg->stick_l_down = GetPrivateProfileIntW(L"deck", L"left_stick_down", 'S', filename); + cfg->stick_l_left = GetPrivateProfileIntW(L"deck", L"left_stick_left", 'A', filename); + + cfg->stick_r_up = GetPrivateProfileIntW(L"deck", L"right_stick_up", 'I', filename); + cfg->stick_r_right = GetPrivateProfileIntW(L"deck", L"right_stick_right", 'L', filename); + cfg->stick_r_down = GetPrivateProfileIntW(L"deck", L"right_stick_down", 'K', filename); + cfg->stick_r_left = GetPrivateProfileIntW(L"deck", L"right_stick_left", 'J', filename); +} \ No newline at end of file diff --git a/sivaio/config.h b/sivaio/config.h new file mode 100644 index 0000000..3f82c82 --- /dev/null +++ b/sivaio/config.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#pragma pack(push, 1) +struct siva_input_config { + uint8_t is_xinput; + uint8_t xinput_player; + + uint8_t test; + uint8_t service; + uint8_t coin; + uint8_t btn_l; + uint8_t btn_r; + + uint8_t stick_l_up; + uint8_t stick_l_right; + uint8_t stick_l_down; + uint8_t stick_l_left; + uint8_t stick_r_up; + uint8_t stick_r_right; + uint8_t stick_r_down; + uint8_t stick_r_left; +}; +#pragma pack(pop) + +void siva_io_config_load(struct siva_input_config *cfg, const wchar_t *filename); \ No newline at end of file diff --git a/mu3io/meson.build b/sivaio/meson.build similarity index 61% rename from mu3io/meson.build rename to sivaio/meson.build index 3d6e60e..38bc413 100644 --- a/mu3io/meson.build +++ b/sivaio/meson.build @@ -1,5 +1,5 @@ -mu3io_lib = static_library( - 'mu3io', +sivaio_lib = static_library( + 'sivaio', name_prefix : '', include_directories : inc, implicit_include_directories : false, @@ -8,7 +8,9 @@ mu3io_lib = static_library( xinput_lib, ], sources : [ - 'mu3io.c', - 'mu3io.h', + 'sivaio.c', + 'sivaio.h', + 'config.c', + 'config.h', ], ) diff --git a/sivaio/sivaio.c b/sivaio/sivaio.c new file mode 100644 index 0000000..5c536e2 --- /dev/null +++ b/sivaio/sivaio.c @@ -0,0 +1,64 @@ +#include +#include + +#include +#include +#include + +#include "sivaio/sivaio.h" +#include "sivaio/config.h" + +#include "util/dprintf.h" + +static bool siva_io_coin = false; +static bool siva_io_service = false; +static uint16_t siva_coin_ct = 0; +static uint16_t siva_service_ct = 0; +static struct siva_input_config cfg; + +uint16_t siva_io_get_api_version(void) +{ + return 0x0100; +} + +HRESULT siva_io_init(void) +{ + dprintf("Siva IO: Init\n"); + siva_io_config_load(&cfg, L".\\bananatools.ini"); + return S_OK; +} + +void siva_io_get_btns(uint8_t *btn, uint8_t *stick) +{ + if (GetAsyncKeyState(cfg.test) & 0x8000) { + *btn |= SIVA_BTN_TEST; + } + + if (GetAsyncKeyState(cfg.service) & 0x8000) { + *btn |= SIVA_BTN_SERVICE; + } +} + +void siva_io_read_coin_counter(uint16_t *coins, uint16_t *services) +{ + if (GetAsyncKeyState(cfg.coin) & 0x8000) { + if (!siva_io_coin) { + siva_io_coin = true; + siva_coin_ct++; + } + } else { + siva_io_coin = false; + } + + if (GetAsyncKeyState(cfg.service) & 0x8000) { + if (!siva_io_service) { + siva_io_service = true; + siva_service_ct++; + } + } else { + siva_io_service = false; + } + + *coins = siva_coin_ct; + *services = siva_service_ct; +} \ No newline at end of file diff --git a/sivaio/sivaio.h b/sivaio/sivaio.h new file mode 100644 index 0000000..afa1376 --- /dev/null +++ b/sivaio/sivaio.h @@ -0,0 +1,57 @@ +#pragma once + +#include + +#include + +enum { + SIVA_BTN_TEST = 0x01, + SIVA_BTN_SERVICE = 0x02, + SIVA_BTN_COIN = 0x03, + SIVA_BTN_LEFT = 0x04, + SIVA_BTN_RIGHT = 0x05, +}; + +enum { + SIVA_STICK_L_UP = 0x01, + SIVA_STICK_L_RIGHT = 0x02, + SIVA_STICK_L_DOWN = 0x03, + SIVA_STICK_L_LEFT = 0x04, + SIVA_STICK_R_UP = 0x05, + SIVA_STICK_R_RIGHT = 0x06, + SIVA_STICK_R_DOWN = 0x07, + SIVA_STICK_R_LEFT = 0x08, +}; + +/* Get the version of the Theatrhythm IO API that this DLL supports. This + function should return a positive 16-bit integer, where the high byte is + the major version and the low byte is the minor version (as defined by the + Semantic Versioning standard). + + The latest API version as of this writing is 0x0100. */ + +uint16_t siva_io_get_api_version(void); + +/* Initialize the IO DLL. This is the second function that will be called on + your DLL, after siva_io_get_api_version. + + All subsequent calls to this API may originate from arbitrary threads. + + Minimum API version: 0x0100 */ + +HRESULT siva_io_init(void); + + +/* Get the state of the cabinet's gameplay buttons as of the last poll. See + SIVA_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into + a left hand side set of inputs and a right hand side set of inputs: the bit + mappings are the same in both cases. + + All buttons are active-high, even though some buttons' electrical signals + on a real cabinet are active-low. + + Minimum API version: 0x0100 */ + +void siva_io_get_btns(uint8_t *btn, uint8_t *stick); + +void siva_io_read_coin_counter(uint16_t *coins, uint16_t *services); \ No newline at end of file