diff --git a/stella/src/win32/README-SDL.txt b/stella/src/win32/README-SDL.txt new file mode 100644 index 000000000..5036e6bad --- /dev/null +++ b/stella/src/win32/README-SDL.txt @@ -0,0 +1,47 @@ + +Please distribute this file with the SDL runtime environment: + +The Simple DirectMedia Layer (SDL for short) is a cross-platfrom library +designed to make it easy to write multi-media software, such as games and +emulators. + +The Simple DirectMedia Layer library source code is available from: +http://www.libsdl.org/ + +This library is distributed under the terms of the GNU LGPL license: +http://www.gnu.org/copyleft/lesser.html + +--------------------------------------------------------------------------- + +The SDL.dll library included in this package has been modified to +automatically work with the Stelladaptor device. + +As per the GPL, all modifications to SDL must be provided and documented. +The included patchfile 'SDL_mmjoystick_1.2.7.diff' can be used with +SDL-1.2.7.zip (located on the main SDL web page). + +To rebuild the SDL.dll file, follow the instructions below: + +1) Get the 'SDL-1.2.7.zip' package from the main SDL website and + unzip it. + +2) Apply the patchfile 'SDL_mmjoystick_1.2.7.diff' to the SDL-1.2.7 + directory (under Linux: patch -p0 < SDL_mmjoystick_1.2.7.diff). + +3) Build the SDL.dll library from within Visual C++ (you may need the DX5 + development files). + + +Notes: + +1) Credit for the bulk of the patchfile goes to Glenn Maynard. + +2) Future versions of SDL will hopefully have this patch integrated. + +3) The included SDL.dll file has not been extensively tested. It is + believed to be compatible with the most common input devices, + but support may not be present for buttons on esoteric devices + (hats, sliders, etc). If the included version of SDL.dll doesn't + support your particular input device (and you have no need for + Stelladaptor support), you can use the standard SDL.dll from + the main SDL website. diff --git a/stella/src/win32/SDL_mmjoystick_1.2.7.diff b/stella/src/win32/SDL_mmjoystick_1.2.7.diff new file mode 100644 index 000000000..083d02a09 --- /dev/null +++ b/stella/src/win32/SDL_mmjoystick_1.2.7.diff @@ -0,0 +1,696 @@ +--- SDL-1.2.7/src/joystick/win32/SDL_mmjoystick.c 2004-02-18 09:22:02.000000000 -0330 ++++ SDL-1.2.7/src/joystick/win32/SDL_mmjoystick.c 2004-07-15 14:43:57.623276184 -0230 +@@ -22,12 +22,19 @@ + + #ifdef SAVE_RCSID + static char rcsid = +- "@(#) $Id: SDL_mmjoystick_1.2.7.diff,v 1.1 2004-07-15 18:08:55 stephena Exp $"; ++ "@(#) $Id: SDL_mmjoystick_1.2.7.diff,v 1.1 2004-07-15 18:08:55 stephena Exp $"; + #endif + +-/* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */ ++/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de ++ * A. Formiga's WINMM driver. ++ * ++ * Hats and sliders are completely untested; the app I'm writing this for mostly ++ * doesn't use them and I don't own any joysticks with them. ++ * ++ * We don't bother to use event notification here. It doesn't seem to work ++ * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and ++ * let it return 0 events. */ + +-#include + #include /* For the definition of NULL */ + + #include "SDL_error.h" +@@ -35,12 +42,28 @@ + #include "SDL_sysjoystick.h" + #include "SDL_joystick_c.h" + +-#include +-#include ++#ifdef _XBOX ++ #include ++#else ++ #include ++#endif ++ ++#define DIRECTINPUT_VERSION 0x0500 ++#include ++ ++#include "SDL_active.h" ++ ++#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ ++ ++extern HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); ++ ++static LPDIRECTINPUT dinput = NULL; ++extern HINSTANCE SDL_Instance; + + #define MAX_JOYSTICKS 16 + #define MAX_AXES 6 /* each joystick can have up to 6 axes */ + #define MAX_BUTTONS 32 /* and 32 buttons */ ++#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */ + #define AXIS_MIN -32768 /* minimum value for axis coordinate */ + #define AXIS_MAX 32767 /* maximum value for axis coordinate */ + /* limit axis to 256 possible positions to filter out noise */ +@@ -48,27 +71,148 @@ + #define JOY_BUTTON_FLAG(n) (1<= MAX_JOYSTICKS ) ++ return DIENUM_STOP; + ++ return DIENUM_CONTINUE; ++} ++ ++static BOOL CALLBACK DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, ++ LPVOID pvRef) ++{ ++ SDL_Joystick *joystick = (SDL_Joystick*)pvRef; ++ HRESULT result; ++ input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; ++ const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS; ++ if(!(dev->dwType & SupportedMask)) ++ return DIENUM_CONTINUE; /* unsupported */ ++ ++ in->ofs = dev->dwOfs; ++ ++ if(dev->dwType & DIDFT_BUTTON) { ++ in->type = BUTTON; ++ in->num = joystick->nbuttons; ++ joystick->nbuttons++; ++ } else if(dev->dwType & DIDFT_POV) { ++ in->type = HAT; ++ in->num = joystick->nhats; ++ joystick->nhats++; ++ } else { /* dev->dwType & DIDFT_AXIS */ ++ DIPROPRANGE diprg; ++ DIPROPDWORD dilong; ++ ++ in->type = AXIS; ++ in->num = joystick->naxes; ++ ++ diprg.diph.dwSize = sizeof(diprg); ++ diprg.diph.dwHeaderSize = sizeof(diprg.diph); ++ diprg.diph.dwObj = dev->dwOfs; ++ diprg.diph.dwHow = DIPH_BYOFFSET; ++ diprg.lMin = AXIS_MIN; ++ diprg.lMax = AXIS_MAX; ++ ++ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, DIPROP_RANGE, &diprg.diph); ++ if ( result != DI_OK ) ++ return DIENUM_CONTINUE; /* don't use this axis */ ++ ++ /* Set dead zone to 0. */ ++ dilong.diph.dwSize = sizeof(dilong); ++ dilong.diph.dwHeaderSize = sizeof(dilong.diph); ++ dilong.diph.dwObj = dev->dwOfs; ++ dilong.diph.dwHow = DIPH_BYOFFSET; ++ dilong.dwData = 0; ++ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, DIPROP_DEADZONE, &dilong.diph); ++ if ( result != DI_OK ) ++ return DIENUM_CONTINUE; /* don't use this axis */ ++ ++ joystick->naxes++; ++ } ++ ++ joystick->hwdata->NumInputs++; ++ ++ if(joystick->hwdata->NumInputs == MAX_INPUTS) ++ return DIENUM_STOP; /* too many */ ++ ++ return DIENUM_CONTINUE; ++} + + /* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available +@@ -77,51 +221,32 @@ + */ + int SDL_SYS_JoystickInit(void) + { +- int i; +- int maxdevs; +- int numdevs; +- JOYINFOEX joyinfo; +- JOYCAPS joycaps; +- MMRESULT result; ++ HRESULT result; + +- numdevs = 0; +- maxdevs = joyGetNumDevs(); +- +- if ( maxdevs > MAX_JOYSTICKS ) { +- maxdevs = MAX_JOYSTICKS; +- } ++ SYS_NumJoysticks = 0; + +- +- for ( i = 0; i < MAX_JOYSTICKS; i++ ) { +- SYS_JoystickID[i] = JOYSTICKID1 + i; ++ /* Create the DirectInput object */ ++ result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, ++ &dinput, NULL); ++ if ( result != DI_OK ) { ++ SetDIerror("DirectInputCreate", result); ++ return(-1); + } + ++ result = IDirectInput_EnumDevices(dinput, ++ DIDEVTYPE_JOYSTICK, ++ EnumJoysticksCallback, ++ NULL, ++ DIEDFL_ATTACHEDONLY ); + +- for ( i = 0; (i < maxdevs); ++i ) { +- +- /* added 8/31/2001 By Vitaliy Mikitchenko */ +- joyinfo.dwSize = sizeof(joyinfo); +- joyinfo.dwFlags = JOY_RETURNALL; +- /* end addition */ +- +- result = joyGetPosEx(SYS_JoystickID[i], &joyinfo); +- if ( result == JOYERR_NOERROR ) { +- result = joyGetDevCaps(SYS_JoystickID[i], &joycaps, sizeof(joycaps)); +- if ( result == JOYERR_NOERROR ) { +- SYS_JoystickID[numdevs] = SYS_JoystickID[i]; +- SYS_Joystick[numdevs] = joycaps; +- numdevs++; +- } +- } +- } +- return(numdevs); ++ return SYS_NumJoysticks; + } + + /* Function to get the device-dependent name of a joystick */ + const char *SDL_SYS_JoystickName(int index) + { + /***-> test for invalid index ? */ +- return(SYS_Joystick[index].szPname); ++ return(SYS_Joystick[index].tszProductName); + } + + /* Function to open a joystick for use. +@@ -131,26 +256,8 @@ + */ + int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) + { +- int index, i; +- int caps_flags[MAX_AXES-2] = +- { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; +- int axis_min[MAX_AXES], axis_max[MAX_AXES]; +- +- +- /* shortcut */ +- index = joystick->index; +- axis_min[0] = SYS_Joystick[index].wXmin; +- axis_max[0] = SYS_Joystick[index].wXmax; +- axis_min[1] = SYS_Joystick[index].wYmin; +- axis_max[1] = SYS_Joystick[index].wYmax; +- axis_min[2] = SYS_Joystick[index].wZmin; +- axis_max[2] = SYS_Joystick[index].wZmax; +- axis_min[3] = SYS_Joystick[index].wRmin; +- axis_max[3] = SYS_Joystick[index].wRmax; +- axis_min[4] = SYS_Joystick[index].wUmin; +- axis_max[4] = SYS_Joystick[index].wUmax; +- axis_min[5] = SYS_Joystick[index].wVmin; +- axis_max[5] = SYS_Joystick[index].wVmax; ++ HRESULT result; ++ LPDIRECTINPUTDEVICE device; + + /* allocate memory for system specific hardware data */ + joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata)); +@@ -160,52 +267,114 @@ + return(-1); + } + memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); ++ joystick->hwdata->buffered = 1; ++ ++ result = IDirectInput_CreateDevice(dinput, &SYS_Joystick[joystick->index].guidInstance, ++ &device, NULL); ++ if ( result != DI_OK ) { ++ SetDIerror("DirectInput::CreateDevice", result); ++ return(-1); ++ } + +- /* set hardware data */ +- joystick->hwdata->id = SYS_JoystickID[index]; +- for ( i = 0; i < MAX_AXES; ++i ) { +- if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { +- joystick->hwdata->transaxis[i].offset = +- AXIS_MIN - axis_min[i]; +- joystick->hwdata->transaxis[i].scale = +- (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); +- } else { +- joystick->hwdata->transaxis[i].offset = 0; +- joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ +- } ++ result = IDirectInputDevice_QueryInterface(device, ++ &IID_IDirectInputDevice2, (LPVOID *)&joystick->hwdata->InputDevice); ++ IDirectInputDevice_Release(device); ++ if ( result != DI_OK ) { ++ SetDIerror("DirectInputDevice::QueryInterface", result); ++ return(-1); + } + +- /* fill nbuttons, naxes, and nhats fields */ +- joystick->nbuttons = SYS_Joystick[index].wNumButtons; +- joystick->naxes = SYS_Joystick[index].wNumAxes; +- if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { +- joystick->nhats = 1; +- } else { +- joystick->nhats = 0; ++ result = IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->InputDevice, SDL_Window, ++ DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); ++ if ( result != DI_OK ) { ++ SetDIerror("DirectInputDevice::SetCooperativeLevel", result); ++ return(-1); ++ } ++ ++ result = IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice, &c_dfDIJoystick); ++ if ( result != DI_OK ) { ++ SetDIerror("DirectInputDevice::SetDataFormat", result); ++ return(-1); ++ } ++ ++ IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice, ++ DIJoystick_EnumDevObjectsProc, ++ joystick, ++ DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); ++ ++ { ++ DIPROPDWORD dipdw; ++ memset(&dipdw, 0, sizeof(dipdw)); ++ dipdw.diph.dwSize = sizeof(dipdw); ++ dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); ++ dipdw.diph.dwObj = 0; ++ dipdw.diph.dwHow = DIPH_DEVICE; ++ dipdw.dwData = INPUT_QSIZE; ++ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, ++ DIPROP_BUFFERSIZE, &dipdw.diph); ++ ++ if ( result == DI_POLLEDDEVICE ) ++ { ++ /* This device doesn't support buffering, so we're forced ++ * to use less reliable polling. */ ++ joystick->hwdata->buffered = 0; ++ } else if ( result != DI_OK ) { ++ SetDIerror("DirectInputDevice::SetProperty", result); ++ return(-1); ++ } + } ++ + return(0); + } + + static Uint8 TranslatePOV(DWORD value) + { +- Uint8 pos; ++ const int HAT_VALS[] = { ++ SDL_HAT_UP, ++ SDL_HAT_UP | SDL_HAT_RIGHT, ++ SDL_HAT_RIGHT, ++ SDL_HAT_DOWN | SDL_HAT_RIGHT, ++ SDL_HAT_DOWN, ++ SDL_HAT_DOWN | SDL_HAT_LEFT, ++ SDL_HAT_LEFT, ++ SDL_HAT_UP | SDL_HAT_LEFT ++ }; ++ ++ if(LOWORD(value) == 0xFFFF) ++ return SDL_HAT_CENTERED; ++ ++ /* Round the value up: */ ++ value += 4500 / 2; ++ value %= 36000; ++ value /= 4500; ++ ++ if(value >= 8) ++ return SDL_HAT_CENTERED; /* shouldn't happen */ ++ ++ return HAT_VALS[value]; ++} + +- pos = SDL_HAT_CENTERED; +- if ( value != JOY_POVCENTERED ) { +- if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { +- pos |= SDL_HAT_UP; +- } +- if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { +- pos |= SDL_HAT_RIGHT; +- } +- if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { +- pos |= SDL_HAT_DOWN; +- } +- if ( value > JOY_POVBACKWARD ) { +- pos |= SDL_HAT_LEFT; +- } +- } +- return(pos); ++/* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to ++ * do it. */ ++static int SDL_PrivateJoystickAxis_Int(SDL_Joystick *joystick, Uint8 axis, Sint16 value) ++{ ++ if(joystick->axes[axis] != value) ++ return SDL_PrivateJoystickAxis(joystick, axis, value); ++ return 0; ++} ++ ++static int SDL_PrivateJoystickHat_Int(SDL_Joystick *joystick, Uint8 hat, Uint8 value) ++{ ++ if(joystick->hats[hat] != value) ++ return SDL_PrivateJoystickHat(joystick, hat, value); ++ return 0; ++} ++ ++static int SDL_PrivateJoystickButton_Int(SDL_Joystick *joystick, Uint8 button, Uint8 state) ++{ ++ if(joystick->buttons[button] != state) ++ return SDL_PrivateJoystickButton(joystick, button, state); ++ return 0; + } + + /* Function to update the state of a joystick - called as a device poll. +@@ -213,76 +382,126 @@ + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +-void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) ++void SDL_SYS_JoystickUpdate_Polled(SDL_Joystick *joystick) + { +- MMRESULT result; ++ DIJOYSTATE state; ++ HRESULT result; + int i; +- DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, +- JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; +- DWORD pos[MAX_AXES]; +- struct _transaxis *transaxis; +- int value, change; +- JOYINFOEX joyinfo; +- +- joyinfo.dwSize = sizeof(joyinfo); +- joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; +- if ( ! joystick->hats ) { +- joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); +- } +- result = joyGetPosEx(joystick->hwdata->id, &joyinfo); +- if ( result != JOYERR_NOERROR ) { +- SetMMerror("joyGetPosEx", result); +- return; +- } +- +- /* joystick motion events */ +- pos[0] = joyinfo.dwXpos; +- pos[1] = joyinfo.dwYpos; +- pos[2] = joyinfo.dwZpos; +- pos[3] = joyinfo.dwRpos; +- pos[4] = joyinfo.dwUpos; +- pos[5] = joyinfo.dwVpos; +- +- transaxis = joystick->hwdata->transaxis; +- for (i = 0; i < joystick->naxes; i++) { +- if (joyinfo.dwFlags & flags[i]) { +- value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); +- change = (value - joystick->axes[i]); +- if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { +- SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); ++ ++ result = IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, sizeof(state), &state); ++ if ( result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED ) { ++ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); ++ result = IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, sizeof(state), &state); ++ } ++ ++ /* Set each known axis, button and POV. */ ++ for(i = 0; i < joystick->hwdata->NumInputs; ++i) ++ { ++ const input_t *in = &joystick->hwdata->Inputs[i]; ++ ++ switch(in->type) ++ { ++ case AXIS: ++ switch(in->ofs) ++ { ++ case DIJOFS_X: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lX); break; ++ case DIJOFS_Y: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lY); break; ++ case DIJOFS_Z: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lZ); break; ++ case DIJOFS_RX: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRx); break; ++ case DIJOFS_RY: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRy); break; ++ case DIJOFS_RZ: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRz); break; ++ case DIJOFS_SLIDER(0): SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.rglSlider[0]); break; ++ case DIJOFS_SLIDER(1): SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.rglSlider[0]); break; + } ++ ++ break; ++ ++ case BUTTON: ++ SDL_PrivateJoystickButton_Int(joystick, in->num, (Uint8) (state.rgbButtons[in->ofs - DIJOFS_BUTTON0]?SDL_PRESSED:SDL_RELEASED)); ++ break; ++ case HAT: ++ { ++ Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]); ++ SDL_PrivateJoystickHat_Int(joystick, in->num, pos); ++ break; ++ } + } + } ++} ++ ++void SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick *joystick) ++{ ++ int i; ++ HRESULT result; ++ DWORD numevents; ++ DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; ++ ++ numevents = INPUT_QSIZE; ++ result = IDirectInputDevice2_GetDeviceData( ++ joystick->hwdata->InputDevice, sizeof(DIDEVICEOBJECTDATA), ++ evtbuf, &numevents, 0); ++ if ( result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED ) { ++ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); ++ result = IDirectInputDevice2_GetDeviceData( ++ joystick->hwdata->InputDevice, sizeof(DIDEVICEOBJECTDATA), ++ evtbuf, &numevents, 0); ++ } ++ ++ /* Handle the events */ ++ if ( result != DI_OK ) ++ return; ++ ++ for(i = 0; i < (int) numevents; ++i) ++ { ++ int j; ++ ++ for(j = 0; j < joystick->hwdata->NumInputs; ++j) ++ { ++ const input_t *in = &joystick->hwdata->Inputs[j]; + +- /* joystick button events */ +- if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { +- for ( i = 0; i < joystick->nbuttons; ++i ) { +- if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { +- if ( ! joystick->buttons[i] ) { +- SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); +- } +- } else { +- if ( joystick->buttons[i] ) { +- SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); +- } ++ if(evtbuf[i].dwOfs != in->ofs) ++ continue; ++ ++ switch(in->type) ++ { ++ case AXIS: ++ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData); ++ break; ++ case BUTTON: ++ SDL_PrivateJoystickButton(joystick, in->num, (Uint8) (evtbuf[i].dwData?SDL_PRESSED:SDL_RELEASED)); ++ break; ++ case HAT: ++ { ++ Uint8 pos = TranslatePOV(evtbuf[i].dwData); ++ SDL_PrivateJoystickHat(joystick, in->num, pos); ++ } + } + } + } ++} + +- /* joystick hat events */ +- if ( joyinfo.dwFlags & JOY_RETURNPOV ) { +- Uint8 pos; +- +- pos = TranslatePOV(joyinfo.dwPOV); +- if ( pos != joystick->hats[0] ) { +- SDL_PrivateJoystickHat(joystick, 0, pos); +- } ++void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) ++{ ++ HRESULT result; ++ ++ result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice); ++ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { ++ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); ++ IDirectInputDevice2_Poll(joystick->hwdata->InputDevice); + } ++ ++ if(joystick->hwdata->buffered) ++ SDL_SYS_JoystickUpdate_Buffered(joystick); ++ else ++ SDL_SYS_JoystickUpdate_Polled(joystick); + } + + /* Function to close a joystick after use */ + void SDL_SYS_JoystickClose(SDL_Joystick *joystick) + { ++ IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice); ++ IDirectInputDevice2_Release(joystick->hwdata->InputDevice); ++ + if (joystick->hwdata != NULL) { + /* free system specific hardware data */ + free(joystick->hwdata); +@@ -292,48 +511,6 @@ + /* Function to perform any system-specific joystick related cleanup */ + void SDL_SYS_JoystickQuit(void) + { +- return; +-} +- +- +-/* implementation functions */ +-void SetMMerror(char *function, int code) +-{ +- static char *error; +- static char errbuf[BUFSIZ]; +- +- errbuf[0] = 0; +- switch (code) +- { +- case MMSYSERR_NODRIVER: +- error = "Joystick driver not present"; +- break; +- +- case MMSYSERR_INVALPARAM: +- case JOYERR_PARMS: +- error = "Invalid parameter(s)"; +- break; +- +- case MMSYSERR_BADDEVICEID: +- error = "Bad device ID"; +- break; +- +- case JOYERR_UNPLUGGED: +- error = "Joystick not attached"; +- break; +- +- case JOYERR_NOCANDO: +- error = "Can't capture joystick input"; +- break; +- +- default: +- sprintf(errbuf, "%s: Unknown Multimedia system error: 0x%x", +- function, code); +- break; +- } +- +- if ( ! errbuf[0] ) { +- sprintf(errbuf, "%s: %s", function, error); +- } +- SDL_SetError("%s", errbuf); ++ IDirectInput_Release(dinput); ++ dinput = NULL; + }