#include #include #include #include "ferrumhook/ferrum-dll.h" #include "util/dll-bind.h" #include "util/dprintf.h" const struct dll_bind_sym ferrum_dll_syms[] = { { .sym = "ferrum_io_jvs_init", .off = offsetof(struct ferrum_dll, jvs_init), },{ .sym = "ferrum_io_gamepad_init", .off = offsetof(struct ferrum_dll, gamepad_init), }, { .sym = "ferrum_io_jvs_poll", .off = offsetof(struct ferrum_dll, jvs_poll), }, { .sym = "ferrum_io_gamepad_poll", .off = offsetof(struct ferrum_dll, gamepad_poll), }, { .sym = "ferrum_io_jvs_read_coin_counter", .off = offsetof(struct ferrum_dll, jvs_read_coin_counter), } }; struct ferrum_dll ferrum_dll; HRESULT ferrum_dll_init(const struct ferrum_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("Ferrum IO: Failed to load IO DLL: %lx: %S\n", hr, cfg->path); goto end; } dprintf("Ferrum IO: Using custom IO DLL: %S\n", cfg->path); src = owned; } else { owned = NULL; src = self; } get_api_version = (void *) GetProcAddress(src, "ferrum_io_get_api_version"); if (get_api_version != NULL) { ferrum_dll.api_version = get_api_version(); } else { ferrum_dll.api_version = 0x0100; dprintf("Custom IO DLL does not expose ferrum_io_get_api_version, " "assuming API version 1.0.\n" "Please ask the developer to update their DLL.\n"); } if (ferrum_dll.api_version >= 0x0200) { hr = E_NOTIMPL; dprintf("Ferrum IO: Custom IO DLL implements an unsupported " "API version (%#04x). Please update Segatools.\n", ferrum_dll.api_version); goto end; } sym = ferrum_dll_syms; hr = dll_bind(&ferrum_dll, src, &sym, _countof(ferrum_dll_syms)); if (FAILED(hr)) { if (src != self) { dprintf("Ferrum 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; }