Gonna be real idk whats in this one chief

This commit is contained in:
Bottersnike 2023-07-14 18:58:39 +01:00
parent 3423861c3c
commit 1ca4d5dc30
Signed by: Bottersnike
SSH Key Fingerprint: SHA256:3g0ghwd4dNX1k1RX8qazbiT+3RIYn/daeBevHZVCiU0
26 changed files with 545 additions and 316 deletions

View File

@ -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))

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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];

View File

@ -1,7 +1,6 @@
#include <Windows.h>
#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);
}

View File

@ -1,7 +1,6 @@
#include <Windows.h>
#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;

View File

@ -1,7 +1,6 @@
#include <Windows.h>
#include "../../common.h"
#include "jvs.h"
static void Ctor(PMICE_JVS this) {
this->vftable = &_MiceJvsBase_vftable;

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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");

View File

@ -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)) {

View File

@ -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 };

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -24,6 +24,7 @@ shared_library(
'games.c',
'input.c',
'micefs.c',
'input_config.c',
'dllmain.c',
],

View File

@ -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) {

View File

@ -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.")

View File

@ -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();

View File

@ -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;

View File

@ -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");