diff --git a/src/micetools/dll/common.h b/src/micetools/dll/common.h index 743b55e..8e430ee 100644 --- a/src/micetools/dll/common.h +++ b/src/micetools/dll/common.h @@ -24,6 +24,7 @@ #include "../lib/mice/mice.h" #include "./util/_util.h" #include "micefs.h" +#include "input_config.h" #define size2int(x) ((int)((x) & 0x7fffffff)) #define size2uint(x) ((unsigned int)((x) & 0xffffffff)) diff --git a/src/micetools/dll/devices/ser_maitouch.c b/src/micetools/dll/devices/ser_maitouch.c index dd79492..df3cdad 100644 --- a/src/micetools/dll/devices/ser_maitouch.c +++ b/src/micetools/dll/devices/ser_maitouch.c @@ -62,6 +62,24 @@ WORD getSensorInRegion(float mX, float mY, float rX, float rY, float rW, float r } static BYTE g_ActiveResponse[14]; +static inline void handleOneButton(int iW, int iH, int iX, int iY) { + float x = (float)iX / (float)(iW); + float y = (float)iY / (float)(iH); + + // If the window is square, assume `1P_ONLY` is set + WORD button; + if (iW == iH) { + button = getSensorInRegion(x, y, 0.0f, 0.0f, 1.0f, 1.0f); + if (button) g_ActiveResponse[button >> 8] |= button & 0xff; + } else { + // 1P + button = getSensorInRegion(x, y, 0.0f, 0.4375f, 0.5f, 0.5625f); + if (button) g_ActiveResponse[button >> 8] |= button & 0xff; + // 2P + button = getSensorInRegion(x, y, 0.5f, 0.4375f, 0.5f, 0.5625f); + if (button) g_ActiveResponse[(button >> 8) + 6] |= button & 0xff; + } +} static void populateActiveResponse() { // Placeholders g_ActiveResponse[1] = '@'; @@ -74,41 +92,29 @@ static void populateActiveResponse() { g_ActiveResponse[9] = '@'; g_ActiveResponse[10] = '@'; - if (!GetAsyncKeyState(VK_LBUTTON)) return; - - POINT pCursor; - GetCursorPos(&pCursor); if (!mainWindow) return; - if (!ScreenToClient(mainWindow, &pCursor)) return; - RECT winRect; if (!GetWindowRect(mainWindow, &winRect)) return; DWORD dwStyle = GetWindowLongW(mainWindow, GWL_STYLE); UnadjustWindowRect(&winRect, dwStyle, FALSE); - int w = winRect.right - winRect.left; int h = winRect.bottom - winRect.top; - float x = (float)pCursor.x / (float)(w); - float y = (float)pCursor.y / (float)(h); + if (GetAsyncKeyState(VK_LBUTTON)) { + POINT pCursor; + GetCursorPos(&pCursor); + if (ScreenToClient(mainWindow, &pCursor)) { + handleOneButton(w, h, pCursor.x, pCursor.y); + } + } - // If the window is square, assume `1P_ONLY` is set - WORD button; - if (w == h) { - button = getSensorInRegion(x, y, 0.0f, 0.0f, 1.0f, 1.0f); - if (button) g_ActiveResponse[button >> 8] |= button & 0xff; - } else { - // 1P - button = getSensorInRegion(x, y, 0.0f, 0.4375f, 0.5f, 0.5625f); - if (button) g_ActiveResponse[button >> 8] |= button & 0xff; - // 2P - button = getSensorInRegion(x, y, 0.5f, 0.4375f, 0.5f, 0.5625f); - if (button) g_ActiveResponse[(button >> 8) + 6] |= button & 0xff; + for (DWORD i = 0; i < nActiveTouches; i++) { + handleOneButton(w, h, activeTouches[i].m_X, activeTouches[i].m_Y); } } BOOL touch_is_enabled = TRUE; // Default on is important! -BYTE thresh = 0x00; // Lazy caching of single value +BYTE thresh = 0x00; // Lazy caching of single value DWORD WINAPI touch_bd_thread(com_device_t* dev) { log_info(plfMaiTouch, "%ls woke up", dev->com->wName); @@ -124,7 +130,7 @@ DWORD WINAPI touch_bd_thread(com_device_t* dev) { if (touch_is_enabled && !comdev_available(dev)) { populateActiveResponse(); comdev_write(dev, g_ActiveResponse, 14); - Sleep(5); // 200Hz should be plenty + Sleep(2); continue; } diff --git a/src/micetools/dll/devices/smb_at24c64an.c b/src/micetools/dll/devices/smb_at24c64an.c index ef30098..fcfa6d6 100644 --- a/src/micetools/dll/devices/smb_at24c64an.c +++ b/src/micetools/dll/devices/smb_at24c64an.c @@ -43,9 +43,9 @@ void set_eeprom_static_config() { .m_Rental = MiceConfig.sysconf.rental, }; ZeroMemory(Static.m_strSerialId, sizeof Static.m_strSerialId); - DWORD len = strlen(MiceConfig.sysconf.serial); + DWORD len = strlen(MiceConfig.sysconf.pcb_serial); if (len > sizeof Static.m_strSerialId - 1) len = sizeof Static.m_strSerialId - 1; - memcpy(Static.m_strSerialId, MiceConfig.sysconf.serial, len); + memcpy(Static.m_strSerialId, MiceConfig.sysconf.pcb_serial, len); fix_crc(Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_REG], &Static, sizeof Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_DUP], &Static, sizeof Static); diff --git a/src/micetools/dll/dllmain.c b/src/micetools/dll/dllmain.c index 47c21ef..f7de14e 100644 --- a/src/micetools/dll/dllmain.c +++ b/src/micetools/dll/dllmain.c @@ -59,13 +59,14 @@ void prebind_hooks() { void init_injection(HMODULE hModule) { WideCharToMultiByte(CP_ACP, 0, exeName, -1, exeNameC, sizeof exeNameC, NULL, NULL); + // We're in a new context now, so need to reconfigure + setup_logging(); // Make sure our CRC32 tables are ready for anything that might want to use them amiCrc32RInit(); load_mice_config(); + load_keybind_config(); - // We're in a new context now, so need to reconfigure - setup_logging(); MiceSetLogBasename(exeNameC); log_info(plfBoot, "Handover complete. Now executing within %ls", exeName); @@ -126,10 +127,7 @@ void init_injection(HMODULE hModule) { // MX SuperIO: Communicate with the HW monitor chip if (MiceConfig.drivers.mxsuperio) setup_mxsuperio(); // MX JVS: Interacting with JVS-based devices - if (MiceConfig.drivers.mxjvs) { - setup_mxjvs(); - load_keybind_config(); - } + if (MiceConfig.drivers.mxjvs) setup_mxjvs(); // MX HW Reset: Forcibly reboot the machine if (MiceConfig.drivers.mxhwreset) setup_mxhwreset(); // MX SMBus: Communicate over the LPC bus. This contains the EEPROM, and PCA9535 diff --git a/src/micetools/dll/drivers/jvs_boards/jvs.h b/src/micetools/dll/drivers/jvs_boards/jvs.h index 987369a..e2bf67c 100644 --- a/src/micetools/dll/drivers/jvs_boards/jvs.h +++ b/src/micetools/dll/drivers/jvs_boards/jvs.h @@ -70,5 +70,3 @@ static inline void MiceJvsWrite(PMICE_JVS this, BYTE data) { if (this->m_lpOutData == NULL) return; if (this->m_nOutIdx < MICE_JVS_MAX) this->m_lpOutData[this->m_nOutIdx++] = data; } - -extern MICE_JVS _MiceJvsBoards[JVS_IO_MAX]; diff --git a/src/micetools/dll/drivers/jvs_boards/jvs_837_14572.c b/src/micetools/dll/drivers/jvs_boards/jvs_837_14572.c index fc47b9f..fa9f680 100644 --- a/src/micetools/dll/drivers/jvs_boards/jvs_837_14572.c +++ b/src/micetools/dll/drivers/jvs_boards/jvs_837_14572.c @@ -1,7 +1,6 @@ #include #include "../../common.h" -#include "jvs.h" #define PLAYER_COUNT 2 #define COIN_COUNTERS 2 @@ -24,15 +23,20 @@ static void Ctor(PMICE_JVS this) { this->m_VersionComm = 0x10; // Coin + Test + 13 switches per player - this->m_ButtonsPerPlayer = PLAYER_SWITCH_COUNT; - this->m_Coins = COIN_COUNTERS; - this->m_Players = PLAYER_COUNT; + if (this->m_ButtonsPerPlayer == 0) this->m_ButtonsPerPlayer = PLAYER_SWITCH_COUNT; + if (this->m_Coins == 0) this->m_Coins = COIN_COUNTERS; + if (this->m_Players == 0) this->m_Players = PLAYER_COUNT; - this->m_NumButtons = this->m_Coins + 1 + (this->m_ButtonsPerPlayer * this->m_Players); - this->m_ButtonStates = malloc(this->m_NumButtons * sizeof *this->m_ButtonStates); - ZeroMemory(this->m_ButtonStates, this->m_NumButtons * sizeof *this->m_ButtonStates); - this->m_Bindings = malloc(this->m_NumButtons * sizeof *this->m_Bindings); - ZeroMemory(this->m_Bindings, this->m_NumButtons * sizeof *this->m_Bindings); + if (this->m_NumButtons == 0) + this->m_NumButtons = this->m_Coins + 1 + (this->m_ButtonsPerPlayer * this->m_Players); + if (this->m_ButtonStates == NULL) { + this->m_ButtonStates = malloc(this->m_NumButtons * sizeof *this->m_ButtonStates); + ZeroMemory(this->m_ButtonStates, this->m_NumButtons * sizeof *this->m_ButtonStates); + } + if (this->m_Bindings == NULL) { + this->m_Bindings = malloc(this->m_NumButtons * sizeof *this->m_Bindings); + ZeroMemory(this->m_Bindings, this->m_NumButtons * sizeof *this->m_Bindings); + } ZeroMemory(this->m_CoinCounts, sizeof this->m_CoinCounts); } diff --git a/src/micetools/dll/drivers/jvs_boards/jvs_837_14895.c b/src/micetools/dll/drivers/jvs_boards/jvs_837_14895.c index e24116f..370d286 100644 --- a/src/micetools/dll/drivers/jvs_boards/jvs_837_14895.c +++ b/src/micetools/dll/drivers/jvs_boards/jvs_837_14895.c @@ -1,7 +1,6 @@ #include #include "../../common.h" -#include "jvs.h" #define PLAYER_COUNT 1 #define COIN_COUNTERS 2 @@ -88,20 +87,12 @@ static JVS_STATUS Transact(PMICE_JVS this, BYTE command) { unsigned char coin_count; coin_count = MiceJvsRead(this); - // int coin1 = jvsKeybindings[board->num].buttons[0]; - // int coin2 = jvsKeybindings[board->num].buttons[1]; - - // if (coin1 && GetAsyncKeyState(coin1) & 1) board->coin_counts[0]++; - // if (coin2 && GetAsyncKeyState(coin2) & 1) board->coin_counts[1]++; - - // for (unsigned char slot = 0; slot < coin_count; slot++) { - // MiceJvsWrite(this, board->coin_counts[slot] >> 8); - // MiceJvsWrite(this, board->coin_counts[slot] & 0xff); - // } + if (MiceInputGetButtonState(&(this->m_Bindings[0]))) this->m_CoinCounts[0]++; + if (MiceInputGetButtonState(&(this->m_Bindings[1]))) this->m_CoinCounts[1]++; for (unsigned char slot = 0; slot < coin_count; slot++) { - MiceJvsWrite(this, 0); - MiceJvsWrite(this, 0); + MiceJvsWrite(this, this->m_CoinCounts[slot] >> 8); + MiceJvsWrite(this, this->m_CoinCounts[slot] & 0xff); } return JVS_STATUS_OK; diff --git a/src/micetools/dll/drivers/jvs_boards/jvs_base.c b/src/micetools/dll/drivers/jvs_boards/jvs_base.c index 94b2d38..f0caf98 100644 --- a/src/micetools/dll/drivers/jvs_boards/jvs_base.c +++ b/src/micetools/dll/drivers/jvs_boards/jvs_base.c @@ -1,7 +1,6 @@ #include #include "../../common.h" -#include "jvs.h" static void Ctor(PMICE_JVS this) { this->vftable = &_MiceJvsBase_vftable; diff --git a/src/micetools/dll/drivers/mxjvs.c b/src/micetools/dll/drivers/mxjvs.c index 03ab91f..683e006 100644 --- a/src/micetools/dll/drivers/mxjvs.c +++ b/src/micetools/dll/drivers/mxjvs.c @@ -4,10 +4,9 @@ #include "../common.h" #include "../input.h" #include "../key_config.h" -#include "jvs_boards/jvs.h" #include "mx.h" -#define JVS_SENSE (MiceConfig.keys.board_count == 0 ? FALSE : _MiceJvsBoards[0].m_SenseOut) +#define JVS_SENSE (g_MiceJvsNumBoards == 0 ? FALSE : _MiceJvsBoards[0].m_SenseOut) JVS_STATUS MiceJvsWrapper(PMICE_JVS this, DWORD nMaxRead) { JVS_STATUS status = JVS_STATUS_OK; @@ -38,11 +37,35 @@ void jvs_send_status(unsigned char status, unsigned char* outData, LPDWORD outCo } } +static float jvsRateAccum; +static float jvsDTHistory[60]; +static size_t jvsDTHIndex = 0; +static size_t jvsDTHCount = 0; +float jvsRate = 0; + BYTE jvsInUnmasked[MICE_JVS_MAX]; BYTE jvsOutUnmasked[MICE_JVS_MAX]; BYTE jvsOutMasked[MICE_JVS_MASKED]; void mxjvs_handle(unsigned char* lpMaskedIn, short nMaskedCount, unsigned char* outData, short maxOut, LPDWORD outCount) { + // Poll rate calculation + static amtime_t last_tick = { .seconds = 0, .microseconds = 0 }; + amtime_t now; + amiTimerGet(&now); + + float dt = (float)amiTimerDiffUsec(&last_tick, &now) / (float)1000000; + if (last_tick.seconds != 0 || last_tick.microseconds != 0) { + jvsRateAccum += dt - jvsDTHistory[jvsDTHIndex]; + jvsDTHistory[jvsDTHIndex] = dt; + if ((++jvsDTHIndex) == _countof(jvsDTHistory)) jvsDTHIndex = 0; + if ((++jvsDTHCount) > _countof(jvsDTHistory)) jvsDTHCount = _countof(jvsDTHistory); + + jvsRate = (jvsRateAccum > 0.0f) ? (1.0f / (jvsRateAccum / (float)jvsDTHCount)) : FLT_MAX; + } + last_tick = now; + + // Actual handler start + SHORT nIn = 0; BOOL wasMark = FALSE; for (int i = 0; i < nMaskedCount; i++) { @@ -81,7 +104,7 @@ void mxjvs_handle(unsigned char* lpMaskedIn, short nMaskedCount, unsigned char* return; } - DWORD nBoardCount = MiceConfig.keys.board_count; + DWORD nBoardCount = g_MiceJvsNumBoards; if (nBoardCount > _countof(_MiceJvsBoards)) nBoardCount = _countof(_MiceJvsBoards); // Not broadcast, not master-bound, and within bounds diff --git a/src/micetools/dll/drivers/mxparallel.c b/src/micetools/dll/drivers/mxparallel.c index 4ea7c0f..a918687 100644 --- a/src/micetools/dll/drivers/mxparallel.c +++ b/src/micetools/dll/drivers/mxparallel.c @@ -2,10 +2,12 @@ #include "../../sysconf.h" -BYTE parallel_flags = 0x00; -BYTE parallel_ctrl = 0x00; -BYTE parallel_status = 0x00; -BYTE parallel_data = 0x00; +static HANDLE parallel_ctrl_changed_event = NULL; + +static BYTE parallel_flags = 0x00; +static BYTE parallel_ctrl = 0x00; +static BYTE parallel_status = 0x00; +static BYTE parallel_data = 0x00; BYTE KEYCHIP_ID[16] = KEY_ID; BYTE _MAIN_ID[16] = MAIN_ID; @@ -71,6 +73,7 @@ BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCod return TRUE; case IOCTL_MXPARALLEL_WRITE_CTRL_PORT: parallel_ctrl = ((LPBYTE)lpInBuffer)[0]; + SetEvent(parallel_ctrl_changed_event); // log_warning(plfMxParallel, "Write ctrl %08x", parallel_ctrl); outLen(0); return TRUE; @@ -101,12 +104,12 @@ BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCod void micexkTransportSend(unsigned char* send_data, int nbytes) { setAck; for (int i = 0; i < nbytes; i++) { - while (_Strobe) YieldProcessor(); + WaitForNotStrobe; setBusy; parallel_data = send_data[i]; - while (!_Strobe) YieldProcessor(); + WaitForStrobe; clearBusy; - while (_Strobe) YieldProcessor(); + WaitForNotStrobe; } clearAck; } @@ -120,10 +123,10 @@ void micexkSendPacket(unsigned char* send_data) { void micexkTransportRecv(unsigned char* buffer, int nbytes) { for (int i = 0; i < nbytes; i++) { clearBusy; - while (!_Strobe) YieldProcessor(); + WaitForStrobe; buffer[i] = parallel_data; setBusy; - while (_Strobe) YieldProcessor(); + WaitForNotStrobe; clearBusy; } } @@ -450,6 +453,8 @@ void setup_mxparallel() { init_nv_storage(); + parallel_ctrl_changed_event = CreateEvent(NULL, FALSE, FALSE, NULL); + file_hook_t* mxparallel = new_file_hook(L"\\\\.\\mxparallel"); mxparallel->DeviceIoControl = &mxparallel_DeviceIoControl; hook_file(mxparallel); diff --git a/src/micetools/dll/drivers/mxparallel.h b/src/micetools/dll/drivers/mxparallel.h index a68be30..630c486 100644 --- a/src/micetools/dll/drivers/mxparallel.h +++ b/src/micetools/dll/drivers/mxparallel.h @@ -17,7 +17,6 @@ typedef struct { } nvram_data_block_t; #pragma pack(pop) - void micexkTransportSend(unsigned char* send_data, int nbytes); void micexkSendPacket(unsigned char* send_data); void micexkTransportRecv(unsigned char* buffer, int nbytes); @@ -59,3 +58,17 @@ static BYTE parallel_data; #define _Reset getControl(0x04) #define _SelPrint getControl(0x08) #define _IsDirWrite getControl(0x20) + +#define WaitForStrobe \ + do { \ + while (!_Strobe) WaitForSingleObject(parallel_ctrl_changed_event, INFINITE); \ + /* Awful way to release any other threads too */ \ + SetEvent(parallel_ctrl_changed_event); \ + } while (0) + +#define WaitForNotStrobe \ + do { \ + while (_Strobe) WaitForSingleObject(parallel_ctrl_changed_event, INFINITE); \ + /* Awful way to release any other threads too */ \ + SetEvent(parallel_ctrl_changed_event); \ + } while (0) diff --git a/src/micetools/dll/games.c b/src/micetools/dll/games.c index 36ff92a..42455b7 100644 --- a/src/micetools/dll/games.c +++ b/src/micetools/dll/games.c @@ -1,6 +1,5 @@ #include "common.h" #include "devices/_devices.h" -#include "drivers/jvs_boards/jvs.h" #include "input.h" #include "key_config.h" @@ -110,7 +109,7 @@ void _MiceSetupMaimai() { MiceConfig.sysconf.dipsw = 0b01111000; MiceConfig.window.nosize = true; - if (MiceConfig.keys.board_count == 0) MiceConfig.keys.board_count = 1; + g_MiceJvsNumBoards = 1; free(_MiceJvsBoards[0].m_Bindings); _MiceJvsBoards[0].m_Bindings = malloc(sizeof maimaiDefaultBindings); @@ -123,6 +122,9 @@ void _MiceSetupMaimai() { _MiceJvsBoards[0].m_ButtonStates = malloc(_countof(maimaiDefaultBindings) * sizeof *_MiceJvsBoards[0].m_ButtonStates); + save_keybind_config(); + load_keybind_config(); + // Maimai is going to check if these exist. They do, now. make_dirs(MiceIpcRelativePath("dev\\w\\maimai")); make_dirs(MiceIpcRelativePath("dev\\v\\maimai")); @@ -139,7 +141,7 @@ void _MiceSetupApm() { MiceConfig.sysconf.dipsw = 0b01000000; // 720p - if (MiceConfig.keys.board_count == 0) MiceConfig.keys.board_count = 1; + g_MiceJvsNumBoards = 1; free(_MiceJvsBoards[0].m_Bindings); _MiceJvsBoards[0].m_Bindings = malloc(sizeof apmDefaultBindings); @@ -151,6 +153,8 @@ void _MiceSetupApm() { free(_MiceJvsBoards[0].m_ButtonStates); _MiceJvsBoards[0].m_ButtonStates = malloc(_countof(apmDefaultBindings) * sizeof *_MiceJvsBoards[0].m_ButtonStates); + + save_keybind_config(); } void _MiceGotGameId(char game_id[4]) { @@ -173,44 +177,7 @@ void _MiceGotGameId(char game_id[4]) { _MiceSetupMaimai(); } else if (IS_GAME(SBYG /* APM2 */) || IS_GAME(SDCM /* UNIB */)) { log_info(plfBoot, "Detect game APM2"); - _MiceSetupApm(); - - // MiceConfig.devices.com1 = ""; - // MiceConfig.devices.com2 = ""; - // MiceConfig.devices.com3 = ""; - // MiceConfig.devices.com5 = ""; - // MiceConfig.devices.com6 = ""; - // MiceConfig.devices.com7 = ""; - // MiceConfig.devices.com8 = ""; - - // if (MiceConfig.keys.board_count == 0) MiceConfig.keys.board_count = 1; - - // if (!jvsKeybindings[0].notdefault) { - // puts("!!"); - - // // Zero all buttons - // memset(&jvsKeybindings[0].buttons[3 * 2], 0, 12 * 2); - // memset(&jvsKeybindings[0].invert[3 * 2], 0, 12 * 2); - - // jvsKeybindings[0].buttons[0 * 2] = VK_BACK; - // jvsKeybindings[0].buttons[1 * 2] = VK_RETURN; - - // jvsKeybindings[0].buttons[3 * 2] = VK_UP; - // jvsKeybindings[0].buttons[4 * 2] = VK_DOWN; - // jvsKeybindings[0].buttons[5 * 2] = VK_LEFT; - // jvsKeybindings[0].buttons[6 * 2] = VK_RIGHT; - - // jvsKeybindings[0].buttons[7 * 2] = 'Q'; - // jvsKeybindings[0].buttons[8 * 2] = 'W'; - // jvsKeybindings[0].buttons[9 * 2] = 'E'; - // jvsKeybindings[0].buttons[10 * 2] = 'A'; - // jvsKeybindings[0].buttons[11 * 2] = 'S'; - // jvsKeybindings[0].buttons[12 * 2] = 'D'; - - // // 2P is unbound by default, as a (nice) keymap with both - // // will probably also involve changing 1P too. - // } } else if (IS_GAME(SBVH /* Sega & Sonic All-Stars Racing Arcade */)) { log_info(plfBoot, "Detect game Sega & Sonic All-Stars Racing Arcade"); diff --git a/src/micetools/dll/gui/gui.c b/src/micetools/dll/gui/gui.c index cd7608e..4254fbd 100644 --- a/src/micetools/dll/gui/gui.c +++ b/src/micetools/dll/gui/gui.c @@ -2,8 +2,8 @@ #ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS #define CIMGUI_DEFINE_ENUMS_AND_STRUCTS #endif +#include "../common.h" #include "../devices/smb_at24c64an.h" -#include "../drivers/jvs_boards/jvs.h" #include "../key_config.h" #include "cimgui.h" #include "imgui/backends/GL/freeglut.h" @@ -152,6 +152,7 @@ void hud_card(ImGuiKey open_key) { igEnd(); } +extern float jvsRate; void hud_fps() { if (igBegin("FPS", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | @@ -167,6 +168,7 @@ void hud_fps() { igText("FPS: %.1f", io->Framerate); igText(" dT: %.2fms", 1000 / io->Framerate); + igText("JVS Rate: %.2f", jvsRate); } igEnd(); @@ -422,16 +424,19 @@ void tab_settings_system() { // The 'M' prefix isn't technically foolproof, but it's good enough for a simple help message staticChanged |= AddSettingString( "PCB serial number", - (MiceConfig.sysconf.serial && MiceConfig.sysconf.serial[0] == 'M' ? SERIAL_HELP : NULL), - &MiceConfig.sysconf.serial); + (MiceConfig.sysconf.pcb_serial && MiceConfig.sysconf.pcb_serial[0] == 'M' ? SERIAL_HELP + : NULL), + &MiceConfig.sysconf.pcb_serial); if (staticChanged) { build_eeprom(); save_current_config(false); } if (AddSettingString( "Keychip serial number", - (MiceConfig.sysconf.keyid && MiceConfig.sysconf.keyid[0] == 'M' ? SERIAL_HELP : NULL), - &MiceConfig.sysconf.keyid)) { + (MiceConfig.sysconf.keychip_serial && MiceConfig.sysconf.keychip_serial[0] == 'M' + ? SERIAL_HELP + : NULL), + &MiceConfig.sysconf.keychip_serial)) { save_current_config(false); } @@ -789,16 +794,16 @@ void AddSettingButton(PMICE_JVS board, int player, int button) { igSameLine(0, -1); if (igButton(clear, vec0)) { bind->m_Type = MICE_BB_TYPE_UNBOUND; - save_current_config(false); + save_keybind_config(); } } igNextColumn(); igBeginDisabled(bind->m_Type == MICE_BB_TYPE_UNBOUND); - if (igCheckbox(invertName, (bool*)&bind->m_Invert)) save_current_config(false); + if (igCheckbox(invertName, (bool*)&bind->m_Invert)) save_keybind_config(); igEndDisabled(); igNextColumn(); - if (igKeyBindPopup_New(name, bind)) save_current_config(false); + if (igKeyBindPopup_New(name, bind)) save_keybind_config(); } void AddButtonsForBoard(PMICE_JVS board) { @@ -841,33 +846,34 @@ void tab_jvs_board(int num) { igSeparator(); - AddButtonsForBoard(&_MiceJvsBoards[0]); + AddButtonsForBoard(&_MiceJvsBoards[num]); - igSeparator(); - AddSetting("Test", NULL); - char keyName[16]; - if (jvsKeybindings[num].test == 0) { - igTextColored(DISABLED_COL, "None"); - } else { - GetKeyNameTextA(MapVirtualKey(jvsKeybindings[num].test, MAPVK_VK_TO_VSC) << 16, keyName, - _countof(keyName)); - igTextUnformatted(keyName, NULL); - } - igNextColumn(); - if (igButton("Bind##JvsTest", vec0)) igOpenPopup_Str("BindJvsTest", ImGuiPopupFlags_None); - if (jvsKeybindings[num].test) { - igSameLine(0, -1); - if (igButton("Clear##ClearJvsTest", vec0)) { - jvsKeybindings[num].test = 0; - save_current_config(false); - } - } - int boundKey; - if (igKeyBindPopup("BindJvsTest", &boundKey)) - if (boundKey != -1) { - jvsKeybindings[num].test = boundKey; - save_current_config(false); - } + // TODO: RESTORE THIS! + // igSeparator(); + // AddSetting("Test", NULL); + // char keyName[16]; + // if (jvsKeybindings[num].test == 0) { + // igTextColored(DISABLED_COL, "None"); + // } else { + // GetKeyNameTextA(MapVirtualKey(jvsKeybindings[num].test, MAPVK_VK_TO_VSC) << 16, keyName, + // _countof(keyName)); + // igTextUnformatted(keyName, NULL); + // } + // igNextColumn(); + // if (igButton("Bind##JvsTest", vec0)) igOpenPopup_Str("BindJvsTest", ImGuiPopupFlags_None); + // if (jvsKeybindings[num].test) { + // igSameLine(0, -1); + // if (igButton("Clear##ClearJvsTest", vec0)) { + // jvsKeybindings[num].test = 0; + // save_keybind_config(); + // } + // } + // int boundKey; + // if (igKeyBindPopup("BindJvsTest", &boundKey)) + // if (boundKey != -1) { + // jvsKeybindings[num].test = boundKey; + // save_keybind_config(); + // } igEndColumns(); @@ -940,15 +946,14 @@ void tab_system_buttons() { } void tab_main_keybinds() { - if (igInputInt("Number of JVS boards", &MiceConfig.keys.board_count, 1, 1, - ImGuiInputTextFlags_None)) { - if (MiceConfig.keys.board_count < 0) MiceConfig.keys.board_count = 0; - if (MiceConfig.keys.board_count > JVS_IO_MAX) MiceConfig.keys.board_count = JVS_IO_MAX; - save_current_config(false); + if (igInputInt("Number of JVS boards", &g_MiceJvsNumBoards, 1, 1, ImGuiInputTextFlags_None)) { + if (g_MiceJvsNumBoards < 1) g_MiceJvsNumBoards = 1; + if (g_MiceJvsNumBoards > JVS_IO_MAX) g_MiceJvsNumBoards = JVS_IO_MAX; + save_keybind_config(); } if (igBeginTabBar("JVSBoards", 0)) { - for (int i = 0; i < MiceConfig.keys.board_count; i++) { + for (int i = 0; i < g_MiceJvsNumBoards; i++) { char name[32]; snprintf(name, _countof(name), "Board %d", i + 1); if (igBeginTabItem(name, NULL, 0)) { diff --git a/src/micetools/dll/hooks/gui.c b/src/micetools/dll/hooks/gui.c index 081afcd..d33c1f3 100644 --- a/src/micetools/dll/hooks/gui.c +++ b/src/micetools/dll/hooks/gui.c @@ -4,6 +4,101 @@ #include "../input.h" +// These APIs were added in Windows 8. Because they're events sent to the WndProc, we're safe to +// just re-define them ourselves, and get progressive enhancement! +#if (WINVER < 0x0602) +#define WM_NCPOINTERUPDATE 0x0241 +#define WM_NCPOINTERDOWN 0x0242 +#define WM_NCPOINTERUP 0x0243 +#define WM_POINTERUPDATE 0x0245 +#define WM_POINTERDOWN 0x0246 +#define WM_POINTERUP 0x0247 +#define WM_POINTERENTER 0x0249 +#define WM_POINTERLEAVE 0x024A +#define WM_POINTERACTIVATE 0x024B +#define WM_POINTERCAPTURECHANGED 0x024C + +#define POINTER_FLAG_INCONTACT 0x00000004 +#define POINTER_FLAG_FIRSTBUTTON 0x00000010 +#define POINTER_FLAG_CANCELED 0x00008000 +#define POINTER_FLAG_DOWN 0x00010000 +#define POINTER_FLAG_UP 0x00040000 + +#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) + +enum tagPOINTER_INPUT_TYPE { + PT_POINTER = 1, // Generic pointer + PT_TOUCH = 2, // Touch + PT_PEN = 3, // Pen + PT_MOUSE = 4, // Mouse + PT_TOUCHPAD = 5, // Touchpad +}; + +typedef DWORD POINTER_INPUT_TYPE; +typedef UINT32 POINTER_FLAGS; + +typedef enum tagPOINTER_BUTTON_CHANGE_TYPE { + POINTER_CHANGE_NONE, + POINTER_CHANGE_FIRSTBUTTON_DOWN, + POINTER_CHANGE_FIRSTBUTTON_UP, + POINTER_CHANGE_SECONDBUTTON_DOWN, + POINTER_CHANGE_SECONDBUTTON_UP, + POINTER_CHANGE_THIRDBUTTON_DOWN, + POINTER_CHANGE_THIRDBUTTON_UP, + POINTER_CHANGE_FOURTHBUTTON_DOWN, + POINTER_CHANGE_FOURTHBUTTON_UP, + POINTER_CHANGE_FIFTHBUTTON_DOWN, + POINTER_CHANGE_FIFTHBUTTON_UP, +} POINTER_BUTTON_CHANGE_TYPE; + +typedef struct tagPOINTER_INFO { + POINTER_INPUT_TYPE pointerType; + UINT32 pointerId; + UINT32 frameId; + POINTER_FLAGS pointerFlags; + HANDLE sourceDevice; + HWND hwndTarget; + POINT ptPixelLocation; + POINT ptHimetricLocation; + POINT ptPixelLocationRaw; + POINT ptHimetricLocationRaw; + DWORD dwTime; + UINT32 historyCount; + INT32 InputData; + DWORD dwKeyStates; + UINT64 PerformanceCount; + POINTER_BUTTON_CHANGE_TYPE ButtonChangeType; +} POINTER_INFO; + +// Our target API at compile time didn't support these functions, but these functions are only ever +// called if we've already received a touch window event, meaning we're actually running on a newer +// version of windows. That means we're safe to load in these functions and use them! +static HMODULE hmUser32 = NULL; +static BOOL(WINAPI* lpGetPointerType)(UINT32 pointerId, POINTER_INPUT_TYPE* pointerType) = NULL; +static BOOL MockGetPointerType(UINT32 pointerId, POINTER_INPUT_TYPE* pointerType) { + puts("Loading mock"); + if (!hmUser32) hmUser32 = LoadLibraryA("User32.dll"); + if (!hmUser32) return FALSE; + puts("Loading function"); + if (!lpGetPointerType) lpGetPointerType = (void*)GetProcAddress(hmUser32, "GetPointerType"); + if (!lpGetPointerType) return FALSE; + puts("Calling"); + return lpGetPointerType(pointerId, pointerType); +} +static BOOL(WINAPI* lpGetPointerInfo)(UINT32 pointerId, POINTER_INFO* pointerInfo) = NULL; +static BOOL MockGetPointerInfo(UINT32 pointerId, POINTER_INFO* pointerInfo) { + if (!hmUser32) hmUser32 = LoadLibraryA("User32.dll"); + if (!hmUser32) return FALSE; + if (!lpGetPointerInfo) lpGetPointerInfo = (void*)GetProcAddress(hmUser32, "GetPointerInfo"); + if (!lpGetPointerInfo) return FALSE; + return lpGetPointerInfo(pointerId, pointerInfo); +} +#else +// If our target API supports these, no mocking is needed +#define MockGetPointerType GetPointerType +#define MockGetPointerInfo GetPointerInfo +#endif + extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); HWND mainWindow = NULL; @@ -152,10 +247,74 @@ void register_gui_hook(FnEndScene* end_scene) { *head = hook; } +DWORD nActiveTouches = 0; +ACTIVE_TOUCH* activeTouches = NULL; +extern DWORD nActiveTouchesMax = 0; + +void SetTouch(UINT id, INT x, INT y, BOOL state) { + if (state) { + // If we can just update in place, do + for (DWORD i = 0; i < nActiveTouches; i++) { + if (activeTouches[i].m_Id == id) { + activeTouches[i].m_X = x; + activeTouches[i].m_Y = y; + return; + } + } + + // Dynamic array re-allocation + if (nActiveTouches == nActiveTouchesMax) { + DWORD newSize = nActiveTouchesMax * 2 + 1; + ACTIVE_TOUCH* newMemory = realloc(activeTouches, sizeof *activeTouches * newSize); + if (newMemory != activeTouches) { + memcpy(newMemory, activeTouches, sizeof *activeTouches * nActiveTouchesMax); + } + activeTouches = newMemory; + nActiveTouchesMax = newSize; + } + + // Store into end of DA + activeTouches[nActiveTouches].m_Id = id; + activeTouches[nActiveTouches].m_X = x; + activeTouches[nActiveTouches].m_Y = y; + nActiveTouches++; + } else { + for (DWORD i = 0; i < nActiveTouches; i++) { + if (activeTouches[i].m_Id == id) { + // Copy backwards + for (DWORD j = i + 1; j < nActiveTouches; j++) { + activeTouches[j - 1].m_Id = activeTouches[j].m_Id; + activeTouches[j - 1].m_X = activeTouches[j].m_X; + activeTouches[j - 1].m_Y = activeTouches[j].m_Y; + } + nActiveTouches--; + } + } + } +} + +void TouchHandler(HWND hWnd, WPARAM wParam, LPARAM lParam) { + UINT32 pointerId = GET_POINTERID_WPARAM(wParam); + POINTER_INFO pointerInfo = { sizeof(POINTER_INFO) }; + POINTER_INPUT_TYPE pointerType = 0; + + if (MockGetPointerType(pointerId, &pointerType) && + MockGetPointerInfo(pointerId, &pointerInfo)) { + POINT point = pointerInfo.ptPixelLocation; + if (pointerType == PT_TOUCH && ScreenToClient(hWnd, &point)) { + SetTouch(pointerInfo.pointerId, point.x, point.y, + !!(pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT)); // | + } + } +} + DWORD changeCursorState = (DWORD)-1; +WNDPROC OriginalWndProc = NULL; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { - ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); + if (hookType == UI_HOOK_DX9) { + ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); + } if (changeCursorState == 1) { while (ShowCursor(TRUE) < 0) @@ -167,6 +326,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UIN changeCursorState = (DWORD)-1; } + switch (uMsg) { + case WM_NCPOINTERUPDATE: + case WM_NCPOINTERDOWN: + case WM_NCPOINTERUP: + case WM_POINTERUPDATE: + case WM_POINTERDOWN: + case WM_POINTERUP: + case WM_POINTERENTER: + case WM_POINTERLEAVE: + case WM_POINTERACTIVATE: + case WM_POINTERCAPTURECHANGED: + TouchHandler(hWnd, wParam, lParam); + break; + } + + if (OriginalWndProc) { + return CallWindowProcA(OriginalWndProc, hWnd, uMsg, wParam, lParam); + } + return DefSubclassProc(hWnd, uMsg, wParam, lParam); } @@ -186,13 +364,19 @@ void post_win_create(HWND hWnd) { DetourAttach((PVOID*)&TrueEndScene, hkEndScene); DetourTransactionCommit(); } - - if (hWnd && !SetWindowSubclass(hWnd, WndProc, (UINT_PTR)&WndProc, (DWORD_PTR)NULL)) { - log_error(plfGUI, "failed to SetWindowSubclass(%d)", GetLastError()); - } + // MiceInputInit will be called by our D3D9 hooks instead } else { MiceInputInit(hWnd); } + + if (hWnd) { + OriginalWndProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC); + if (OriginalWndProc == NULL) log_warning(plfGUI, "GWLP_WNDPROC NULL"); + + if (!SetWindowSubclass(hWnd, WndProc, (UINT_PTR)&WndProc, (DWORD_PTR)NULL)) { + log_error(plfGUI, "failed to SetWindowSubclass(%d)", GetLastError()); + } + } } RECT monitorRect = { 0 }; diff --git a/src/micetools/dll/hooks/gui.h b/src/micetools/dll/hooks/gui.h index eb42da2..b3fce91 100644 --- a/src/micetools/dll/hooks/gui.h +++ b/src/micetools/dll/hooks/gui.h @@ -43,6 +43,14 @@ void register_gui_hook(FnEndScene* end_scene); void hook_gui(); void setup_hud_gui(); +typedef struct { + UINT m_Id; + INT m_X; + INT m_Y; +} ACTIVE_TOUCH; +extern DWORD nActiveTouches; +extern ACTIVE_TOUCH* activeTouches; + BOOL UnadjustWindowRect(LPRECT prc, DWORD dwStyle, BOOL fMenu); extern HWND mainWindow; extern DWORD changeCursorState; diff --git a/src/micetools/dll/hooks/system.c b/src/micetools/dll/hooks/system.c index 8944229..c430c0e 100644 --- a/src/micetools/dll/hooks/system.c +++ b/src/micetools/dll/hooks/system.c @@ -36,17 +36,21 @@ DWORD WINAPI FakeGetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) { } HCURSOR WINAPI FakeLoadCursorFromFileA(LPCSTR lpFileName) { return (HANDLE)1; } -BOOL FakeSetSystemCursor(HCURSOR hcur, DWORD id) { return TRUE; } -BOOL FakeDeleteObject(HGDIOBJ ho) { return TRUE; } +BOOL WINAPI FakeSetSystemCursor(HCURSOR hcur, DWORD id) { return TRUE; } +BOOL WINAPI FakeDeleteObject(HGDIOBJ ho) { return TRUE; } -FARPROC FakeGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { - log_trace(plfSystem, "GetProcAddress(%s)", lpProcName); +FARPROC WINAPI FakeGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { + // log_error(plfSystem, "GetProcAddress(%s)", lpProcName); return TrueGetProcAddress(hModule, lpProcName); } -HMODULE FakeGetModuleHandleA(LPCSTR lpModuleName) { - log_trace(plfSystem, "GetModuleHandleA(%s)", lpModuleName); +HMODULE WINAPI FakeGetModuleHandleA(LPCSTR lpModuleName) { + // log_game(plfSystem, "GetModuleHandleA(%s)", lpModuleName); return TrueGetModuleHandleA(lpModuleName); } +HMODULE WINAPI FakeGetModuleHandleW(LPCWSTR lpModuleName) { + // log_game(plfSystem, "GetModuleHandleW(%ls)", lpModuleName); + return TrueGetModuleHandleW(lpModuleName); +} LONG WINAPI FakeRtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation) { log_trace(plfSystem, "RtlGetVersion(%p)", lpVersionInformation); @@ -89,8 +93,9 @@ void hook_system() { hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL); hook("Kernel32.dll", "GetTempPathW", FakeGetTempPathW, NULL); // hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL); - // hook("Kernel32.dll", "GetProcAddress", FakeGetProcAddress, (void*)&TrueGetProcAddress); - // hook("Kernel32.dll", "GetModuleHandleA", FakeGetModuleHandleA, (void*)&TrueGetModuleHandleA); + hook("Kernel32.dll", "GetProcAddress", FakeGetProcAddress, (void*)&TrueGetProcAddress); + hook("Kernel32.dll", "GetModuleHandleA", FakeGetModuleHandleA, (void*)&TrueGetModuleHandleA); + hook("Kernel32.dll", "GetModuleHandleW", FakeGetModuleHandleW, (void*)&TrueGetModuleHandleW); hook("Kernel32.dll", "LoadLibraryA", FakeLoadLibraryA, (void*)&TrueLoadLibraryA); hook("Kernel32.dll", "LoadLibraryW", FakeLoadLibraryW, (void*)&TrueLoadLibraryW); diff --git a/src/micetools/dll/hooks/system.h b/src/micetools/dll/hooks/system.h index 0e0989e..7eb3abe 100644 --- a/src/micetools/dll/hooks/system.h +++ b/src/micetools/dll/hooks/system.h @@ -4,6 +4,7 @@ FARPROC(WINAPI* TrueGetProcAddress)(HMODULE hModule, LPCSTR lpProcName); HMODULE(WINAPI* TrueGetModuleHandleA)(LPCSTR lpModuleName); +HMODULE(WINAPI* TrueGetModuleHandleW)(LPCWSTR lpModuleName); HMODULE(WINAPI* TrueLoadLibraryA)(LPCSTR lpLibFileName); HMODULE(WINAPI* TrueLoadLibraryW)(LPCWSTR lpLibFileName); diff --git a/src/micetools/dll/input_config.c b/src/micetools/dll/input_config.c new file mode 100644 index 0000000..83325eb --- /dev/null +++ b/src/micetools/dll/input_config.c @@ -0,0 +1,129 @@ +#include "common.h" + +int g_MiceJvsNumBoards = 0; +MICE_JVS _MiceJvsBoards[JVS_IO_MAX]; + +void save_keybind_config() { + HANDLE hFile = CreateFileA(KEYBINDS_PATH, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE, NULL, + CREATE_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Failed to open keybinds file: %d", GetLastError()); + return; + } + + SetFilePointer(hFile, 8, NULL, 0); + + DWORD nWrote; + DWORD totalSize = 0; + WriteFile(hFile, &g_MiceJvsNumBoards, sizeof g_MiceJvsNumBoards, &nWrote, NULL); + totalSize += nWrote; + + for (int board = 0; board < g_MiceJvsNumBoards; board++) { + WriteFile(hFile, &_MiceJvsBoards[board].m_Players, sizeof _MiceJvsBoards[board].m_Players, + &nWrote, NULL); + totalSize += nWrote; + WriteFile(hFile, &_MiceJvsBoards[board].m_ButtonsPerPlayer, + sizeof _MiceJvsBoards[board].m_ButtonsPerPlayer, &nWrote, NULL); + totalSize += nWrote; + WriteFile(hFile, &_MiceJvsBoards[board].m_Coins, sizeof _MiceJvsBoards[board].m_Coins, + &nWrote, NULL); + totalSize += nWrote; + WriteFile(hFile, &_MiceJvsBoards[board].m_NumButtons, + sizeof _MiceJvsBoards[board].m_NumButtons, &nWrote, NULL); + totalSize += nWrote; + + WriteFile(hFile, _MiceJvsBoards[board].m_Bindings, + sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards[board].m_NumButtons, + &nWrote, NULL); + totalSize += nWrote; + } + + SetFilePointer(hFile, 0, NULL, 0); + WriteFile(hFile, &totalSize, sizeof totalSize, &nWrote, NULL); + + amiCrc32RInit(); + DWORD readLeft = totalSize; + DWORD crc32 = 0; + SetFilePointer(hFile, 8, NULL, 0); + while (readLeft) { + BYTE readBuf[0x1000]; + DWORD toRead = sizeof readBuf; + if (readLeft < toRead) toRead = readLeft; + DWORD nRead; + ReadFile(hFile, readBuf, toRead, &nRead, NULL); + + if (nRead == 0) { + fprintf(stderr, "Binding saving failed %d\n", GetLastError()); + CloseHandle(hFile); + return; + } + crc32 = amiCrc32RCalc(nRead, readBuf, crc32); + readLeft -= nRead; + } + SetFilePointer(hFile, 4, NULL, 0); + WriteFile(hFile, &crc32, sizeof crc32, &nWrote, NULL); + + CloseHandle(hFile); +} +void load_keybind_config() { + HANDLE hFile = + CreateFileA(KEYBINDS_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) return; + + DWORD nRead; + DWORD nSize = 0; + ReadFile(hFile, &nSize, sizeof nSize, &nRead, NULL); + + SetFilePointer(hFile, 8, NULL, 0); + amiCrc32RInit(); + DWORD crc32 = 0; + while (nSize) { + BYTE readBuf[0x1000]; + DWORD toRead = sizeof readBuf; + if (nSize < toRead) toRead = nSize; + ReadFile(hFile, readBuf, toRead, &nRead, NULL); + + if (nRead == 0) { + log_error(plfBoot, "Binding reading failed\n"); + CloseHandle(hFile); + return; + } + crc32 = amiCrc32RCalc(nRead, readBuf, crc32); + nSize -= nRead; + } + + DWORD savedCrc; + SetFilePointer(hFile, 4, NULL, 0); + ReadFile(hFile, &savedCrc, sizeof savedCrc, &nRead, NULL); + if (savedCrc != crc32) { + log_error(plfBoot, "Binding file CRC failed (%08x!=%08x)\n", savedCrc, crc32); + CloseHandle(hFile); + return; + } + + ReadFile(hFile, &g_MiceJvsNumBoards, sizeof g_MiceJvsNumBoards, &nRead, NULL); + + for (int board = 0; board < g_MiceJvsNumBoards; board++) { + ReadFile(hFile, &_MiceJvsBoards[board].m_Players, sizeof _MiceJvsBoards[board].m_Players, + &nRead, NULL); + ReadFile(hFile, &_MiceJvsBoards[board].m_ButtonsPerPlayer, + sizeof _MiceJvsBoards[board].m_ButtonsPerPlayer, &nRead, NULL); + ReadFile(hFile, &_MiceJvsBoards[board].m_Coins, sizeof _MiceJvsBoards[board].m_Coins, + &nRead, NULL); + ReadFile(hFile, &_MiceJvsBoards[board].m_NumButtons, + sizeof _MiceJvsBoards[board].m_NumButtons, &nRead, NULL); + + free(_MiceJvsBoards[board].m_Bindings); + _MiceJvsBoards[board].m_Bindings = + malloc(sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards[board].m_NumButtons); + ReadFile(hFile, _MiceJvsBoards[board].m_Bindings, + sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards[board].m_NumButtons, + &nRead, NULL); + + free(_MiceJvsBoards[board].m_ButtonStates); + _MiceJvsBoards[board].m_ButtonStates = malloc(sizeof *_MiceJvsBoards[board].m_ButtonStates * + _MiceJvsBoards[board].m_NumButtons); + } + + CloseHandle(hFile); +} diff --git a/src/micetools/dll/input_config.h b/src/micetools/dll/input_config.h new file mode 100644 index 0000000..a124614 --- /dev/null +++ b/src/micetools/dll/input_config.h @@ -0,0 +1,7 @@ +#include "drivers/jvs_boards/jvs.h" + +void save_keybind_config(); +void load_keybind_config(); + +extern MICE_JVS _MiceJvsBoards[JVS_IO_MAX]; +extern int g_MiceJvsNumBoards; diff --git a/src/micetools/dll/key_config.h b/src/micetools/dll/key_config.h index 863c65e..59d0596 100644 --- a/src/micetools/dll/key_config.h +++ b/src/micetools/dll/key_config.h @@ -5,11 +5,11 @@ #define JVS_IO_MAX 31 #define JVS_BUTTON_PAIR_COUNT 15 -struct { - int buttons[JVS_BUTTON_PAIR_COUNT * 2]; - bool invert[JVS_BUTTON_PAIR_COUNT * 2]; - int test; - int notdefault; -} jvsKeybindings[JVS_IO_MAX] = { 0 }; +// struct { +// int buttons[JVS_BUTTON_PAIR_COUNT * 2]; +// bool invert[JVS_BUTTON_PAIR_COUNT * 2]; +// int test; +// int notdefault; +// } jvsKeybindings[JVS_IO_MAX] = { 0 }; int keySystemTest = 0; diff --git a/src/micetools/dll/meson.build b/src/micetools/dll/meson.build index 14cf0be..c1c21a2 100644 --- a/src/micetools/dll/meson.build +++ b/src/micetools/dll/meson.build @@ -24,6 +24,7 @@ shared_library( 'games.c', 'input.c', 'micefs.c', + 'input_config.c', 'dllmain.c', ], diff --git a/src/micetools/lib/mice/config.c b/src/micetools/lib/mice/config.c index 987e490..90336c1 100644 --- a/src/micetools/lib/mice/config.c +++ b/src/micetools/lib/mice/config.c @@ -6,12 +6,9 @@ #include "../../../../subprojects/inih_dep/ini.h" #include "../../dll/devices/smb_pca9535.h" -#include "../../dll/drivers/jvs_boards/jvs.h" #include "../../dll/hooks/files.h" #include "../../dll/key_config.h" -MICE_JVS _MiceJvsBoards[JVS_IO_MAX]; - config_t MiceConfig = { #define SECTION(s, comment) .s = { #define CFG_str(s, n, default, comment) .n = default, @@ -42,135 +39,10 @@ static void fprintf_prefix(FILE *file, const char *prefix, const char *text) { free(copy); } -void save_keybinds() { - HANDLE hFile = CreateFileA(KEYBINDS_PATH, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE, NULL, - CREATE_ALWAYS, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - fprintf(stderr, "Failed to open keybinds file: %d", GetLastError()); - return; - } - - SetFilePointer(hFile, 8, NULL, 0); - - DWORD nWrote; - DWORD totalSize = 0; - WriteFile(hFile, &MiceConfig.keys.board_count, sizeof MiceConfig.keys.board_count, &nWrote, - NULL); - totalSize += nWrote; - - for (int board = 0; board < MiceConfig.keys.board_count; board++) { - WriteFile(hFile, &_MiceJvsBoards->m_Players, sizeof _MiceJvsBoards->m_Players, &nWrote, - NULL); - totalSize += nWrote; - WriteFile(hFile, &_MiceJvsBoards->m_ButtonsPerPlayer, - sizeof _MiceJvsBoards->m_ButtonsPerPlayer, &nWrote, NULL); - totalSize += nWrote; - WriteFile(hFile, &_MiceJvsBoards->m_Coins, sizeof _MiceJvsBoards->m_Coins, &nWrote, NULL); - totalSize += nWrote; - WriteFile(hFile, &_MiceJvsBoards->m_NumButtons, sizeof _MiceJvsBoards->m_NumButtons, - &nWrote, NULL); - totalSize += nWrote; - - WriteFile(hFile, _MiceJvsBoards[board].m_Bindings, - sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards->m_NumButtons, &nWrote, - NULL); - totalSize += nWrote; - } - - SetFilePointer(hFile, 0, NULL, 0); - WriteFile(hFile, &totalSize, sizeof totalSize, &nWrote, NULL); - - amiCrc32RInit(); - DWORD readLeft = totalSize; - DWORD crc32 = 0; - SetFilePointer(hFile, 8, NULL, 0); - while (readLeft) { - BYTE readBuf[0x1000]; - DWORD toRead = sizeof readBuf; - if (readLeft < toRead) toRead = readLeft; - DWORD nRead; - ReadFile(hFile, readBuf, toRead, &nRead, NULL); - - if (nRead == 0) { - fprintf(stderr, "Binding saving failed %d\n", GetLastError()); - CloseHandle(hFile); - return; - } - crc32 = amiCrc32RCalc(nRead, readBuf, crc32); - readLeft -= nRead; - } - SetFilePointer(hFile, 4, NULL, 0); - WriteFile(hFile, &crc32, sizeof crc32, &nWrote, NULL); - - CloseHandle(hFile); -} -void load_keybind_config() { - HANDLE hFile = - CreateFileA(KEYBINDS_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) return; - - DWORD nRead; - DWORD nSize = 0; - ReadFile(hFile, &nSize, sizeof nSize, &nRead, NULL); - - SetFilePointer(hFile, 8, NULL, 0); - amiCrc32RInit(); - DWORD crc32 = 0; - while (nSize) { - BYTE readBuf[0x1000]; - DWORD toRead = sizeof readBuf; - if (nSize < toRead) toRead = nSize; - ReadFile(hFile, readBuf, toRead, &nRead, NULL); - - if (nRead == 0) { - fprintf(stderr, "Binding reading failed\n"); - CloseHandle(hFile); - return; - } - crc32 = amiCrc32RCalc(nRead, readBuf, crc32); - nSize -= nRead; - } - - DWORD savedCrc; - SetFilePointer(hFile, 4, NULL, 0); - ReadFile(hFile, &savedCrc, sizeof savedCrc, &nRead, NULL); - if (savedCrc != crc32) { - fprintf(stderr, "Binding file CRC failed (%08x!=%08x)\n", savedCrc, crc32); - CloseHandle(hFile); - return; - } - - ReadFile(hFile, &MiceConfig.keys.board_count, sizeof MiceConfig.keys.board_count, &nRead, NULL); - - for (int board = 0; board < MiceConfig.keys.board_count; board++) { - ReadFile(hFile, &_MiceJvsBoards->m_Players, sizeof _MiceJvsBoards->m_Players, &nRead, NULL); - ReadFile(hFile, &_MiceJvsBoards->m_ButtonsPerPlayer, - sizeof _MiceJvsBoards->m_ButtonsPerPlayer, &nRead, NULL); - ReadFile(hFile, &_MiceJvsBoards->m_Coins, sizeof _MiceJvsBoards->m_Coins, &nRead, NULL); - ReadFile(hFile, &_MiceJvsBoards->m_NumButtons, sizeof _MiceJvsBoards->m_NumButtons, &nRead, - NULL); - - free(_MiceJvsBoards[board].m_Bindings); - _MiceJvsBoards[board].m_Bindings = - malloc(sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards->m_NumButtons); - ReadFile(hFile, _MiceJvsBoards[board].m_Bindings, - sizeof *_MiceJvsBoards[board].m_Bindings * _MiceJvsBoards->m_NumButtons, &nRead, - NULL); - - free(_MiceJvsBoards[board].m_ButtonStates); - _MiceJvsBoards[board].m_ButtonStates = - malloc(sizeof *_MiceJvsBoards[board].m_ButtonStates * _MiceJvsBoards->m_NumButtons); - } - - CloseHandle(hFile); -} - char keybindBuffer[2 * JVS_IO_MAX * (sizeof _MiceJvsBoards[0].m_Bindings[0]) * 32]; void save_current_config(bool writeDefault) { CreateDirectoryA("mice", NULL); // TODO: A touch nicer? - save_keybinds(); - FILE *config_file; fopen_s(&config_file, CONFIG_PATH, "w"); if (config_file == NULL) { @@ -270,24 +142,30 @@ void load_mice_config() { if (ini_parse(CONFIG_PATH, handler, &MiceConfig) < 0) { printf("Loading config defaults\n"); - if (MiceConfig.sysconf.serial) free(MiceConfig.sysconf.serial); - MiceConfig.sysconf.serial = malloc(17); - if (MiceConfig.sysconf.keyid) free(MiceConfig.sysconf.keyid); - MiceConfig.sysconf.keyid = malloc(17); - GetSerialNumbers(MiceConfig.sysconf.serial, MiceConfig.sysconf.keyid); + if (MiceConfig.sysconf.pcb_serial) free(MiceConfig.sysconf.pcb_serial); + MiceConfig.sysconf.pcb_serial = malloc(17); + memset(MiceConfig.sysconf.pcb_serial, 0, 17); + if (MiceConfig.sysconf.keychip_serial) free(MiceConfig.sysconf.keychip_serial); + MiceConfig.sysconf.keychip_serial = malloc(17); + memset(MiceConfig.sysconf.keychip_serial, 0, 17); + GetSerialNumbers(MiceConfig.sysconf.pcb_serial, MiceConfig.sysconf.keychip_serial); save_current_config(true); } - if (!MiceConfig.sysconf.serial || strlen(MiceConfig.sysconf.serial) == 0) { - if (MiceConfig.sysconf.serial) free(MiceConfig.sysconf.serial); - MiceConfig.sysconf.serial = malloc(17); - GetSerialNumbers(MiceConfig.sysconf.serial, NULL); + if (!MiceConfig.sysconf.pcb_serial || strlen(MiceConfig.sysconf.pcb_serial) == 0) { + if (MiceConfig.sysconf.pcb_serial) free(MiceConfig.sysconf.pcb_serial); + MiceConfig.sysconf.pcb_serial = malloc(17); + memset(MiceConfig.sysconf.pcb_serial, 0, 17); + GetSerialNumbers(MiceConfig.sysconf.pcb_serial, NULL); + save_current_config(false); } - if (!MiceConfig.sysconf.keyid || strlen(MiceConfig.sysconf.keyid) == 0) { - if (MiceConfig.sysconf.keyid) free(MiceConfig.sysconf.keyid); - MiceConfig.sysconf.keyid = malloc(17); - GetSerialNumbers(NULL, MiceConfig.sysconf.keyid); + if (!MiceConfig.sysconf.keychip_serial || strlen(MiceConfig.sysconf.keychip_serial) == 0) { + if (MiceConfig.sysconf.keychip_serial) free(MiceConfig.sysconf.keychip_serial); + MiceConfig.sysconf.keychip_serial = malloc(17); + memset(MiceConfig.sysconf.keychip_serial, 0, 17); + GetSerialNumbers(NULL, MiceConfig.sysconf.keychip_serial); + save_current_config(false); } if (MiceConfig.window.dipsw) { diff --git a/src/micetools/lib/mice/config.def b/src/micetools/lib/mice/config.def index 36e2dee..cd106aa 100644 --- a/src/micetools/lib/mice/config.def +++ b/src/micetools/lib/mice/config.def @@ -40,9 +40,10 @@ SECTION(sysconf, "System configuration settings") CFG_int(sysconf, platform, 2, "System platform. 0 = RingWide, 1 = RingEdge, 2 = RingEdge2") CFG_int(sysconf, region, 1, "Board region. 1 = Jpn, 2 = USA, 4 = Exp, 8 = Chn") CFG_bool(sysconf, rental, false, "") -CFG_str(sysconf, serial, "A000-00000000000", "") -CFG_str(sysconf, keyid, "A000-00000000000", "") CFG_hex(sysconf, dipsw, 2, 40, "DIP Switch values") // Default 40 = 1280x720 +COMMENT("These serial numbers were automatically generated for you. Please don't change them unless someone has told you to.") +CFG_str(sysconf, pcb_serial, "", "") +CFG_str(sysconf, keychip_serial, "", "") ENDSECTION(sysconf) SECTION(window, "Game window positioning settings") @@ -106,7 +107,6 @@ ENDSECTION(hooks) SECTION(keys, "Raw keybinding data. Edit this using the built in binding tool!") CFG_int(keys, test, 0, "") CFG_int(keys, service, 0, "") -CFG_int(keys, board_count, 1, "") ENDSECTION(keys) SECTION(devices, "Register attached hardware devices. COM4 is reserved for JVS.") diff --git a/src/micetools/lib/mice/config.h b/src/micetools/lib/mice/config.h index 7bdcb36..03ce688 100644 --- a/src/micetools/lib/mice/config.h +++ b/src/micetools/lib/mice/config.h @@ -27,3 +27,4 @@ extern config_t MiceConfig; void save_current_config(bool writeDefault); void load_mice_config(); void load_keybind_config(); +void save_keybind_config(); diff --git a/src/micetools/lib/mice/serial.c b/src/micetools/lib/mice/serial.c index 096d4f5..3bcfa72 100644 --- a/src/micetools/lib/mice/serial.c +++ b/src/micetools/lib/mice/serial.c @@ -67,11 +67,16 @@ cleanup: } inline static void alphaNum(CHAR *lpAddr, BYTE val) { - val %= 26 + 10; + // I and O are disallowed, hence the extra logic + val %= (26 - 2) + 10; if (val < 10) lpAddr[0] = '0' + val; - else + else if (val < 18) lpAddr[0] = 'A' + (val - 10); + else if (val < 23) + lpAddr[0] = 'J' + (val - 18); + else + lpAddr[0] = 'P' + (val - 23); } inline static void numeric(CHAR *lpAddr, BYTE val) { val %= 100; diff --git a/src/micetools/system_dummy/dummykeychip/callbacks-stub.c b/src/micetools/system_dummy/dummykeychip/callbacks-stub.c index 30fdab6..4c69c7a 100644 --- a/src/micetools/system_dummy/dummykeychip/callbacks-stub.c +++ b/src/micetools/system_dummy/dummykeychip/callbacks-stub.c @@ -40,10 +40,10 @@ void mdkPcpAbNetworkAddress(pcpa_t* stream, void* data) { void mdkPcpAbDvd(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, AB_DVD, "01"); } void mdkPcpPbKeyId(pcpa_t* stream, void* data) { - pcpaSetSendPacket(stream, BIL_KEYID, MiceConfig.sysconf.keyid); + pcpaSetSendPacket(stream, BIL_KEYID, MiceConfig.sysconf.keychip_serial); } void mdkPcpPbMainId(pcpa_t* stream, void* data) { - pcpaSetSendPacket(stream, BIL_MAINID, MiceConfig.sysconf.serial); + pcpaSetSendPacket(stream, BIL_MAINID, MiceConfig.sysconf.pcb_serial); } void mdkPcpPbPlayCount(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_PLAYCOUNT, "00000000");