Update wine_patches

This commit is contained in:
brunodev85 2024-02-01 17:16:28 -03:00
parent c43e0ca4f2
commit f22e79a96d
3 changed files with 579 additions and 579 deletions

View File

@ -1,4 +1,4 @@
/* DirectInput
/* DirectInput
*
* Copyright 1998 Marcus Meissner
* Copyright 1998,1999 Lionel Ulmer
@ -158,7 +158,7 @@ static HRESULT dinput_create( IUnknown **out )
}
/******************************************************************************
* DirectInputCreateEx (DINPUT.@)
* DirectInputCreateEx (DINPUT.@)
*/
HRESULT WINAPI DirectInputCreateEx( HINSTANCE hinst, DWORD version, REFIID iid, void **out, IUnknown *outer )
{
@ -191,7 +191,7 @@ HRESULT WINAPI DirectInputCreateEx( HINSTANCE hinst, DWORD version, REFIID iid,
}
/******************************************************************************
* DirectInput8Create (DINPUT8.@)
* DirectInput8Create (DINPUT8.@)
*/
HRESULT WINAPI DECLSPEC_HOTPATCH DirectInput8Create( HINSTANCE hinst, DWORD version, REFIID iid, void **out, IUnknown *outer )
{
@ -226,7 +226,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH DirectInput8Create( HINSTANCE hinst, DWORD vers
}
/******************************************************************************
* DirectInputCreateA (DINPUT.@)
* DirectInputCreateA (DINPUT.@)
*/
HRESULT WINAPI DECLSPEC_HOTPATCH DirectInputCreateA( HINSTANCE hinst, DWORD version, IDirectInputA **out, IUnknown *outer )
{
@ -234,7 +234,7 @@ HRESULT WINAPI DECLSPEC_HOTPATCH DirectInputCreateA( HINSTANCE hinst, DWORD vers
}
/******************************************************************************
* DirectInputCreateW (DINPUT.@)
* DirectInputCreateW (DINPUT.@)
*/
HRESULT WINAPI DECLSPEC_HOTPATCH DirectInputCreateW( HINSTANCE hinst, DWORD version, IDirectInputW **out, IUnknown *outer )
{
@ -288,7 +288,7 @@ __ASM_GLOBAL_FUNC( enum_callback_wrapper,
#endif
/******************************************************************************
* IDirectInputW_EnumDevices
* IDirectInputW_EnumDevices
*/
static HRESULT WINAPI dinput7_EnumDevices( IDirectInput7W *iface, DWORD type, LPDIENUMDEVICESCALLBACKW callback,
void *context, DWORD flags )
@ -542,7 +542,7 @@ static HRESULT WINAPI dinput7_CreateDeviceEx( IDirectInput7W *iface, const GUID
if (IsEqualGUID( &GUID_SysKeyboard, guid )) hr = keyboard_create_device( impl, guid, &device );
else if (IsEqualGUID( &GUID_SysMouse, guid )) hr = mouse_create_device( impl, guid, &device );
else if (IsEqualGUID( &GUID_Joystick, guid )) hr = gamepad_create_device( impl, guid, &device );
else if (IsEqualGUID( &GUID_Joystick, guid )) hr = gamepad_create_device( impl, guid, &device );
else hr = hid_joystick_create_device( impl, guid, &device );
if (FAILED(hr)) return hr;
@ -649,10 +649,10 @@ static HRESULT WINAPI dinput8_EnumDevices( IDirectInput8W *iface, DWORD type, LP
if (hr == DI_OK && try_enum_device( device_type, callback, &instance, context, flags ) == DIENUM_STOP)
return DI_OK;
} while (SUCCEEDED(hr));
hr = gamepad_enum_device( type, flags, &instance, impl->dwVersion );
hr = gamepad_enum_device( type, flags, &instance, impl->dwVersion );
if (hr == DI_OK && try_enum_device( device_type, callback, &instance, context, flags ) == DIENUM_STOP)
return DI_OK;
return DI_OK;
}
return DI_OK;
@ -1130,7 +1130,7 @@ static const IClassFactoryVtbl class_factory_vtbl =
static struct class_factory class_factory = {{&class_factory_vtbl}};
/***********************************************************************
* DllGetClassObject (DINPUT.@)
* DllGetClassObject (DINPUT.@)
*/
HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **out )
{
@ -1149,7 +1149,7 @@ HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **out )
}
/******************************************************************************
* DInput hook thread
* DInput hook thread
*/
static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )

View File

@ -1,4 +1,4 @@
/* DirectInput Gamepad device
/* DirectInput Gamepad device
*
* Copyright 2024 BrunoSX
*
@ -65,18 +65,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
struct gamepad_state
{
short buttons;
char dpad;
short thumb_lx;
short thumb_ly;
short thumb_rx;
short thumb_ry;
short buttons;
char dpad;
short thumb_lx;
short thumb_ly;
short thumb_rx;
short thumb_ry;
};
struct gamepad
{
struct dinput_device base;
struct gamepad_state state;
struct gamepad_state state;
};
static const struct dinput_device_vtbl gamepad_vtbl;
@ -92,92 +92,92 @@ static inline struct gamepad *impl_from_IDirectInputDevice8W( IDirectInputDevice
static void close_server_socket( void )
{
if (server_sock != INVALID_SOCKET)
{
closesocket( server_sock );
server_sock = INVALID_SOCKET;
}
if (winsock_loaded)
{
WSACleanup();
winsock_loaded = FALSE;
}
if (server_sock != INVALID_SOCKET)
{
closesocket( server_sock );
server_sock = INVALID_SOCKET;
}
if (winsock_loaded)
{
WSACleanup();
winsock_loaded = FALSE;
}
}
static BOOL create_server_socket( void )
{
WSADATA wsa_data;
struct sockaddr_in server_addr;
int res;
close_server_socket();
winsock_loaded = WSAStartup( MAKEWORD(2,2), &wsa_data ) == NO_ERROR;
if (!winsock_loaded) return FALSE;
{
WSADATA wsa_data;
struct sockaddr_in server_addr;
int res;
close_server_socket();
winsock_loaded = WSAStartup( MAKEWORD(2,2), &wsa_data ) == NO_ERROR;
if (!winsock_loaded) return FALSE;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
server_addr.sin_port = htons( SERVER_PORT );
server_sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if (server_sock == INVALID_SOCKET) return FALSE;
if (server_sock == INVALID_SOCKET) return FALSE;
res = bind( server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr) );
if (res == SOCKET_ERROR) return FALSE;
return TRUE;
if (res == SOCKET_ERROR) return FALSE;
return TRUE;
}
static BOOL get_gamepad_request( DIDEVICEINSTANCEW *instance, DWORD version )
{
int res, client_addr_len, gamepad_id, name_len;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
DWORD size;
int res, client_addr_len, gamepad_id, name_len;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
DWORD size;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
client_addr.sin_port = htons( CLIENT_PORT );
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD;
buffer[1] = 0;
res = sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
if (res == SOCKET_ERROR) return FALSE;
res = recvfrom( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len );
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD) return FALSE;
memcpy( &gamepad_id, buffer + 1, 4 );
if (gamepad_id == 0)
{
connected_gamepad_id = 0;
return FALSE;
}
connected_gamepad_id = gamepad_id;
mapper_type = buffer[5];
memcpy( &name_len, buffer + 6, 4 );
char gamepad_name[name_len + 1];
gamepad_name[name_len] = '\0';
memcpy( gamepad_name, buffer + 10, name_len );
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD;
buffer[1] = 0;
res = sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
if (res == SOCKET_ERROR) return FALSE;
res = recvfrom( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len );
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD) return FALSE;
memcpy( &gamepad_id, buffer + 1, 4 );
if (gamepad_id == 0)
{
connected_gamepad_id = 0;
return FALSE;
}
connected_gamepad_id = gamepad_id;
mapper_type = buffer[5];
memcpy( &name_len, buffer + 6, 4 );
char gamepad_name[name_len + 1];
gamepad_name[name_len] = '\0';
memcpy( gamepad_name, buffer + 10, name_len );
size = instance->dwSize;
memset( instance, 0, size );
instance->dwSize = size;
instance->guidInstance = GUID_Joystick;
instance->guidProduct = GUID_Joystick;
instance->guidProduct.Data1 = MAKELONG( 0x045e, 0x028e );
instance->guidProduct.Data1 = MAKELONG( 0x045e, 0x028e );
if (version >= 0x0800) instance->dwDevType = DIDEVTYPE_HID | DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEGAMEPAD_STANDARD << 8);
else instance->dwDevType = DIDEVTYPE_HID | DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8);
instance->wUsagePage = HID_USAGE_PAGE_GENERIC;
instance->wUsagePage = HID_USAGE_PAGE_GENERIC;
instance->wUsage = HID_USAGE_GENERIC_GAMEPAD;
MultiByteToWideChar( CP_ACP, 0, gamepad_name, -1, instance->tszInstanceName, MAX_PATH );
MultiByteToWideChar( CP_ACP, 0, gamepad_name, -1, instance->tszProductName, MAX_PATH );
return TRUE;
return TRUE;
}
static LONG scale_value( LONG value, struct object_properties *properties )
@ -225,200 +225,200 @@ static LONG scale_axis_value( LONG value, struct object_properties *properties )
static void handle_gamepad_input( IDirectInputDevice8W *iface, short thumb_lx, short thumb_ly, short thumb_rx, short thumb_ry, short buttons, char dpad )
{
int i, j;
DWORD time, seq;
BOOL notify = FALSE;
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
DIJOYSTATE *state = (DIJOYSTATE *)impl->base.device_state;
time = GetCurrentTime();
seq = impl->base.dinput->evsequence++;
if (mapper_type == MAPPER_TYPE_STANDARD)
{
if (thumb_lx != impl->state.thumb_lx)
{
impl->state.thumb_lx = thumb_lx;
state->lX = scale_axis_value(thumb_lx, &impl->base.object_properties[0]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), state->lX, time, seq );
notify = TRUE;
}
if (thumb_ly != impl->state.thumb_ly)
{
impl->state.thumb_ly = thumb_ly;
state->lY = scale_axis_value(thumb_ly, &impl->base.object_properties[1]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), state->lY, time, seq );
notify = TRUE;
}
if (thumb_rx != impl->state.thumb_rx)
{
impl->state.thumb_rx = thumb_rx;
state->lZ = scale_axis_value(thumb_rx, &impl->base.object_properties[2]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lZ, time, seq );
notify = TRUE;
}
if (thumb_ry != impl->state.thumb_ry)
{
impl->state.thumb_ry = thumb_ry;
state->lRz = scale_axis_value(thumb_ry, &impl->base.object_properties[5]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 ), state->lRz, time, seq );
notify = TRUE;
}
if (buttons != impl->state.buttons)
{
impl->state.buttons = buttons;
for (i = 0, j = 0; i < 12; i++)
{
switch (i)
{
case IDX_BUTTON_A: j = 1; break;
case IDX_BUTTON_B: j = 2; break;
case IDX_BUTTON_X: j = 0; break;
case IDX_BUTTON_Y: j = 3; break;
case IDX_BUTTON_L1: j = 4; break;
case IDX_BUTTON_R1: j = 5; break;
case IDX_BUTTON_L2: j = 6; break;
case IDX_BUTTON_R2: j = 7; break;
case IDX_BUTTON_SELECT: j = 8; break;
case IDX_BUTTON_START: j = 9; break;
case IDX_BUTTON_L3: j = 10; break;
case IDX_BUTTON_R3: j = 11; break;
}
state->rgbButtons[j] = (buttons & (1<<i)) ? 0x80 : 0x00;
queue_event( iface, DIDFT_BUTTON | DIDFT_MAKEINSTANCE( j ), state->rgbButtons[j], time, seq );
}
notify = TRUE;
}
if (dpad != impl->state.dpad)
{
impl->state.dpad = dpad;
state->rgdwPOV[0] = dpad != -1 ? dpad * 4500 : -1;
queue_event( iface, DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ), state->rgdwPOV[0], time, seq );
notify = TRUE;
}
}
else if (mapper_type == MAPPER_TYPE_XINPUT)
{
if (thumb_lx != impl->state.thumb_lx)
{
impl->state.thumb_lx = thumb_lx;
state->lX = scale_axis_value(thumb_lx, &impl->base.object_properties[0]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), state->lX, time, seq );
notify = TRUE;
}
if (thumb_ly != impl->state.thumb_ly)
{
impl->state.thumb_ly = thumb_ly;
state->lY = scale_axis_value(thumb_ly, &impl->base.object_properties[1]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), state->lY, time, seq );
notify = TRUE;
}
if (thumb_rx != impl->state.thumb_rx)
{
impl->state.thumb_rx = thumb_rx;
state->lRx = scale_axis_value(thumb_rx, &impl->base.object_properties[3]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lRx, time, seq );
notify = TRUE;
}
if (thumb_ry != impl->state.thumb_ry)
{
impl->state.thumb_ry = thumb_ry;
state->lRy = scale_axis_value(thumb_ry, &impl->base.object_properties[4]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 4 ), state->lRy, time, seq );
notify = TRUE;
}
if (buttons != impl->state.buttons)
{
impl->state.buttons = buttons;
for (i = 0; i < 10; i++)
{
state->rgbButtons[i] = (buttons & (1<<i)) ? 0x80 : 0x00;
queue_event( iface, DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ), state->rgbButtons[i], time, seq );
}
state->lZ = scale_value((buttons & (1<<10)) ? 32767 : ((buttons & (1<<11)) ? -32768 : 0), &impl->base.object_properties[2]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lZ, time, seq );
notify = TRUE;
}
if (dpad != impl->state.dpad)
{
impl->state.dpad = dpad;
state->rgdwPOV[0] = dpad != -1 ? dpad * 4500 : -1;
queue_event( iface, DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ), state->rgdwPOV[0], time, seq );
notify = TRUE;
}
}
if (notify && impl->base.hEvent) SetEvent( impl->base.hEvent );
int i, j;
DWORD time, seq;
BOOL notify = FALSE;
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
DIJOYSTATE *state = (DIJOYSTATE *)impl->base.device_state;
time = GetCurrentTime();
seq = impl->base.dinput->evsequence++;
if (mapper_type == MAPPER_TYPE_STANDARD)
{
if (thumb_lx != impl->state.thumb_lx)
{
impl->state.thumb_lx = thumb_lx;
state->lX = scale_axis_value(thumb_lx, &impl->base.object_properties[0]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), state->lX, time, seq );
notify = TRUE;
}
if (thumb_ly != impl->state.thumb_ly)
{
impl->state.thumb_ly = thumb_ly;
state->lY = scale_axis_value(thumb_ly, &impl->base.object_properties[1]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), state->lY, time, seq );
notify = TRUE;
}
if (thumb_rx != impl->state.thumb_rx)
{
impl->state.thumb_rx = thumb_rx;
state->lZ = scale_axis_value(thumb_rx, &impl->base.object_properties[2]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lZ, time, seq );
notify = TRUE;
}
if (thumb_ry != impl->state.thumb_ry)
{
impl->state.thumb_ry = thumb_ry;
state->lRz = scale_axis_value(thumb_ry, &impl->base.object_properties[5]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 ), state->lRz, time, seq );
notify = TRUE;
}
if (buttons != impl->state.buttons)
{
impl->state.buttons = buttons;
for (i = 0, j = 0; i < 12; i++)
{
switch (i)
{
case IDX_BUTTON_A: j = 1; break;
case IDX_BUTTON_B: j = 2; break;
case IDX_BUTTON_X: j = 0; break;
case IDX_BUTTON_Y: j = 3; break;
case IDX_BUTTON_L1: j = 4; break;
case IDX_BUTTON_R1: j = 5; break;
case IDX_BUTTON_L2: j = 6; break;
case IDX_BUTTON_R2: j = 7; break;
case IDX_BUTTON_SELECT: j = 8; break;
case IDX_BUTTON_START: j = 9; break;
case IDX_BUTTON_L3: j = 10; break;
case IDX_BUTTON_R3: j = 11; break;
}
state->rgbButtons[j] = (buttons & (1<<i)) ? 0x80 : 0x00;
queue_event( iface, DIDFT_BUTTON | DIDFT_MAKEINSTANCE( j ), state->rgbButtons[j], time, seq );
}
notify = TRUE;
}
if (dpad != impl->state.dpad)
{
impl->state.dpad = dpad;
state->rgdwPOV[0] = dpad != -1 ? dpad * 4500 : -1;
queue_event( iface, DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ), state->rgdwPOV[0], time, seq );
notify = TRUE;
}
}
else if (mapper_type == MAPPER_TYPE_XINPUT)
{
if (thumb_lx != impl->state.thumb_lx)
{
impl->state.thumb_lx = thumb_lx;
state->lX = scale_axis_value(thumb_lx, &impl->base.object_properties[0]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), state->lX, time, seq );
notify = TRUE;
}
if (thumb_ly != impl->state.thumb_ly)
{
impl->state.thumb_ly = thumb_ly;
state->lY = scale_axis_value(thumb_ly, &impl->base.object_properties[1]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), state->lY, time, seq );
notify = TRUE;
}
if (thumb_rx != impl->state.thumb_rx)
{
impl->state.thumb_rx = thumb_rx;
state->lRx = scale_axis_value(thumb_rx, &impl->base.object_properties[3]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lRx, time, seq );
notify = TRUE;
}
if (thumb_ry != impl->state.thumb_ry)
{
impl->state.thumb_ry = thumb_ry;
state->lRy = scale_axis_value(thumb_ry, &impl->base.object_properties[4]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 4 ), state->lRy, time, seq );
notify = TRUE;
}
if (buttons != impl->state.buttons)
{
impl->state.buttons = buttons;
for (i = 0; i < 10; i++)
{
state->rgbButtons[i] = (buttons & (1<<i)) ? 0x80 : 0x00;
queue_event( iface, DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ), state->rgbButtons[i], time, seq );
}
state->lZ = scale_value((buttons & (1<<10)) ? 32767 : ((buttons & (1<<11)) ? -32768 : 0), &impl->base.object_properties[2]);
queue_event( iface, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ), state->lZ, time, seq );
notify = TRUE;
}
if (dpad != impl->state.dpad)
{
impl->state.dpad = dpad;
state->rgdwPOV[0] = dpad != -1 ? dpad * 4500 : -1;
queue_event( iface, DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ), state->rgdwPOV[0], time, seq );
notify = TRUE;
}
}
if (notify && impl->base.hEvent) SetEvent( impl->base.hEvent );
}
static BOOL get_gamepad_state_request( IDirectInputDevice8W *iface )
{
char buffer[BUFFER_SIZE];
int res, client_addr_len, gamepad_id;
char dpad;
short buttons, thumb_lx, thumb_ly, thumb_rx, thumb_ry;
struct sockaddr_in client_addr;
char buffer[BUFFER_SIZE];
int res, client_addr_len, gamepad_id;
char dpad;
short buttons, thumb_lx, thumb_ly, thumb_rx, thumb_ry;
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
client_addr.sin_port = htons( CLIENT_PORT );
client_addr_len = sizeof(client_addr);
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD_STATE;
memcpy( buffer + 1, &connected_gamepad_id, 4 );
res = sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
if (res == SOCKET_ERROR) return FALSE;
res = recvfrom( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len );
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD_STATE || buffer[1] != 1) return FALSE;
memcpy( &gamepad_id, buffer + 2, 4 );
if (gamepad_id != connected_gamepad_id) return FALSE;
memcpy( &buttons, buffer + 6, 2 );
dpad = buffer[8];
memcpy( &thumb_lx, buffer + 9, 2 );
memcpy( &thumb_ly, buffer + 11, 2 );
memcpy( &thumb_rx, buffer + 13, 2 );
memcpy( &thumb_ry, buffer + 15, 2 );
handle_gamepad_input( iface, thumb_lx, thumb_ly, thumb_rx, thumb_ry, buttons, dpad );
return TRUE;
buffer[0] = REQUEST_CODE_GET_GAMEPAD_STATE;
memcpy( buffer + 1, &connected_gamepad_id, 4 );
res = sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
if (res == SOCKET_ERROR) return FALSE;
res = recvfrom( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len );
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD_STATE || buffer[1] != 1) return FALSE;
memcpy( &gamepad_id, buffer + 2, 4 );
if (gamepad_id != connected_gamepad_id) return FALSE;
memcpy( &buttons, buffer + 6, 2 );
dpad = buffer[8];
memcpy( &thumb_lx, buffer + 9, 2 );
memcpy( &thumb_ly, buffer + 11, 2 );
memcpy( &thumb_rx, buffer + 13, 2 );
memcpy( &thumb_ry, buffer + 15, 2 );
handle_gamepad_input( iface, thumb_lx, thumb_ly, thumb_rx, thumb_ry, buttons, dpad );
return TRUE;
}
static void release_gamepad_request( void )
{
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
int client_addr_len;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
int client_addr_len;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
client_addr.sin_port = htons( CLIENT_PORT );
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_RELEASE_GAMEPAD;
sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_RELEASE_GAMEPAD;
sendto( server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len );
}
HRESULT gamepad_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance, DWORD version )
{
if (!create_server_socket()) return DIERR_INPUTLOST;
{
if (!create_server_socket()) return DIERR_INPUTLOST;
return get_gamepad_request( instance, version ) ? DI_OK : DIERR_INPUTLOST;
}
@ -427,12 +427,12 @@ static BOOL CALLBACK init_object_properties( const DIDEVICEOBJECTINSTANCEW *inst
struct gamepad *impl = (struct gamepad *)data;
struct object_properties *properties = impl->base.object_properties + instance->dwOfs / sizeof(LONG);
properties->logical_min = -32768;
properties->logical_min = -32768;
properties->logical_max = 32767;
properties->range_min = 0;
properties->range_min = 0;
properties->range_max = 65535;
properties->saturation = 10000;
properties->granularity = 1;
properties->saturation = 10000;
properties->granularity = 1;
return DIENUM_CONTINUE;
}
@ -444,10 +444,10 @@ HRESULT gamepad_create_device( struct dinput *dinput, const GUID *guid, IDirectI
*out = NULL;
if (!IsEqualGUID( &GUID_Joystick, guid )) return DIERR_DEVICENOTREG;
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
dinput_device_init( &impl->base, &gamepad_vtbl, guid, dinput );
impl->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": struct gamepad*->base.crit");
impl->base.read_event = CreateEventW( NULL, TRUE, FALSE, NULL );
impl->base.read_event = CreateEventW( NULL, TRUE, FALSE, NULL );
gamepad_enum_device( 0, 0, &impl->base.instance, dinput->dwVersion );
impl->base.caps.dwDevType = impl->base.instance.dwDevType;
@ -461,7 +461,7 @@ HRESULT gamepad_create_device( struct dinput *dinput, const GUID *guid, IDirectI
IDirectInputDevice_Release( &impl->base.IDirectInputDevice8W_iface );
return E_OUTOFMEMORY;
}
IDirectInputDevice8_EnumObjects( &impl->base.IDirectInputDevice8W_iface, init_object_properties, impl, DIDFT_ABSAXIS );
if (dinput->dwVersion >= 0x0800)
@ -476,32 +476,32 @@ HRESULT gamepad_create_device( struct dinput *dinput, const GUID *guid, IDirectI
static void gamepad_release( IDirectInputDevice8W *iface )
{
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
CloseHandle( impl->base.read_event );
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
CloseHandle( impl->base.read_event );
}
static HRESULT gamepad_read( IDirectInputDevice8W *iface )
{
get_gamepad_state_request( iface );
Sleep( 16 );
return DI_OK;
{
get_gamepad_state_request( iface );
Sleep( 16 );
return DI_OK;
}
static HRESULT gamepad_acquire( IDirectInputDevice8W *iface )
{
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
SetEvent( impl->base.read_event );
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
SetEvent( impl->base.read_event );
return DI_OK;
}
static HRESULT gamepad_unacquire( IDirectInputDevice8W *iface )
{
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
WaitForSingleObject( impl->base.read_event, INFINITE );
connected_gamepad_id = 0;
release_gamepad_request();
close_server_socket();
struct gamepad *impl = impl_from_IDirectInputDevice8W( iface );
WaitForSingleObject( impl->base.read_event, INFINITE );
connected_gamepad_id = 0;
release_gamepad_request();
close_server_socket();
return DI_OK;
}
@ -527,159 +527,159 @@ static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDE
static void get_device_objects( int *instance_count, DIDEVICEOBJECTINSTANCEW **out )
{
int i, index = 0;
*instance_count = 0;
*out = NULL;
int i, index = 0;
*instance_count = 0;
*out = NULL;
if (mapper_type == MAPPER_TYPE_STANDARD)
{
*instance_count = 17;
DIDEVICEOBJECTINSTANCEW instances[*instance_count];
instances[index].guidType = GUID_XAxis;
instances[index].dwOfs = DIJOFS_X;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"X Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_X;
index++;
instances[index].guidType = GUID_YAxis;
instances[index].dwOfs = DIJOFS_Y;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Y Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Y;
index++;
instances[index].guidType = GUID_ZAxis;
instances[index].dwOfs = DIJOFS_Z;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Z Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Z;
index++;
if (mapper_type == MAPPER_TYPE_STANDARD)
{
*instance_count = 17;
DIDEVICEOBJECTINSTANCEW instances[*instance_count];
instances[index].guidType = GUID_XAxis;
instances[index].dwOfs = DIJOFS_X;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"X Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_X;
index++;
instances[index].guidType = GUID_YAxis;
instances[index].dwOfs = DIJOFS_Y;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Y Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Y;
index++;
instances[index].guidType = GUID_ZAxis;
instances[index].dwOfs = DIJOFS_Z;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Z Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Z;
index++;
instances[index].guidType = GUID_RzAxis;
instances[index].dwOfs = DIJOFS_RZ;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Rz Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RZ;
index++;
for (i = 0; i < 12; i++)
{
instances[index].guidType = GUID_Button,
instances[index].dwOfs = DIJOFS_BUTTON( i ),
instances[index].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ),
swprintf( instances[index].tszName, MAX_PATH, L"Button %d", i );
instances[index].wUsagePage = HID_USAGE_PAGE_BUTTON;
instances[index].wUsage = i + 1;
index++;
}
instances[index].guidType = GUID_POV;
instances[index].dwOfs = DIJOFS_POV( 0 );
instances[index].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 );
swprintf( instances[index].tszName, MAX_PATH, L"POV" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_HATSWITCH;
*out = instances;
}
else if (mapper_type == MAPPER_TYPE_XINPUT)
{
*instance_count = 16;
DIDEVICEOBJECTINSTANCEW instances[*instance_count];
instances[index].guidType = GUID_XAxis;
instances[index].dwOfs = DIJOFS_X;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"X Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_X;
index++;
instances[index].guidType = GUID_YAxis;
instances[index].dwOfs = DIJOFS_Y;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Y Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Y;
index++;
instances[index].guidType = GUID_ZAxis;
instances[index].dwOfs = DIJOFS_Z;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Z Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Z;
index++;
instances[index].guidType = GUID_RzAxis;
instances[index].dwOfs = DIJOFS_RZ;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Rz Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RZ;
index++;
for (i = 0; i < 12; i++)
{
instances[index].guidType = GUID_Button,
instances[index].dwOfs = DIJOFS_BUTTON( i ),
instances[index].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ),
swprintf( instances[index].tszName, MAX_PATH, L"Button %d", i );
instances[index].wUsagePage = HID_USAGE_PAGE_BUTTON;
instances[index].wUsage = i + 1;
index++;
}
instances[index].guidType = GUID_POV;
instances[index].dwOfs = DIJOFS_POV( 0 );
instances[index].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 );
swprintf( instances[index].tszName, MAX_PATH, L"POV" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_HATSWITCH;
*out = instances;
}
else if (mapper_type == MAPPER_TYPE_XINPUT)
{
*instance_count = 16;
DIDEVICEOBJECTINSTANCEW instances[*instance_count];
instances[index].guidType = GUID_XAxis;
instances[index].dwOfs = DIJOFS_X;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"X Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_X;
index++;
instances[index].guidType = GUID_YAxis;
instances[index].dwOfs = DIJOFS_Y;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Y Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Y;
index++;
instances[index].guidType = GUID_ZAxis;
instances[index].dwOfs = DIJOFS_Z;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Z Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_Z;
index++;
instances[index].guidType = GUID_RxAxis;
instances[index].dwOfs = DIJOFS_RX;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Rx Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RX;
index++;
instances[index].guidType = GUID_RxAxis;
instances[index].dwOfs = DIJOFS_RX;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Rx Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RX;
index++;
instances[index].guidType = GUID_RyAxis;
instances[index].dwOfs = DIJOFS_RY;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 4 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Ry Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RY;
index++;
for (i = 0; i < 10; i++)
{
instances[index].guidType = GUID_Button,
instances[index].dwOfs = DIJOFS_BUTTON( i ),
instances[index].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ),
swprintf( instances[index].tszName, MAX_PATH, L"Button %d", i );
instances[index].wUsagePage = HID_USAGE_PAGE_BUTTON;
instances[index].wUsage = i + 1;
index++;
}
instances[index].guidType = GUID_POV;
instances[index].dwOfs = DIJOFS_POV( 0 );
instances[index].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 );
swprintf( instances[index].tszName, MAX_PATH, L"POV" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_HATSWITCH;
*out = instances;
}
instances[index].guidType = GUID_RyAxis;
instances[index].dwOfs = DIJOFS_RY;
instances[index].dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 4 );
instances[index].dwFlags = DIDOI_ASPECTPOSITION;
swprintf( instances[index].tszName, MAX_PATH, L"Ry Axis" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_RY;
index++;
for (i = 0; i < 10; i++)
{
instances[index].guidType = GUID_Button,
instances[index].dwOfs = DIJOFS_BUTTON( i ),
instances[index].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE( i ),
swprintf( instances[index].tszName, MAX_PATH, L"Button %d", i );
instances[index].wUsagePage = HID_USAGE_PAGE_BUTTON;
instances[index].wUsage = i + 1;
index++;
}
instances[index].guidType = GUID_POV;
instances[index].dwOfs = DIJOFS_POV( 0 );
instances[index].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 );
swprintf( instances[index].tszName, MAX_PATH, L"POV" );
instances[index].wUsagePage = HID_USAGE_PAGE_GENERIC;
instances[index].wUsage = HID_USAGE_GENERIC_HATSWITCH;
*out = instances;
}
}
static HRESULT gamepad_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter,
DWORD flags, LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context )
{
int instance_count;
DIDEVICEOBJECTINSTANCEW* instances;
{
int instance_count;
DIDEVICEOBJECTINSTANCEW* instances;
BOOL ret;
DWORD i;
get_device_objects( &instance_count, &instances );
get_device_objects( &instance_count, &instances );
for (i = 0; i < instance_count; i++)
{
instances[i].dwSize = sizeof(DIDEVICEOBJECTINSTANCEW);
instances[i].wReportId = 1;
instances[i].dwSize = sizeof(DIDEVICEOBJECTINSTANCEW);
instances[i].wReportId = 1;
ret = try_enum_object( filter, flags, callback, instances + i, context );
if (ret != DIENUM_CONTINUE) return DIENUM_STOP;
}
@ -722,7 +722,7 @@ static HRESULT gamepad_get_property(IDirectInputDevice8W *iface, DWORD property,
{
DIPROPGUIDANDPATH *value = (DIPROPGUIDANDPATH *)header;
value->guidClass = GUID_DEVCLASS_HIDCLASS;
lstrcpynW( value->wszPath, L"virtual#vid_045e&pid_028e&ig_00", MAX_PATH );
lstrcpynW( value->wszPath, L"virtual#vid_045e&pid_028e&ig_00", MAX_PATH );
return DI_OK;
}
}

View File

@ -74,15 +74,15 @@ struct xinput_controller
XINPUT_CAPABILITIES caps;
XINPUT_STATE state;
BOOL enabled;
BOOL connected;
int id;
BOOL connected;
int id;
};
static struct xinput_controller controller =
{
.enabled = FALSE,
.connected = FALSE,
.id = 0
.enabled = FALSE,
.connected = FALSE,
.id = 0
};
static HMODULE xinput_instance;
@ -97,93 +97,93 @@ static char xinput_min_index = 3;
static void close_server_socket(void)
{
if (server_sock != INVALID_SOCKET)
{
closesocket(server_sock);
server_sock = INVALID_SOCKET;
}
if (winsock_loaded)
{
WSACleanup();
winsock_loaded = FALSE;
}
if (server_sock != INVALID_SOCKET)
{
closesocket(server_sock);
server_sock = INVALID_SOCKET;
}
if (winsock_loaded)
{
WSACleanup();
winsock_loaded = FALSE;
}
}
static BOOL create_server_socket(void)
{
WSADATA wsa_data;
struct sockaddr_in server_addr;
int res;
close_server_socket();
winsock_loaded = WSAStartup(MAKEWORD(2,2), &wsa_data) == NO_ERROR;
if (!winsock_loaded) return FALSE;
{
WSADATA wsa_data;
struct sockaddr_in server_addr;
int res;
close_server_socket();
winsock_loaded = WSAStartup(MAKEWORD(2,2), &wsa_data) == NO_ERROR;
if (!winsock_loaded) return FALSE;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(SERVER_PORT);
server_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (server_sock == INVALID_SOCKET) return FALSE;
if (server_sock == INVALID_SOCKET) return FALSE;
res = bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (res == SOCKET_ERROR) return FALSE;
return TRUE;
if (res == SOCKET_ERROR) return FALSE;
return TRUE;
}
static int get_gamepad_request(void)
{
int res, client_addr_len, gamepad_id;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
int res, client_addr_len, gamepad_id;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(CLIENT_PORT);
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD;
buffer[1] = 1;
res = sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
if (res == SOCKET_ERROR) return 0;
res = recvfrom(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD) return 0;
memcpy(&gamepad_id, buffer + 1, 4);
return gamepad_id;
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD;
buffer[1] = 1;
res = sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
if (res == SOCKET_ERROR) return 0;
res = recvfrom(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD) return 0;
memcpy(&gamepad_id, buffer + 1, 4);
return gamepad_id;
}
static void release_gamepad_request(void)
{
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
int client_addr_len;
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
int client_addr_len;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(CLIENT_PORT);
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_RELEASE_GAMEPAD;
sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_RELEASE_GAMEPAD;
sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
}
static BOOL controller_check_caps(void)
{
XINPUT_CAPABILITIES *caps = &controller.caps;
memset(caps, 0, sizeof(XINPUT_CAPABILITIES));
caps->Gamepad.wButtons = 0xffff;
caps->Gamepad.bLeftTrigger = (1u << (sizeof(caps->Gamepad.bLeftTrigger) + 1)) - 1;
caps->Gamepad.bRightTrigger = (1u << (sizeof(caps->Gamepad.bRightTrigger) + 1)) - 1;
caps->Gamepad.sThumbLX = (1u << (sizeof(caps->Gamepad.sThumbLX) + 1)) - 1;
caps->Gamepad.sThumbLY = (1u << (sizeof(caps->Gamepad.sThumbLY) + 1)) - 1;
caps->Gamepad.sThumbRX = (1u << (sizeof(caps->Gamepad.sThumbRX) + 1)) - 1;
caps->Gamepad.sThumbRY = (1u << (sizeof(caps->Gamepad.sThumbRY) + 1)) - 1;
caps->Gamepad.bRightTrigger = (1u << (sizeof(caps->Gamepad.bRightTrigger) + 1)) - 1;
caps->Gamepad.sThumbLX = (1u << (sizeof(caps->Gamepad.sThumbLX) + 1)) - 1;
caps->Gamepad.sThumbLY = (1u << (sizeof(caps->Gamepad.sThumbLY) + 1)) - 1;
caps->Gamepad.sThumbRX = (1u << (sizeof(caps->Gamepad.sThumbRX) + 1)) - 1;
caps->Gamepad.sThumbRY = (1u << (sizeof(caps->Gamepad.sThumbRY) + 1)) - 1;
caps->Type = XINPUT_DEVTYPE_GAMEPAD;
caps->SubType = XINPUT_DEVSUBTYPE_GAMEPAD;
@ -199,54 +199,54 @@ static void controller_disable(void)
static void controller_destroy(void)
{
release_gamepad_request();
xinput_min_index = 3;
release_gamepad_request();
xinput_min_index = 3;
if (controller.connected)
{
controller_disable();
controller.connected = FALSE;
}
close_server_socket();
close_server_socket();
}
static void controller_enable(void)
{
if (controller.enabled) return;
controller.enabled = TRUE;
SetEvent(update_event);
SetEvent(update_event);
}
static void controller_init(void)
{
memset(&controller.state, 0, sizeof(controller.state));
controller.enabled = FALSE;
controller.connected = TRUE;
controller_check_caps();
controller.connected = TRUE;
controller_check_caps();
controller_enable();
}
static void controller_check_connection(void)
{
controller.id = 0;
if (server_sock == INVALID_SOCKET) create_server_socket();
int gamepad_id = get_gamepad_request();
if (gamepad_id > 0)
{
controller.id = gamepad_id;
if (!controller.connected)
{
controller.id = gamepad_id;
controller_init();
}
}
controller.id = 0;
if (server_sock == INVALID_SOCKET) create_server_socket();
int gamepad_id = get_gamepad_request();
if (gamepad_id > 0)
{
controller.id = gamepad_id;
if (!controller.connected)
{
controller.id = gamepad_id;
controller_init();
}
}
}
static void stop_update_thread(void)
{
ResetEvent(update_event);
ResetEvent(update_event);
SetEvent(stop_event);
WaitForSingleObject(done_event, INFINITE);
@ -254,67 +254,67 @@ static void stop_update_thread(void)
CloseHandle(stop_event);
CloseHandle(done_event);
CloseHandle(update_event);
controller_destroy();
}
static void read_controller_state(void)
{
char buffer[BUFFER_SIZE];
int i, res, client_addr_len, gamepad_id;
char dpad;
short buttons, thumb_lx, thumb_ly, thumb_rx, thumb_ry;
struct sockaddr_in client_addr;
XINPUT_STATE state;
char buffer[BUFFER_SIZE];
int i, res, client_addr_len, gamepad_id;
char dpad;
short buttons, thumb_lx, thumb_ly, thumb_rx, thumb_ry;
struct sockaddr_in client_addr;
XINPUT_STATE state;
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(CLIENT_PORT);
client_addr_len = sizeof(client_addr);
client_addr_len = sizeof(client_addr);
buffer[0] = REQUEST_CODE_GET_GAMEPAD_STATE;
memcpy(buffer + 1, &controller.id, 4);
res = sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
if (res == SOCKET_ERROR) return;
res = recvfrom(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD_STATE || buffer[1] != 1) return;
memcpy(&gamepad_id, buffer + 2, 4);
if (gamepad_id != controller.id) return;
memcpy(&buttons, buffer + 6, 2);
dpad = buffer[8];
memcpy(&thumb_lx, buffer + 9, 2);
memcpy(&thumb_ly, buffer + 11, 2);
memcpy(&thumb_rx, buffer + 13, 2);
memcpy(&thumb_ry, buffer + 15, 2);
buffer[0] = REQUEST_CODE_GET_GAMEPAD_STATE;
memcpy(buffer + 1, &controller.id, 4);
res = sendto(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, client_addr_len);
if (res == SOCKET_ERROR) return;
res = recvfrom(server_sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &client_addr_len);
if (res == SOCKET_ERROR || buffer[0] != REQUEST_CODE_GET_GAMEPAD_STATE || buffer[1] != 1) return;
memcpy(&gamepad_id, buffer + 2, 4);
if (gamepad_id != controller.id) return;
memcpy(&buttons, buffer + 6, 2);
dpad = buffer[8];
memcpy(&thumb_lx, buffer + 9, 2);
memcpy(&thumb_ly, buffer + 11, 2);
memcpy(&thumb_rx, buffer + 13, 2);
memcpy(&thumb_ry, buffer + 15, 2);
state.Gamepad.wButtons = 0;
for (i = 0; i < 10; i++)
{
if ((buttons & (1<<i))) {
switch (i)
{
case IDX_BUTTON_A: state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
case IDX_BUTTON_B: state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
case IDX_BUTTON_X: state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
case IDX_BUTTON_Y: state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
case IDX_BUTTON_L1: state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
case IDX_BUTTON_R1: state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
case IDX_BUTTON_SELECT: state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
case IDX_BUTTON_START: state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
case IDX_BUTTON_L3: state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
case IDX_BUTTON_R3: state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
}
}
{
if ((buttons & (1<<i))) {
switch (i)
{
case IDX_BUTTON_A: state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
case IDX_BUTTON_B: state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
case IDX_BUTTON_X: state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
case IDX_BUTTON_Y: state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
case IDX_BUTTON_L1: state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
case IDX_BUTTON_R1: state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
case IDX_BUTTON_SELECT: state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
case IDX_BUTTON_START: state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
case IDX_BUTTON_L3: state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
case IDX_BUTTON_R3: state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
}
}
}
state.Gamepad.bLeftTrigger = (buttons & (1<<10)) ? 255 : 0;
state.Gamepad.bRightTrigger = (buttons & (1<<11)) ? 255 : 0;
state.Gamepad.bLeftTrigger = (buttons & (1<<10)) ? 255 : 0;
state.Gamepad.bRightTrigger = (buttons & (1<<11)) ? 255 : 0;
switch (dpad)
{
@ -328,41 +328,41 @@ static void read_controller_state(void)
case 7: state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP; break;
}
state.Gamepad.sThumbLX = thumb_lx;
state.Gamepad.sThumbLY = -thumb_ly;
state.Gamepad.sThumbRX = thumb_rx;
state.Gamepad.sThumbRY = -thumb_ry;
state.Gamepad.sThumbLX = thumb_lx;
state.Gamepad.sThumbLY = -thumb_ly;
state.Gamepad.sThumbRX = thumb_rx;
state.Gamepad.sThumbRY = -thumb_ry;
state.dwPacketNumber = controller.state.dwPacketNumber + 1;
controller.state = state;
}
static DWORD WINAPI controller_update_thread_proc(void *param)
{
DWORD last_time, curr_time;
const int num_events = 2;
DWORD last_time, curr_time;
const int num_events = 2;
HANDLE events[num_events];
DWORD ret = WAIT_TIMEOUT;
SetThreadDescription(GetCurrentThread(), L"wine_xinput_controller_update");
SetEvent(start_event);
last_time = GetCurrentTime();
last_time = GetCurrentTime();
do
{
curr_time = GetCurrentTime();
curr_time = GetCurrentTime();
if (ret == WAIT_TIMEOUT || (curr_time - last_time) >= 2000) {
controller_check_connection();
last_time = curr_time;
}
if (controller.connected && controller.enabled)
{
read_controller_state();
Sleep(16);
}
events[0] = update_event;
events[1] = stop_event;
controller_check_connection();
last_time = curr_time;
}
if (controller.connected && controller.enabled)
{
read_controller_state();
Sleep(16);
}
events[0] = update_event;
events[1] = stop_event;
}
while ((ret = MsgWaitForMultipleObjectsEx(num_events, events, 2000, QS_ALLINPUT, MWMO_ALERTABLE)) < num_events - 1 ||
ret == num_events || ret == WAIT_TIMEOUT);
@ -386,7 +386,7 @@ static BOOL WINAPI start_update_thread_once(INIT_ONCE *once, void *param, void *
if (!done_event) ERR("failed to create done event, error %lu\n", GetLastError());
update_event = CreateEventA(NULL, TRUE, FALSE, NULL);
if (!update_event) ERR("failed to create update event, error %lu\n", GetLastError());
if (!update_event) ERR("failed to create update event, error %lu\n", GetLastError());
thread = CreateThread(NULL, 0, controller_update_thread_proc, NULL, 0, NULL);
if (!thread) ERR("failed to create update thread, error %lu\n", GetLastError());
@ -404,7 +404,7 @@ static void start_update_thread(void)
static BOOL controller_is_connected(DWORD index)
{
return index == 0 && controller.connected;
return index == 0 && controller.connected;
}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
@ -435,9 +435,9 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
be sent */
start_update_thread();
if (!controller.connected) return;
if (enable) controller_enable();
else controller_disable();
if (!controller.connected) return;
if (enable) controller_enable();
else controller_disable();
}
DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION *vibration)
@ -447,7 +447,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION *vib
start_update_thread();
if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
if (!controller_is_connected(index)) return ERROR_DEVICE_NOT_CONNECTED;
if (!controller_is_connected(index)) return ERROR_DEVICE_NOT_CONNECTED;
return ERROR_SUCCESS;
}
@ -461,8 +461,8 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
start_update_thread();
if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
if (index < xinput_min_index) xinput_min_index = index;
if (index == xinput_min_index) index = 0;
if (index < xinput_min_index) xinput_min_index = index;
if (index == xinput_min_index) index = 0;
if (!controller_is_connected(index)) return ERROR_DEVICE_NOT_CONNECTED;
*state = controller.state;
@ -496,8 +496,8 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetKeystroke(DWORD index, DWORD reserved, P
TRACE("index %lu, reserved %lu, keystroke %p.\n", index, reserved, keystroke);
if (index >= XUSER_MAX_COUNT && index != XUSER_INDEX_ANY) return ERROR_BAD_ARGUMENTS;
if (!controller_is_connected(index)) return ERROR_DEVICE_NOT_CONNECTED;
if (!controller_is_connected(index)) return ERROR_DEVICE_NOT_CONNECTED;
return ERROR_SUCCESS;
}