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, &regsize);
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, &regsize);
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, &regsize);
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