146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SDL_JOYSTICK_WINMM 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */ 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define WIN32_LEAN_AND_MEAN 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <windows.h> 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <mmsystem.h> 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <regstr.h> 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_events.h" 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_joystick.h" 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_sysjoystick.h" 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_joystick_c.h" 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_JOYSTICKS 16 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_AXES 6 /* each joystick can have up to 6 axes */ 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_BUTTONS 32 /* and 32 buttons */ 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define AXIS_MIN -32768 /* minimum value for axis coordinate */ 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define AXIS_MAX 32767 /* maximum value for axis coordinate */ 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* limit axis to 256 possible positions to filter out noise */ 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256) 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define JOY_BUTTON_FLAG(n) (1<<n) 4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* array to hold joystick ID values */ 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic UINT SYS_JoystickID[MAX_JOYSTICKS]; 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic JOYCAPS SYS_Joystick[MAX_JOYSTICKS]; 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic char *SYS_JoystickName[MAX_JOYSTICKS]; 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The private structure used to keep track of a joystick */ 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct joystick_hwdata 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* joystick ID */ 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner UINT id; 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* values used to translate device-specific coordinates into 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL-standard ranges */ 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner struct _transaxis { 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int offset; 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner float scale; 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } transaxis[6]; 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}; 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Convert a win32 Multimedia API return code to a text message */ 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SetMMerror(char *function, int code); 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic char *GetJoystickName(int index, const char *szRegKey) 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* added 7/24/2004 by Eckhard Stolberg */ 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner see if there is a joystick for the current 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner index (1-16) listed in the registry 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char *name = NULL; 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner HKEY hTopKey; 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner HKEY hKey; 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner DWORD regsize; 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner LONG regresult; 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char regkey[256]; 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char regvalue[256]; 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner char regname[256]; 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s\\%s", 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner REGSTR_PATH_JOYCONFIG, szRegKey, REGSTR_KEY_JOYCURR); 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hTopKey = HKEY_LOCAL_MACHINE; 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (regresult != ERROR_SUCCESS) { 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner hTopKey = HKEY_CURRENT_USER; 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (regresult != ERROR_SUCCESS) { 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return NULL; 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* find the registry key name for the joystick's properties */ 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regsize = sizeof(regname); 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(regvalue, SDL_arraysize(regvalue), "Joystick%d%s", index+1, REGSTR_VAL_JOYOEMNAME); 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE)regname, ®size); 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner RegCloseKey(hKey); 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (regresult != ERROR_SUCCESS) { 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return NULL; 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* open that registry key */ 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM, regname); 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (regresult != ERROR_SUCCESS) { 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return NULL; 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* find the size for the OEM name text */ 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regsize = sizeof(regvalue); 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, ®size); 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (regresult == ERROR_SUCCESS) { 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* allocate enough memory for the OEM name text ... */ 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner name = (char *) SDL_malloc(regsize); 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( name ) { 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* ... and read it from the registry */ 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner regresult = RegQueryValueExA(hKey, 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner REGSTR_VAL_JOYOEMNAME, 0, 0, 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (LPBYTE) name, ®size); 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner RegCloseKey(hKey); 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(name); 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to scan the system for joysticks. 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This function should set SDL_numjoysticks to the number of available 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * joysticks. Joystick 0 should be the system default joystick. 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * It should return 0, or -1 on an unrecoverable fatal error. 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SYS_JoystickInit(void) 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int maxdevs; 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int numdevs; 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner JOYINFOEX joyinfo; 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner JOYCAPS joycaps; 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MMRESULT result; 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Reset the joystick ID & name mapping tables */ 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = 0; i < MAX_JOYSTICKS; ++i ) { 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYS_JoystickID[i] = 0; 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYS_JoystickName[i] = NULL; 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Loop over all potential joystick devices */ 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner numdevs = 0; 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner maxdevs = joyGetNumDevs(); 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = JOYSTICKID1; i < maxdevs && numdevs < MAX_JOYSTICKS; ++i ) { 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joyinfo.dwSize = sizeof(joyinfo); 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joyinfo.dwFlags = JOY_RETURNALL; 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner result = joyGetPosEx(i, &joyinfo); 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( result == JOYERR_NOERROR ) { 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner result = joyGetDevCaps(i, &joycaps, sizeof(joycaps)); 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( result == JOYERR_NOERROR ) { 16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYS_JoystickID[numdevs] = i; 16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYS_Joystick[numdevs] = joycaps; 16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYS_JoystickName[numdevs] = GetJoystickName(i, joycaps.szRegKey); 16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner numdevs++; 16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(numdevs); 17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to get the device-dependent name of a joystick */ 17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerconst char *SDL_SYS_JoystickName(int index) 17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SYS_JoystickName[index] != NULL ) { 17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(SYS_JoystickName[index]); 18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(SYS_Joystick[index].szPname); 18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to open a joystick for use. 18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner The joystick to open is specified by the index field of the joystick. 18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This should fill the nbuttons and naxes fields of the joystick structure. 18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner It returns 0, or -1 if there is an error. 18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SYS_JoystickOpen(SDL_Joystick *joystick) 19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int index, i; 19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int caps_flags[MAX_AXES-2] = 19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; 19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int axis_min[MAX_AXES], axis_max[MAX_AXES]; 19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* shortcut */ 19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner index = joystick->index; 20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[0] = SYS_Joystick[index].wXmin; 20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[0] = SYS_Joystick[index].wXmax; 20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[1] = SYS_Joystick[index].wYmin; 20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[1] = SYS_Joystick[index].wYmax; 20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[2] = SYS_Joystick[index].wZmin; 20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[2] = SYS_Joystick[index].wZmax; 20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[3] = SYS_Joystick[index].wRmin; 20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[3] = SYS_Joystick[index].wRmax; 20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[4] = SYS_Joystick[index].wUmin; 20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[4] = SYS_Joystick[index].wUmax; 21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_min[5] = SYS_Joystick[index].wVmin; 21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner axis_max[5] = SYS_Joystick[index].wVmax; 21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* allocate memory for system specific hardware data */ 21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); 21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (joystick->hwdata == NULL) 21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(-1); 21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); 22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* set hardware data */ 22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata->id = SYS_JoystickID[index]; 22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = 0; i < MAX_AXES; ++i ) { 22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { 22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata->transaxis[i].offset = 22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner AXIS_MIN - axis_min[i]; 22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata->transaxis[i].scale = 22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); 23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata->transaxis[i].offset = 0; 23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ 23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* fill nbuttons, naxes, and nhats fields */ 23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->nbuttons = SYS_Joystick[index].wNumButtons; 23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->naxes = SYS_Joystick[index].wNumAxes; 23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { 24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->nhats = 1; 24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joystick->nhats = 0; 24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(0); 24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic Uint8 TranslatePOV(DWORD value) 24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 pos; 25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos = SDL_HAT_CENTERED; 25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( value != JOY_POVCENTERED ) { 25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { 25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos |= SDL_HAT_UP; 25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { 25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos |= SDL_HAT_RIGHT; 25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { 26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos |= SDL_HAT_DOWN; 26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( value > JOY_POVBACKWARD ) { 26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos |= SDL_HAT_LEFT; 26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(pos); 26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to update the state of a joystick - called as a device poll. 27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This function shouldn't update the joystick structure directly, 27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * but instead should call SDL_PrivateJoystick*() to deliver events 27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * and update joystick device state. 27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) 27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MMRESULT result; 27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, 27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; 28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner DWORD pos[MAX_AXES]; 28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner struct _transaxis *transaxis; 28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int value, change; 28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner JOYINFOEX joyinfo; 28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joyinfo.dwSize = sizeof(joyinfo); 28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; 28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! joystick->hats ) { 28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); 28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner result = joyGetPosEx(joystick->hwdata->id, &joyinfo); 29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( result != JOYERR_NOERROR ) { 29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SetMMerror("joyGetPosEx", result); 29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return; 29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* joystick motion events */ 29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[0] = joyinfo.dwXpos; 29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[1] = joyinfo.dwYpos; 29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[2] = joyinfo.dwZpos; 30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[3] = joyinfo.dwRpos; 30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[4] = joyinfo.dwUpos; 30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos[5] = joyinfo.dwVpos; 30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner transaxis = joystick->hwdata->transaxis; 30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for (i = 0; i < joystick->naxes; i++) { 30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (joyinfo.dwFlags & flags[i]) { 30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); 30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner change = (value - joystick->axes[i]); 30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { 31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); 31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* joystick button events */ 31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { 31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for ( i = 0; i < joystick->nbuttons; ++i ) { 31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { 31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! joystick->buttons[i] ) { 32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); 32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( joystick->buttons[i] ) { 32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); 32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* joystick hat events */ 33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( joyinfo.dwFlags & JOY_RETURNPOV ) { 33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint8 pos; 33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner pos = TranslatePOV(joyinfo.dwPOV); 33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( pos != joystick->hats[0] ) { 33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_PrivateJoystickHat(joystick, 0, pos); 33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to close a joystick after use */ 34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_JoystickClose(SDL_Joystick *joystick) 34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if (joystick->hwdata != NULL) { 34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* free system specific hardware data */ 34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(joystick->hwdata); 34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Function to perform any system-specific joystick related cleanup */ 35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_JoystickQuit(void) 35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int i; 35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner for (i = 0; i < MAX_JOYSTICKS; i++) { 35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( SYS_JoystickName[i] != NULL ) { 35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(SYS_JoystickName[i]); 35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* implementation functions */ 36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SetMMerror(char *function, int code) 36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner static char *error; 36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner static char errbuf[1024]; 36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner errbuf[0] = 0; 36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (code) 37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner { 37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case MMSYSERR_NODRIVER: 37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner error = "Joystick driver not present"; 37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case MMSYSERR_INVALPARAM: 37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case JOYERR_PARMS: 37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner error = "Invalid parameter(s)"; 37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case MMSYSERR_BADDEVICEID: 38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner error = "Bad device ID"; 38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case JOYERR_UNPLUGGED: 38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner error = "Joystick not attached"; 38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case JOYERR_NOCANDO: 38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner error = "Can't capture joystick input"; 39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(errbuf, SDL_arraysize(errbuf), 39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner "%s: Unknown Multimedia system error: 0x%x", 39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner function, code); 39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! errbuf[0] ) { 40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); 40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("%s", errbuf); 40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* SDL_JOYSTICK_WINMM */ 406