LIBS: updated sdl2

Martin Gerhardy 2020-03-11 00:32:36 +01:00
parent 5060779c18
commit 82203ac3ac
35 changed files with 757 additions and 426 deletions

View File

@ -757,8 +757,10 @@ macro(CheckOpenGLX11)
endmacro()
# Requires:
# - nada
# - PkgCheckModules
macro(CheckOpenGLESX11)
pkg_check_modules(EGL egl)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${EGL_CFLAGS}")
if(VIDEO_OPENGLES)
check_c_source_compiles("
#define EGL_API_FB

View File

@ -468,6 +468,24 @@ extern "C" {
*/
#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
/**
* \brief A variable that overrides the automatic controller type detection
*
* The variable should be comma separated entries, in the form: VID/PID=type
*
* The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd
*
* The type should be one of:
* Xbox360
* XboxOne
* PS3
* PS4
* SwitchPro
*
* This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
*/
#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE"
/**
* \brief A variable that lets you manually hint extra gamecontroller db entries.
*

View File

@ -618,8 +618,8 @@ extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
* \brief Set the clip rectangle for the current target.
*
* \param renderer The renderer for which clip rectangle should be set.
* \param rect A pointer to the rectangle to set as the clip rectangle, or
* NULL to disable clipping.
* \param rect A pointer to the rectangle to set as the clip rectangle,
* relative to the viewport, or NULL to disable clipping.
*
* \return 0 on success, or -1 on error
*

View File

@ -408,6 +408,8 @@ extern DECLSPEC int SDLCALL SDL_abs(int x);
extern DECLSPEC int SDLCALL SDL_isdigit(int x);
extern DECLSPEC int SDLCALL SDL_isspace(int x);
extern DECLSPEC int SDLCALL SDL_isupper(int x);
extern DECLSPEC int SDLCALL SDL_islower(int x);
extern DECLSPEC int SDLCALL SDL_toupper(int x);
extern DECLSPEC int SDLCALL SDL_tolower(int x);

View File

@ -59,7 +59,7 @@ typedef struct SDL_version
*/
#define SDL_MAJOR_VERSION 2
#define SDL_MINOR_VERSION 0
#define SDL_PATCHLEVEL 11
#define SDL_PATCHLEVEL 13
/**
* \brief Macro to determine SDL version program was compiled against.

View File

@ -710,6 +710,41 @@ prepare_audioqueue(_THIS)
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
/* Set the channel layout for the audio queue */
AudioChannelLayout layout;
SDL_zero(layout);
switch (this->spec.channels) {
case 1:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
break;
case 2:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
break;
case 3:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4;
break;
case 4:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Quadraphonic;
break;
case 5:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_0_A;
break;
case 6:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_5_1_A;
break;
case 7:
/* FIXME: Need to move channel[4] (BC) to channel[6] */
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A;
break;
case 8:
layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A;
break;
}
if (layout.mChannelLayoutTag != 0) {
result = AudioQueueSetProperty(this->hidden->audioQueue, kAudioQueueProperty_ChannelLayout, &layout, sizeof(layout));
CHECK_RESULT("AudioQueueSetProperty(kAudioQueueProperty_ChannelLayout)");
}
/* Allocate a sample buffer */
this->hidden->bufferSize = this->spec.size;
this->hidden->bufferOffset = iscapture ? 0 : this->hidden->bufferSize;
@ -820,6 +855,17 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setPreferredSampleRate:this->spec.freq error:nil];
this->spec.freq = (int)session.sampleRate;
#if TARGET_OS_TV
if (iscapture) {
[session setPreferredInputNumberOfChannels:this->spec.channels error:nil];
this->spec.channels = session.preferredInputNumberOfChannels;
} else {
[session setPreferredOutputNumberOfChannels:this->spec.channels error:nil];
this->spec.channels = session.preferredOutputNumberOfChannels;
}
#else
/* Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS */
#endif /* TARGET_OS_TV */
}
#endif
@ -864,7 +910,7 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
return SDL_SetError("Unsupported audio format");
}
strdesc->mBytesPerFrame = strdesc->mBitsPerChannel * strdesc->mChannelsPerFrame / 8;
strdesc->mBytesPerFrame = strdesc->mChannelsPerFrame * strdesc->mBitsPerChannel / 8;
strdesc->mBytesPerPacket = strdesc->mBytesPerFrame * strdesc->mFramesPerPacket;
#if MACOSX_COREAUDIO

View File

@ -63,8 +63,10 @@ public:
void OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ args);
void OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
void OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
void OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args);
void OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args);
void OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args);
SDL_semaphore* completed;
private:
const SDL_bool iscapture;
@ -72,20 +74,23 @@ private:
Windows::Foundation::EventRegistrationToken added_handler;
Windows::Foundation::EventRegistrationToken removed_handler;
Windows::Foundation::EventRegistrationToken updated_handler;
Windows::Foundation::EventRegistrationToken completed_handler;
Windows::Foundation::EventRegistrationToken default_changed_handler;
};
SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture)
: iscapture(_iscapture)
, completed(SDL_CreateSemaphore(0))
, watcher(DeviceInformation::CreateWatcher(_iscapture ? DeviceClass::AudioCapture : DeviceClass::AudioRender))
{
if (!watcher)
if (!watcher || !completed)
return; // uhoh.
// !!! FIXME: this doesn't need a lambda here, I think, if I make SDL_WasapiDeviceEventHandler a proper C++/CX class. --ryan.
added_handler = watcher->Added += ref new TypedEventHandler<DeviceWatcher^, DeviceInformation^>([this](DeviceWatcher^ sender, DeviceInformation^ args) { OnDeviceAdded(sender, args); } );
removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceRemoved(sender, args); } );
updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceUpdated(sender, args); } );
completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher^, Platform::Object^>([this](DeviceWatcher^ sender, Platform::Object^ args) { OnEnumerationCompleted(sender, args); } );
if (iscapture) {
default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object^, DefaultAudioCaptureDeviceChangedEventArgs^>([this](Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args) { OnDefaultCaptureDeviceChanged(sender, args); } );
} else {
@ -100,9 +105,14 @@ SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler()
watcher->Added -= added_handler;
watcher->Removed -= removed_handler;
watcher->Updated -= updated_handler;
watcher->EnumerationCompleted -= completed_handler;
watcher->Stop();
watcher = nullptr;
}
if (completed) {
SDL_DestroySemaphore(completed);
completed = nullptr;
}
if (iscapture) {
MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
@ -135,6 +145,13 @@ SDL_WasapiDeviceEventHandler::OnDeviceUpdated(DeviceWatcher^ sender, DeviceInfor
SDL_assert(sender == this->watcher);
}
void
SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args)
{
SDL_assert(sender == this->watcher);
SDL_SemPost(this->completed);
}
void
SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args)
{
@ -173,6 +190,8 @@ void WASAPI_EnumerateEndpoints(void)
// listening for updates.
playback_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_FALSE);
capture_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE);
SDL_SemWait(playback_device_event_handler->completed);
SDL_SemWait(capture_device_event_handler->completed);
}
struct SDL_WasapiActivationHandler : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >

View File

@ -747,3 +747,5 @@
#define SDL_OnApplicationDidBecomeActive SDL_OnApplicationDidBecomeActive_REAL
#define SDL_OnApplicationDidChangeStatusBarOrientation SDL_OnApplicationDidChangeStatusBarOrientation_REAL
#define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL
#define SDL_isupper SDL_isupper_REAL
#define SDL_islower SDL_islower_REAL

View File

@ -744,7 +744,7 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasColorKey,(SDL_Surface *a),(a),return)
#undef SDL_CreateThreadWithStackSize
#endif
#if defined(__WIN32__) && !defined(HAVE_LIBC)
#if defined(__WIN32__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d, pfnSDL_CurrentBeginThread e, pfnSDL_CurrentEndThread f),(a,b,c,d,e,f),return)
#elif defined(__OS2__)
SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d, pfnSDL_CurrentBeginThread e, pfnSDL_CurrentEndThread f),(a,b,c,d,e,f),return)
@ -807,3 +807,5 @@ SDL_DYNAPI_PROC(void,SDL_OnApplicationDidChangeStatusBarOrientation,(void),(),)
#ifdef __ANDROID__
SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
#endif
SDL_DYNAPI_PROC(int,SDL_isupper,(int a),(a),return)
SDL_DYNAPI_PROC(int,SDL_islower,(int a),(a),return)

View File

@ -33,6 +33,13 @@
#include "../video/SDL_sysvideo.h"
#include "SDL_syswm.h"
#undef SDL_PRIs64
#ifdef __WIN32__
#define SDL_PRIs64 "I64d"
#else
#define SDL_PRIs64 "lld"
#endif
/* An arbitrary limit so we don't have unbounded growth */
#define SDL_MAX_QUEUED_EVENTS 65535

View File

@ -129,12 +129,6 @@ static const SDL_UDEV_Symbols *udev_ctx = NULL;
#undef make_path
#undef read_thread
#ifndef SDL_LIBUSB_DYNAMIC
#if __WINDOWS__
#define SDL_LIBUSB_DYNAMIC "libusb-1.0.dll"
#endif /* __WINDOWS__ */
#endif /* SDL_LIBUSB_DYNAMIC */
#ifdef SDL_LIBUSB_DYNAMIC
/* libusb HIDAPI Implementation */
@ -542,73 +536,52 @@ int HID_API_EXPORT HID_API_CALL hid_exit(void)
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
#ifdef SDL_LIBUSB_DYNAMIC
struct LIBUSB_hid_device_info *usb_devs = NULL;
struct LIBUSB_hid_device_info *usb_dev;
#endif
#if HAVE_PLATFORM_BACKEND
struct PLATFORM_hid_device_info *raw_devs = NULL;
struct PLATFORM_hid_device_info *raw_dev;
#endif /* HAVE_PLATFORM_BACKEND */
#endif
struct hid_device_info *devs = NULL, *last = NULL, *new_dev;
SDL_bool bFound;
if (SDL_hidapi_wasinit == SDL_FALSE) {
hid_init();
}
#if HAVE_PLATFORM_BACKEND
if (udev_ctx) {
raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
}
#endif /* HAVE_PLATFORM_BACKEND */
#ifdef SDL_LIBUSB_DYNAMIC
if (libusb_ctx.libhandle) {
struct LIBUSB_hid_device_info *usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
struct LIBUSB_hid_device_info *usb_dev;
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
bFound = SDL_FALSE;
#if HAVE_PLATFORM_BACKEND
for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
if (raw_dev->vendor_id == 0x057e && raw_dev->product_id == 0x0337) {
/* The GameCube adapter is handled by the USB HIDAPI driver */
continue;
}
if (usb_dev->vendor_id == raw_dev->vendor_id &&
usb_dev->product_id == raw_dev->product_id &&
(raw_dev->interface_number < 0 || usb_dev->interface_number == raw_dev->interface_number)) {
bFound = SDL_TRUE;
break;
}
}
#endif
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
if (!bFound) {
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
LIBUSB_CopyHIDDeviceInfo(usb_dev, new_dev);
if (last != NULL) {
last->next = new_dev;
} else {
devs = new_dev;
}
last = new_dev;
if (last != NULL) {
last->next = new_dev;
} else {
devs = new_dev;
}
last = new_dev;
}
LIBUSB_hid_free_enumeration(usb_devs);
}
#endif /* SDL_LIBUSB_DYNAMIC */
#if HAVE_PLATFORM_BACKEND
if (udev_ctx) {
raw_devs = PLATFORM_hid_enumerate(vendor_id, product_id);
for (raw_dev = raw_devs; raw_dev; raw_dev = raw_dev->next) {
bFound = SDL_FALSE;
for (new_dev = devs; new_dev; new_dev = new_dev->next) {
if (raw_dev->vendor_id == new_dev->vendor_id &&
raw_dev->product_id == new_dev->product_id &&
raw_dev->interface_number == new_dev->interface_number) {
SDL_bool bFound = SDL_FALSE;
#ifdef SDL_LIBUSB_DYNAMIC
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
if (raw_dev->vendor_id == usb_dev->vendor_id &&
raw_dev->product_id == usb_dev->product_id &&
(raw_dev->interface_number < 0 || raw_dev->interface_number == usb_dev->interface_number)) {
bFound = SDL_TRUE;
break;
}
}
#endif
if (!bFound) {
new_dev = (struct hid_device_info*) SDL_malloc(sizeof(struct hid_device_info));
PLATFORM_CopyHIDDeviceInfo(raw_dev, new_dev);
@ -626,6 +599,11 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
}
#endif /* HAVE_PLATFORM_BACKEND */
#ifdef SDL_LIBUSB_DYNAMIC
if (libusb_ctx.libhandle) {
LIBUSB_hid_free_enumeration(usb_devs);
}
#endif
return devs;
}
@ -770,3 +748,5 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device)
}
#endif /* SDL_JOYSTICK_HIDAPI */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@ -63,6 +63,11 @@ typedef LONG NTSTATUS;
/*#define HIDAPI_USE_DDK*/
/* The timeout in milliseconds for waiting on WriteFile to
complete in hid_write. The longest observed time to do a output
report that we've seen is ~200-250ms so let's double that */
#define HID_WRITE_TIMEOUT_MILLISECONDS 500
#ifdef __cplusplus
extern "C" {
#endif
@ -163,6 +168,7 @@ struct hid_device_ {
BOOL read_pending;
char *read_buf;
OVERLAPPED ol;
OVERLAPPED write_ol;
};
static hid_device *new_hid_device()
@ -178,6 +184,8 @@ static hid_device *new_hid_device()
dev->read_buf = NULL;
memset(&dev->ol, 0, sizeof(dev->ol));
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
memset(&dev->write_ol, 0, sizeof(dev->write_ol));
dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
return dev;
}
@ -185,6 +193,7 @@ static hid_device *new_hid_device()
static void free_hid_device(hid_device *dev)
{
CloseHandle(dev->ol.hEvent);
CloseHandle(dev->write_ol.hEvent);
CloseHandle(dev->device_handle);
LocalFree(dev->last_error_str);
free(dev->read_buf);
@ -310,6 +319,12 @@ int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
return 1;
}
// Sound BlasterX G1 - Causes 10 second stalls when asking for manufacturer's string
if ( vendor_id == 0x041E && product_id == 0x3249 )
{
return 1;
}
return 0;
}
@ -672,14 +687,12 @@ int HID_API_EXPORT HID_API_CALL hid_write_output_report(hid_device *dev, const u
return -1;
}
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t length, int milliseconds)
{
DWORD bytes_written;
BOOL res;
size_t stashed_length = length;
OVERLAPPED ol;
unsigned char *buf;
memset(&ol, 0, sizeof(ol));
/* Make sure the right number of bytes are passed to WriteFile. Windows
expects the number of bytes which are in the _longest_ report (plus
@ -704,7 +717,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
}
else
{
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &ol );
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* WriteFile() failed. Return error. */
@ -716,7 +729,16 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
/* Wait here until the write is done. This makes
hid_write() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
res = WaitForSingleObject(dev->write_ol.hEvent, milliseconds);
if (res != WAIT_OBJECT_0)
{
// There was a Timeout.
bytes_written = (DWORD) -1;
register_error(dev, "WriteFile/WaitForSingleObject Timeout");
goto end_of_function;
}
res = GetOverlappedResult(dev->device_handle, &dev->write_ol, &bytes_written, FALSE/*F=don't_wait*/);
if (!res) {
/* The Write operation failed. */
register_error(dev, "WriteFile");
@ -731,6 +753,10 @@ end_of_function:
return bytes_written;
}
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
{
return hid_write_timeout(dev, data, length, HID_WRITE_TIMEOUT_MILLISECONDS);
}
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
{

View File

@ -280,6 +280,7 @@ static const char *s_ControllerMappings [] =
"03000000ff1100004133000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,",
"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,",
@ -377,6 +378,7 @@ static const char *s_ControllerMappings [] =
"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,",
"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,",
"030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000006f0e00000702000003060000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,",
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,",
"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
@ -601,6 +603,7 @@ static const char *s_ControllerMappings [] =
"03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,",
"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000006f0e00000702000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",

View File

@ -146,6 +146,7 @@ SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
SDL_JoystickDriver *driver;
int device_index;
int existing_player_index;
if (player_index < 0) {
return SDL_FALSE;
@ -160,6 +161,15 @@ SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
SDL_joystick_players = new_players;
SDL_memset(&SDL_joystick_players[SDL_joystick_player_count], 0xFF, (player_index - SDL_joystick_player_count + 1) * sizeof(SDL_joystick_players[0]));
SDL_joystick_player_count = player_index + 1;
} else if (SDL_joystick_players[player_index] == instance_id) {
/* Joystick is already assigned the requested player index */
return SDL_TRUE;
}
/* Clear the old player index */
existing_player_index = SDL_GetPlayerIndexForJoystickID(instance_id);
if (existing_player_index >= 0) {
SDL_joystick_players[existing_player_index] = -1;
}
SDL_joystick_players[player_index] = instance_id;

View File

@ -162,6 +162,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x20d6, 0x792a ), k_eControllerType_PS4Controller, NULL }, // PowerA - Fusion Fight Pad
{ MAKE_CONTROLLER_ID( 0x7545, 0x0104 ), k_eControllerType_PS4Controller, NULL }, // Armor 3 or Level Up Cobra - At least one variant has gyro
{ MAKE_CONTROLLER_ID( 0x9886, 0x0025 ), k_eControllerType_PS4Controller, NULL }, // Astro C40
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro Fightstick w/ Touchpad for PS4
{ MAKE_CONTROLLER_ID( 0x0079, 0x0006 ), k_eControllerType_UnknownNonSteamController, NULL }, // DragonRise Generic USB PCB, sometimes configured as a PC Twin Shock Controller - looks like a DS3 but the face buttons are 1-4 instead of symbols
@ -539,6 +540,30 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB)
};
static SDL_INLINE const char *GetControllerTypeOverride( int nVID, int nPID )
{
const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLERTYPE);
if (hint) {
char key[32];
const char *spot = NULL;
SDL_snprintf(key, sizeof(key), "0x%.4x/0x%.4x=", nVID, nPID);
spot = SDL_strstr(hint, key);
if (!spot) {
SDL_snprintf(key, sizeof(key), "0x%.4X/0x%.4X=", nVID, nPID);
spot = SDL_strstr(hint, key);
}
if (spot) {
spot += SDL_strlen(key);
if (SDL_strncmp(spot, "k_eControllerType_", 18) == 0) {
spot += 18;
}
return spot;
}
}
return NULL;
}
static SDL_INLINE EControllerType GuessControllerType( int nVID, int nPID )
{
#if 0//def _DEBUG
@ -564,6 +589,37 @@ static SDL_INLINE EControllerType GuessControllerType( int nVID, int nPID )
unsigned int unDeviceID = MAKE_CONTROLLER_ID( nVID, nPID );
int iIndex;
const char *pszOverride = GetControllerTypeOverride( nVID, nPID );
if ( pszOverride )
{
if ( SDL_strncasecmp( pszOverride, "Xbox360", 7 ) == 0 )
{
return k_eControllerType_XBox360Controller;
}
if ( SDL_strncasecmp( pszOverride, "XboxOne", 7 ) == 0 )
{
return k_eControllerType_XBoxOneController;
}
if ( SDL_strncasecmp( pszOverride, "PS3", 3 ) == 0 )
{
return k_eControllerType_PS3Controller;
}
if ( SDL_strncasecmp( pszOverride, "PS4", 3 ) == 0 )
{
return k_eControllerType_PS4Controller;
}
if ( SDL_strncasecmp( pszOverride, "SwitchPro", 9 ) == 0 )
{
return k_eControllerType_SwitchProController;
}
if ( SDL_strncasecmp( pszOverride, "Steam", 5 ) == 0 )
{
return k_eControllerType_SteamController;
}
return k_eControllerType_UnknownNonSteamController;
}
for ( iIndex = 0; iIndex < sizeof( arrControllers ) / sizeof( arrControllers[0] ); ++iIndex )
{
if ( unDeviceID == arrControllers[ iIndex ].m_unDeviceID )

View File

@ -29,6 +29,7 @@
#include "SDL_haptic.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
#include "../../SDL_hints_c.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
@ -47,6 +48,7 @@ typedef struct {
Uint8 rumble[1+MAX_CONTROLLERS];
/* Without this variable, hid_write starts to lag a TON */
SDL_bool rumbleUpdate;
SDL_bool m_bUseButtonLabels;
} SDL_DriverGameCube_Context;
static SDL_bool
@ -95,6 +97,28 @@ static float RemapVal(float val, float A, float B, float C, float D)
return C + (D - C) * (val - A) / (B - A);
}
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
}
static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
{
if (!ctx->m_bUseButtonLabels) {
/* Use button positions */
switch (button) {
case SDL_CONTROLLER_BUTTON_B:
return SDL_CONTROLLER_BUTTON_X;
case SDL_CONTROLLER_BUTTON_X:
return SDL_CONTROLLER_BUTTON_B;
default:
break;
}
}
return button;
}
static SDL_bool
HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
{
@ -164,6 +188,9 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
}
}
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
return SDL_TRUE;
error:
@ -244,7 +271,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
#define READ_BUTTON(off, flag, button) \
SDL_PrivateJoystickButton( \
joystick, \
button, \
RemapButton(ctx, button), \
(curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
);
READ_BUTTON(1, 0x01, 0) /* A */
@ -352,9 +379,14 @@ HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
static void
HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
hid_close(device->dev);
device->dev = NULL;
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
SDL_free(device->context);
device->context = NULL;
}

View File

@ -100,6 +100,7 @@ typedef struct {
SDL_bool is_bluetooth;
SDL_bool audio_supported;
SDL_bool rumble_supported;
int player_index;
Uint8 volume;
Uint32 last_volume_check;
PS4StatePacket_t last_state;
@ -182,6 +183,33 @@ static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
return SDL_TRUE;
}
static void
SetLedsForPlayerIndex(DS4EffectsState_t *effects, int player_index)
{
/* This list is the same as what hid-sony.c uses in the Linux kernel.
The first 4 values correspond to what the PS4 assigns.
*/
static const Uint8 colors[7][3] = {
{ 0x00, 0x00, 0x40 }, /* Blue */
{ 0x40, 0x00, 0x00 }, /* Red */
{ 0x00, 0x40, 0x00 }, /* Green */
{ 0x20, 0x00, 0x20 }, /* Pink */
{ 0x02, 0x01, 0x00 }, /* Orange */
{ 0x00, 0x01, 0x01 }, /* Teal */
{ 0x01, 0x01, 0x01 } /* White */
};
if (player_index >= 0) {
player_index %= SDL_arraysize(colors);
} else {
player_index = 0;
}
effects->ucLedRed = colors[player_index][0];
effects->ucLedGreen = colors[player_index][1];
effects->ucLedBlue = colors[player_index][2];
}
static SDL_bool
HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device)
{
@ -194,12 +222,22 @@ HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID
return -1;
}
static int HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
static void
HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
}
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
static int HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
if (!ctx) {
return;
}
ctx->player_index = player_index;
/* This will set the new LED state based on the new player index */
HIDAPI_DriverPS4_RumbleJoystick(device, SDL_JoystickFromInstanceID(instance_id), 0, 0);
}
static SDL_bool
HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
@ -248,6 +286,9 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
}
}
/* Initialize player index (needed for setting LEDs) */
ctx->player_index = SDL_JoystickGetPlayerIndex(joystick);
/* Initialize LED and effect state */
HIDAPI_DriverPS4_RumbleJoystick(device, joystick, 0, 0);
@ -293,9 +334,8 @@ HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
effects->ucRumbleLeft = (low_frequency_rumble >> 8);
effects->ucRumbleRight = (high_frequency_rumble >> 8);
effects->ucLedRed = 0;
effects->ucLedGreen = 0;
effects->ucLedBlue = 80;
/* Populate the LED state with the appropriate color from our lookup table */
SetLedsForPlayerIndex(effects, ctx->player_index);
if (ctx->is_bluetooth) {
/* Bluetooth reports need a CRC at the end of the packet (at least on Linux) */

View File

@ -76,7 +76,9 @@ static int SDL_HIDAPI_RumbleThread(void *data)
if (request) {
SDL_LockMutex(request->device->dev_lock);
hid_write(request->device->dev, request->data, request->size);
if (request->device->dev) {
hid_write( request->device->dev, request->data, request->size );
}
SDL_UnlockMutex(request->device->dev_lock);
(void)SDL_AtomicDecRef(&request->device->rumble_pending);
SDL_free(request);

View File

@ -635,15 +635,15 @@ static void RotatePad( int *pX, int *pY, float flAngleInRad )
{
short int origX = *pX, origY = *pY;
*pX = (int)( cosf( flAngleInRad ) * origX - sinf( flAngleInRad ) * origY );
*pY = (int)( sinf( flAngleInRad ) * origX + cosf( flAngleInRad ) * origY );
*pX = (int)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY );
*pY = (int)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY );
}
static void RotatePadShort( short *pX, short *pY, float flAngleInRad )
{
short int origX = *pX, origY = *pY;
*pX = (short)( cosf( flAngleInRad ) * origX - sinf( flAngleInRad ) * origY );
*pY = (short)( sinf( flAngleInRad ) * origX + cosf( flAngleInRad ) * origY );
*pX = (short)( SDL_cosf( flAngleInRad ) * origX - SDL_sinf( flAngleInRad ) * origY );
*pY = (short)( SDL_sinf( flAngleInRad ) * origX + SDL_cosf( flAngleInRad ) * origY );
}
@ -1117,8 +1117,8 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
(ctx->m_state.sLeftPadX > kPadDeadZone) ? SDL_PRESSED : SDL_RELEASED);
}
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, ctx->m_state.sTriggerL * 2 - 32768);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, ctx->m_state.sTriggerR * 2 - 32768);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, (int)ctx->m_state.sTriggerL * 2 - 32768);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, (int)ctx->m_state.sTriggerR * 2 - 32768);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, ctx->m_state.sLeftStickX);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, ~ctx->m_state.sLeftStickY);

View File

@ -197,6 +197,7 @@ typedef struct {
SDL_bool m_bInputOnly;
SDL_bool m_bHasHomeLED;
SDL_bool m_bUsingBluetooth;
SDL_bool m_bIsGameCube;
SDL_bool m_bUseButtonLabels;
Uint8 m_nCommandNumber;
SwitchCommonOutputPacket_t m_RumblePacket;
@ -245,6 +246,15 @@ static SDL_bool IsGameCubeFormFactor(int vendor_id, int product_id)
static SDL_bool
HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
/* The HORI Wireless Switch Pad enumerates as a HID device when connected via USB
with the same VID/PID as when connected over Bluetooth but doesn't actually
support communication over USB. The most reliable way to block this without allowing the
controller to continually attempt to reconnect is to filter it out by manufactuer/product string.
Note that the controller does have a different product string when connected over Bluetooth.
*/
if (SDL_strcmp( name, "HORI Wireless Switch Pad" ) == 0) {
return SDL_FALSE;
}
return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO);
}
@ -446,7 +456,7 @@ static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx)
/* Refresh the rumble state periodically */
if (ctx->m_bRumbleActive) {
ctx->m_unRumbleRefresh = SDL_GetTicks() + 1000;
ctx->m_unRumbleRefresh = SDL_GetTicks() + 30;
if (!ctx->m_unRumbleRefresh) {
ctx->m_unRumbleRefresh = 1;
}
@ -468,7 +478,7 @@ static SDL_bool BTrySetupUSB(SDL_DriverSwitch_Context *ctx)
return SDL_FALSE;
}
if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_HighSpeed, NULL, 0, SDL_TRUE)) {
/* The 8BitDo M30 doesn't respond to this command, but otherwise works correctly */
/* The 8BitDo M30 and SF30 Pro don't respond to this command, but otherwise work correctly */
/*return SDL_FALSE;*/
}
if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_Handshake, NULL, 0, SDL_TRUE)) {
@ -629,18 +639,30 @@ static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata,
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
{
if (ctx->m_bUseButtonLabels) {
switch (button) {
case SDL_CONTROLLER_BUTTON_A:
return SDL_CONTROLLER_BUTTON_B;
case SDL_CONTROLLER_BUTTON_B:
return SDL_CONTROLLER_BUTTON_A;
case SDL_CONTROLLER_BUTTON_X:
return SDL_CONTROLLER_BUTTON_Y;
case SDL_CONTROLLER_BUTTON_Y:
return SDL_CONTROLLER_BUTTON_X;
default:
break;
if (!ctx->m_bUseButtonLabels) {
/* Use button positions */
if (ctx->m_bIsGameCube) {
switch (button) {
case SDL_CONTROLLER_BUTTON_B:
return SDL_CONTROLLER_BUTTON_X;
case SDL_CONTROLLER_BUTTON_X:
return SDL_CONTROLLER_BUTTON_B;
default:
break;
}
} else {
switch (button) {
case SDL_CONTROLLER_BUTTON_A:
return SDL_CONTROLLER_BUTTON_B;
case SDL_CONTROLLER_BUTTON_B:
return SDL_CONTROLLER_BUTTON_A;
case SDL_CONTROLLER_BUTTON_X:
return SDL_CONTROLLER_BUTTON_Y;
case SDL_CONTROLLER_BUTTON_Y:
return SDL_CONTROLLER_BUTTON_X;
default:
break;
}
}
}
return button;
@ -737,12 +759,12 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
if (IsGameCubeFormFactor(device->vendor_id, device->product_id)) {
/* This is a controller shaped like a GameCube controller, with a large central A button */
ctx->m_bUseButtonLabels = SDL_TRUE;
} else {
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
ctx->m_bIsGameCube = SDL_TRUE;
}
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
@ -805,10 +827,10 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi
if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
Uint8 data = packet->rgucButtons[0];
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);

View File

@ -244,6 +244,22 @@ HIDAPI_DriverXbox360_QuitWindowsGamingInput(SDL_DriverXbox360_Context *ctx)
#endif /* SDL_JOYSTICK_HIDAPI_WINDOWS_GAMING_INPUT */
#if defined(__MACOSX__)
static SDL_bool
IsBluetoothXboxOneController(Uint16 vendor_id, Uint16 product_id)
{
/* Check to see if it's the Xbox One S or Xbox One Elite Series 2 in Bluetooth mode */
if (vendor_id == USB_VENDOR_MICROSOFT) {
if (product_id == USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH ||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
#endif
static SDL_bool
HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
@ -267,10 +283,17 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
/* This is the Steam Virtual Gamepad, which isn't supported by this driver */
return SDL_FALSE;
}
if (vendor_id == USB_VENDOR_MICROSOFT && product_id == 0x02e0) {
/* This is the old Bluetooth Xbox One S firmware, which isn't supported by this driver */
#if defined(__MACOSX__)
/* Wired Xbox One controllers are handled by this driver, interfacing with
the 360Controller driver available from:
https://github.com/360Controller/360Controller/releases
Bluetooth Xbox One controllers are handled by the SDL Xbox One driver
*/
if (IsBluetoothXboxOneController(vendor_id, product_id)) {
return SDL_FALSE;
}
#endif
return (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE);
#else
return (type == SDL_CONTROLLER_TYPE_XBOX360);
@ -403,23 +426,38 @@ HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
#else /* !__WIN32__ */
#ifdef __MACOSX__
/* On Mac OS X the 360Controller driver uses this short report,
and we need to prefix it with a magic token so hidapi passes it through untouched
*/
Uint8 rumble_packet[] = { 'M', 'A', 'G', 'I', 'C', '0', 0x00, 0x04, 0x00, 0x00 };
if (IsBluetoothXboxOneController(device->vendor_id, device->product_id)) {
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
rumble_packet[6+2] = (low_frequency_rumble >> 8);
rumble_packet[6+3] = (high_frequency_rumble >> 8);
rumble_packet[4] = (low_frequency_rumble >> 8);
rumble_packet[5] = (high_frequency_rumble >> 8);
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
return SDL_SetError("Couldn't send rumble packet");
}
} else {
/* On Mac OS X the 360Controller driver uses this short report,
and we need to prefix it with a magic token so hidapi passes it through untouched
*/
Uint8 rumble_packet[] = { 'M', 'A', 'G', 'I', 'C', '0', 0x00, 0x04, 0x00, 0x00 };
rumble_packet[6+2] = (low_frequency_rumble >> 8);
rumble_packet[6+3] = (high_frequency_rumble >> 8);
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
return SDL_SetError("Couldn't send rumble packet");
}
}
#else
Uint8 rumble_packet[] = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
rumble_packet[3] = (low_frequency_rumble >> 8);
rumble_packet[4] = (high_frequency_rumble >> 8);
#endif
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
return SDL_SetError("Couldn't send rumble packet");
}
#endif
#endif /* __WIN32__ */
return 0;
@ -651,106 +689,6 @@ HIDAPI_DriverXbox360_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev,
}
#endif /* __WIN32__ */
#ifdef __MACOSX__
static void
HIDAPI_DriverXboxOneS_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
if (ctx->last_state[14] != data[14]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[15] != data[15]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[16] != data[16]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[13] != data[13]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
switch (data[13]) {
case 1:
dpad_up = SDL_TRUE;
break;
case 2:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
break;
case 3:
dpad_right = SDL_TRUE;
break;
case 4:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
break;
case 5:
dpad_down = SDL_TRUE;
break;
case 6:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
break;
case 7:
dpad_left = SDL_TRUE;
break;
case 8:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
break;
default:
break;
}
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
}
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
if (axis == 32704) {
axis = 32767;
}
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
if (axis == 32704) {
axis = 32767;
}
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static void
HIDAPI_DriverXboxOneS_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360_Context *ctx, Uint8 *data, int size)
{
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
#endif /* __MACOSX__ */
static SDL_bool
HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
{
@ -767,31 +705,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef __WIN32__
HIDAPI_DriverXbox360_HandleStatePacket(joystick, device->dev, ctx, data, size);
#else
switch (data[0]) {
case 0x00:
HIDAPI_DriverXbox360_HandleStatePacket(joystick, device->dev, ctx, data, size);
break;
#ifdef __MACOSX__
case 0x01:
HIDAPI_DriverXboxOneS_HandleStatePacket(joystick, device->dev, ctx, data, size);
break;
case 0x02:
HIDAPI_DriverXboxOneS_HandleGuidePacket(joystick, device->dev, ctx, data, size);
break;
#endif
default:
#ifdef DEBUG_JOYSTICK
SDL_Log("Unknown Xbox 360 packet, size = %d\n", size);
SDL_Log("%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16]);
#endif
break;
}
#endif /* __WIN32__ */
}
if (size < 0) {

View File

@ -74,11 +74,6 @@ static const Uint8 xboxone_init6[] = {
0x00, 0x00, 0xFF, 0x00, 0xEB
};
static const Uint8 xboxone_rumble_reset[] = {
0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00
};
/*
* This specifies the selection of init packets that a gamepad
* will be sent on init *and* the order in which they will be
@ -110,15 +105,21 @@ static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init6, sizeof(xboxone_init6), { 0x00, 0x00 } },
};
typedef enum {
XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN,
XBOX_ONE_WIRELESS_PROTOCOL_V1,
XBOX_ONE_WIRELESS_PROTOCOL_V2,
} SDL_XboxOneWirelessProtocol;
typedef struct {
Uint16 vendor_id;
Uint16 product_id;
Uint32 start_time;
SDL_bool bluetooth;
SDL_XboxOneWirelessProtocol wireless_protocol;
SDL_bool initialized;
Uint32 start_time;
Uint8 sequence;
Uint8 last_state[USB_PACKET_LENGTH];
SDL_bool rumble_synchronized;
SDL_bool rumble_synchronization_complete;
SDL_bool has_paddles;
} SDL_DriverXboxOne_Context;
@ -168,47 +169,6 @@ ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
return SDL_FALSE;
}
static SDL_bool
ControllerNeedsRumbleSequenceSynchronized(Uint16 vendor_id, Uint16 product_id)
{
if (vendor_id == USB_VENDOR_MICROSOFT) {
/* All Xbox One controllers, from model 1537 through Elite Series 2, appear to need this */
return SDL_TRUE;
}
return SDL_FALSE;
}
static SDL_bool
SynchronizeRumbleSequence(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
{
Uint16 vendor_id = ctx->vendor_id;
Uint16 product_id = ctx->product_id;
if (ctx->rumble_synchronized) {
return SDL_TRUE;
}
if (ControllerNeedsRumbleSequenceSynchronized(vendor_id, product_id)) {
int i;
Uint8 init_packet[USB_PACKET_LENGTH];
SDL_memcpy(init_packet, xboxone_rumble_reset, sizeof(xboxone_rumble_reset));
for (i = 0; i < 255; ++i) {
init_packet[2] = ((ctx->sequence + i) % 255);
if (SDL_HIDAPI_LockRumble() < 0) {
return SDL_FALSE;
}
if (SDL_HIDAPI_SendRumbleAndUnlock(device, init_packet, sizeof(xboxone_rumble_reset)) != sizeof(xboxone_rumble_reset)) {
SDL_SetError("Couldn't write Xbox One initialization packet");
return SDL_FALSE;
}
}
}
ctx->rumble_synchronized = SDL_TRUE;
return SDL_TRUE;
}
/* Return true if this controller sends the 0x02 "waiting for init" packet */
static SDL_bool
ControllerSendsWaitingForInit(Uint16 vendor_id, Uint16 product_id)
@ -235,66 +195,60 @@ SendControllerInit(SDL_HIDAPI_Device *device, SDL_DriverXboxOne_Context *ctx)
{
Uint16 vendor_id = ctx->vendor_id;
Uint16 product_id = ctx->product_id;
int i;
Uint8 init_packet[USB_PACKET_LENGTH];
if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
int i;
Uint8 init_packet[USB_PACKET_LENGTH];
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
for (i = 0; i < SDL_arraysize(xboxone_init_packets); ++i) {
const SDL_DriverXboxOne_InitPacket *packet = &xboxone_init_packets[i];
if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
continue;
}
if (packet->vendor_id && (vendor_id != packet->vendor_id)) {
continue;
}
if (packet->product_id && (product_id != packet->product_id)) {
continue;
}
if (packet->product_id && (product_id != packet->product_id)) {
continue;
}
if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
continue;
}
if (packet->exclude_vendor_id && (vendor_id == packet->exclude_vendor_id)) {
continue;
}
if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
continue;
}
if (packet->exclude_product_id && (product_id == packet->exclude_product_id)) {
continue;
}
SDL_memcpy(init_packet, packet->data, packet->size);
if (init_packet[0] != 0x01) {
init_packet[2] = ctx->sequence++;
}
if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
SDL_SetError("Couldn't write Xbox One initialization packet");
return SDL_FALSE;
}
SDL_memcpy(init_packet, packet->data, packet->size);
if (init_packet[0] != 0x01) {
init_packet[2] = ctx->sequence++;
}
if (hid_write(device->dev, init_packet, packet->size) != packet->size) {
SDL_SetError("Couldn't write Xbox One initialization packet");
return SDL_FALSE;
}
if (packet->response[0]) {
const Uint32 RESPONSE_TIMEOUT_MS = 50;
Uint32 start = SDL_GetTicks();
SDL_bool got_response = SDL_FALSE;
if (packet->response[0]) {
const Uint32 RESPONSE_TIMEOUT_MS = 50;
Uint32 start = SDL_GetTicks();
SDL_bool got_response = SDL_FALSE;
while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
Uint8 data[USB_PACKET_LENGTH];
int size;
while (!got_response && !SDL_TICKS_PASSED(SDL_GetTicks(), start + RESPONSE_TIMEOUT_MS)) {
Uint8 data[USB_PACKET_LENGTH];
int size;
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
DumpPacket("Xbox One INIT packet: size = %d", data, size);
DumpPacket("Xbox One INIT packet: size = %d", data, size);
#endif
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
got_response = SDL_TRUE;
}
if (size >= 2 && data[0] == packet->response[0] && data[1] == packet->response[1]) {
got_response = SDL_TRUE;
}
}
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Init sequence %d got response: %s\n", i, got_response ? "TRUE" : "FALSE");
#endif
}
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Init sequence %d got response: %s\n", i, got_response ? "TRUE" : "FALSE");
#endif
}
}
SynchronizeRumbleSequence(device, ctx);
return SDL_TRUE;
}
@ -302,14 +256,16 @@ static SDL_bool
HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
#ifdef __LINUX__
if (IsBluetoothXboxOneController(vendor_id, product_id)) {
/* We can't do rumble on this device, hid_write() fails, so don't try to open it here */
return SDL_FALSE;
}
if (vendor_id == USB_VENDOR_POWERA && product_id == 0x541a) {
/* The PowerA Mini controller, model 1240245-01, blocks while writing feature reports */
return SDL_FALSE;
}
#endif
#ifdef __MACOSX__
/* Wired Xbox One controllers are handled by the 360Controller driver */
if (!IsBluetoothXboxOneController(vendor_id, product_id)) {
return SDL_FALSE;
}
#endif
return (type == SDL_CONTROLLER_TYPE_XBOXONE);
}
@ -358,6 +314,8 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->vendor_id = device->vendor_id;
ctx->product_id = device->product_id;
ctx->bluetooth = IsBluetoothXboxOneController(device->vendor_id, device->product_id);
ctx->initialized = ctx->bluetooth ? SDL_TRUE : SDL_FALSE;
ctx->start_time = SDL_GetTicks();
ctx->sequence = 1;
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
@ -374,38 +332,24 @@ static int
HIDAPI_DriverXboxOne_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
Uint8 *pending_rumble;
int *pending_size;
int maximum_size;
SynchronizeRumbleSequence(device, ctx);
if (ctx->bluetooth) {
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
if (SDL_HIDAPI_LockRumble() < 0) {
return -1;
}
rumble_packet[4] = (low_frequency_rumble >> 8);
rumble_packet[5] = (high_frequency_rumble >> 8);
if (!ctx->rumble_synchronization_complete) {
if (!SDL_HIDAPI_GetPendingRumbleLocked(device, &pending_rumble, &pending_size, &maximum_size)) {
/* Rumble synchronization has drained */
ctx->rumble_synchronization_complete = SDL_TRUE;
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
return SDL_SetError("Couldn't send rumble packet");
}
}
/* Try to overwrite any pending rumble with the new value */
if (ctx->rumble_synchronization_complete &&
SDL_HIDAPI_GetPendingRumbleLocked(device, &pending_rumble, &pending_size, &maximum_size)) {
/* Magnitude is 1..100 so scale the 16-bit input here */
pending_rumble[8] = low_frequency_rumble / 655;
pending_rumble[9] = high_frequency_rumble / 655;
SDL_HIDAPI_UnlockRumble();
} else {
Uint8 rumble_packet[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF };
/* Magnitude is 1..100 so scale the 16-bit input here */
rumble_packet[2] = ctx->sequence++;
rumble_packet[8] = low_frequency_rumble / 655;
rumble_packet[9] = high_frequency_rumble / 655;
if (SDL_HIDAPI_SendRumbleAndUnlock(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
return SDL_SetError("Couldn't send rumble packet");
}
}
@ -533,6 +477,115 @@ HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, hid_device *dev, S
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[4] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
static void
HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
if (ctx->last_state[14] != data[14]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data[14] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data[14] & 0x02) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data[14] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data[14] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data[14] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data[14] & 0x80) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[15] != data[15]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSTICK, (data[15] & 0x20) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_UNKNOWN)
{
if (data[15] & 0x10) {
ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V2;
}
}
if (ctx->wireless_protocol == XBOX_ONE_WIRELESS_PROTOCOL_V2)
{
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
}
}
if (ctx->last_state[16] != data[16]) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[13] != data[13]) {
SDL_bool dpad_up = SDL_FALSE;
SDL_bool dpad_down = SDL_FALSE;
SDL_bool dpad_left = SDL_FALSE;
SDL_bool dpad_right = SDL_FALSE;
switch (data[13]) {
case 1:
dpad_up = SDL_TRUE;
break;
case 2:
dpad_up = SDL_TRUE;
dpad_right = SDL_TRUE;
break;
case 3:
dpad_right = SDL_TRUE;
break;
case 4:
dpad_right = SDL_TRUE;
dpad_down = SDL_TRUE;
break;
case 5:
dpad_down = SDL_TRUE;
break;
case 6:
dpad_left = SDL_TRUE;
dpad_down = SDL_TRUE;
break;
case 7:
dpad_left = SDL_TRUE;
break;
case 8:
dpad_up = SDL_TRUE;
dpad_left = SDL_TRUE;
break;
default:
break;
}
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_DOWN, dpad_down);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_UP, dpad_up);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, dpad_right);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
}
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
if (axis == 32704) {
axis = 32767;
}
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT, axis);
axis = ((int)*(Sint16*)(&data[11]) * 64) - 32768;
if (axis == 32704) {
axis = 32767;
}
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static void
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
ctx->wireless_protocol = XBOX_ONE_WIRELESS_PROTOCOL_V1;
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[1] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
static SDL_bool
HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
{
@ -563,34 +616,50 @@ HIDAPI_DriverXboxOne_UpdateDevice(SDL_HIDAPI_Device *device)
#ifdef DEBUG_XBOX_PROTOCOL
DumpPacket("Xbox One packet: size = %d", data, size);
#endif
switch (data[0]) {
case 0x02:
/* Controller is connected and waiting for initialization */
if (!ctx->initialized) {
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
#endif
if (!SendControllerInit(device, ctx)) {
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;
}
break;
case 0x03:
/* Controller heartbeat */
break;
case 0x20:
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
break;
case 0x07:
HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
break;
default:
if (ctx->bluetooth) {
switch (data[0]) {
case 0x01:
HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(joystick, device->dev, ctx, data, size);
break;
case 0x02:
HIDAPI_DriverXboxOneBluetooth_HandleGuidePacket(joystick, device->dev, ctx, data, size);
break;
default:
#ifdef DEBUG_JOYSTICK
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
#endif
break;
break;
}
} else {
switch (data[0]) {
case 0x02:
/* Controller is connected and waiting for initialization */
if (!ctx->initialized) {
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Delay after init: %ums\n", SDL_GetTicks() - ctx->start_time);
#endif
if (!SendControllerInit(device, ctx)) {
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
return SDL_FALSE;
}
ctx->initialized = SDL_TRUE;
}
break;
case 0x03:
/* Controller heartbeat */
break;
case 0x20:
HIDAPI_DriverXboxOne_HandleStatePacket(joystick, device->dev, ctx, data, size);
break;
case 0x07:
HIDAPI_DriverXboxOne_HandleModePacket(joystick, device->dev, ctx, data, size);
break;
default:
#ifdef DEBUG_JOYSTICK
SDL_Log("Unknown Xbox One packet: 0x%.2x\n", data[0]);
#endif
break;
}
}
}

View File

@ -43,6 +43,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/usb/USBSpec.h>
#endif
@ -218,12 +219,15 @@ HIDAPI_InitializeDiscovery()
SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
if (SDL_HIDAPI_discovery.m_notificationPort) {
{
CFMutableDictionaryRef matchingDict = IOServiceMatching("IOUSBDevice");
/* Note: IOServiceAddMatchingNotification consumes the reference to matchingDict */
io_iterator_t portIterator = 0;
io_object_t entry;
if (IOServiceAddMatchingNotification(SDL_HIDAPI_discovery.m_notificationPort, kIOMatchedNotification, matchingDict, CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator) == 0) {
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOFirstMatchNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
@ -234,12 +238,15 @@ HIDAPI_InitializeDiscovery()
}
}
{
CFMutableDictionaryRef matchingDict = IOServiceMatching("IOBluetoothDevice");
/* Note: IOServiceAddMatchingNotification consumes the reference to matchingDict */
io_iterator_t portIterator = 0;
io_object_t entry;
if (IOServiceAddMatchingNotification(SDL_HIDAPI_discovery.m_notificationPort, kIOMatchedNotification, matchingDict, CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator) == 0) {
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOTerminatedNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
@ -406,7 +413,7 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
const Uint16 USAGE_GAMEPAD = 0x0005;
const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
int i;
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
SDL_GameControllerType type;
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
return NULL;
@ -419,6 +426,7 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
return NULL;
}
type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
if (driver->enabled && driver->IsSupportedDevice(device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {

View File

@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,11,0
PRODUCTVERSION 2,0,11,0
FILEVERSION 2,0,13,0
PRODUCTVERSION 2,0,13,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "2, 0, 11, 0\0"
VALUE "FileVersion", "2, 0, 13, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright © 2020 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL2.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "2, 0, 11, 0\0"
VALUE "ProductVersion", "2, 0, 13, 0\0"
END
END
BLOCK "VarFileInfo"

View File

@ -1167,7 +1167,7 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
if (fmt->palette) {
for (i = 0; i < fmt->palette->ncolors; i++) {
Uint8 alpha_value = fmt->palette->colors[i].a;
if (alpha_value != 0 || alpha_value != SDL_ALPHA_OPAQUE) {
if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) {
needAlpha = SDL_TRUE;
break;
}

View File

@ -712,6 +712,7 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
texturedata->texture.dirty = SDL_TRUE;
if (data->drawstate.texture == texture) {
data->drawstate.texture = NULL;
data->drawstate.shader = NULL;
IDirect3DDevice9_SetPixelShader(data->device, NULL);
IDirect3DDevice9_SetTexture(data->device, 0, NULL);
if (texturedata->yuv) {
@ -1238,7 +1239,7 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
/* upload the new VBO data for this set of commands. */
vbo = data->vertexBuffers[vboidx];
if (!vbo || (data->vertexBufferSize[vboidx] < vertsize)) {
if (data->vertexBufferSize[vboidx] < vertsize) {
const DWORD usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
const DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
if (vbo) {
@ -1462,20 +1463,17 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
if (FAILED(result)) {
IDirect3DSurface9_Release(backBuffer);
return D3D_SetError("GetDesc()", result);
}
result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
if (FAILED(result)) {
IDirect3DSurface9_Release(backBuffer);
return D3D_SetError("CreateOffscreenPlainSurface()", result);
}
result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface);
if (FAILED(result)) {
IDirect3DSurface9_Release(surface);
IDirect3DSurface9_Release(backBuffer);
return D3D_SetError("GetRenderTargetData()", result);
}
@ -1487,7 +1485,6 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY);
if (FAILED(result)) {
IDirect3DSurface9_Release(surface);
IDirect3DSurface9_Release(backBuffer);
return D3D_SetError("LockRect()", result);
}
@ -1535,6 +1532,7 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (renderdata->drawstate.texture == texture) {
renderdata->drawstate.texture = NULL;
renderdata->drawstate.shader = NULL;
IDirect3DDevice9_SetPixelShader(renderdata->device, NULL);
IDirect3DDevice9_SetTexture(renderdata->device, 0, NULL);
if (data->yuv) {
@ -1632,6 +1630,7 @@ D3D_Reset(SDL_Renderer * renderer)
IDirect3DVertexBuffer9_Release(data->vertexBuffers[i]);
}
data->vertexBuffers[i] = NULL;
data->vertexBufferSize[i] = 0;
}
result = IDirect3DDevice9_Reset(data->device, &data->pparams);

View File

@ -898,6 +898,7 @@ SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf,
SDL_memset(outbuf, 0, 4);
while (inbytesleft > 0) {
const size_t oldinbytesleft = inbytesleft;
retCode = SDL_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
switch (retCode) {
case SDL_ICONV_E2BIG:
@ -925,6 +926,11 @@ SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf,
inbytesleft = 0;
break;
}
/* Avoid infinite loops when nothing gets converted */
if (oldinbytesleft == inbytesleft)
{
break;
}
}
SDL_iconv_close(cd);

View File

@ -438,11 +438,15 @@ int SDL_abs(int x)
#if defined(HAVE_CTYPE_H)
int SDL_isdigit(int x) { return isdigit(x); }
int SDL_isspace(int x) { return isspace(x); }
int SDL_isupper(int x) { return isupper(x); }
int SDL_islower(int x) { return islower(x); }
int SDL_toupper(int x) { return toupper(x); }
int SDL_tolower(int x) { return tolower(x); }
#else
int SDL_isdigit(int x) { return ((x) >= '0') && ((x) <= '9'); }
int SDL_isspace(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n') || ((x) == '\f') || ((x) == '\v'); }
int SDL_isupper(int x) { return ((x) >= 'A') && ((x) <= 'Z'); }
int SDL_islower(int x) { return ((x) >= 'a') && ((x) <= 'z'); }
int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A'+((x)-'a')) : (x); }
int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a'+((x)-'A')) : (x); }
#endif

View File

@ -96,19 +96,30 @@ extern "C"
int
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{
// Thread priorities do not look to be settable via C++11's thread
// interface, at least as of this writing (Nov 2012). std::thread does
// provide access to the OS' native handle, however, and some form of
// priority-setting could, in theory, be done through this interface.
//
// WinRT: UPDATE (Aug 20, 2013): thread priorities cannot be changed
// on WinRT, at least not for any thread that's already been created.
// WinRT threads appear to be based off of the WinRT class,
// ThreadPool, more info on which can be found at:
// http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.threading.threadpool.aspx
//
// For compatibility sake, 0 will be returned here.
return (0);
#ifdef __WINRT__
int value;
if (priority == SDL_THREAD_PRIORITY_LOW) {
value = THREAD_PRIORITY_LOWEST;
}
else if (priority == SDL_THREAD_PRIORITY_HIGH) {
value = THREAD_PRIORITY_HIGHEST;
}
else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
// FIXME: WinRT does not support TIME_CRITICAL! -flibit
SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "TIME_CRITICAL unsupported, falling back to HIGHEST");
value = THREAD_PRIORITY_HIGHEST;
}
else {
value = THREAD_PRIORITY_NORMAL;
}
if (!SetThreadPriority(GetCurrentThread(), value)) {
return WIN_SetError("SetThreadPriority()");
}
return 0;
#else
return SDL_Unsupported();
#endif
}
extern "C"

View File

@ -962,8 +962,10 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_Color copy_color;
SDL_Rect bounds;
int ret;
int palette_ck_transform = 0;
SDL_bool palette_ck_transform = SDL_FALSE;
int palette_ck_value = 0;
SDL_bool palette_has_alpha = SDL_FALSE;
Uint8 *palette_saved_alpha = NULL;
if (!surface) {
SDL_InvalidParamError("surface");
@ -1025,10 +1027,45 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
bounds.w = surface->w;
bounds.h = surface->h;
/* Source surface has a palette with no real alpha (0 or OPAQUE).
* Destination format has alpha.
* -> set alpha channel to be opaque */
if (surface->format->palette && format->Amask) {
SDL_bool set_opaque = SDL_FALSE;
{
int i;
for (i = 0; i < surface->format->palette->ncolors; i++) {
Uint8 alpha_value = surface->format->palette->colors[i].a;
if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) {
/* Palette has at least one alpha value. Don't do anything */
set_opaque = SDL_FALSE;
palette_has_alpha = SDL_TRUE;
break;
}
if (alpha_value == 0) {
set_opaque = SDL_TRUE;
}
}
}
/* Set opaque and backup palette alpha values */
if (set_opaque) {
int i;
palette_saved_alpha = SDL_stack_alloc(Uint8, surface->format->palette->ncolors);
for (i = 0; i < surface->format->palette->ncolors; i++) {
palette_saved_alpha[i] = surface->format->palette->colors[i].a;
surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
}
}
}
/* Transform colorkey to alpha. for cases where source palette has duplicate values, and colorkey is one of them */
if (copy_flags & SDL_COPY_COLORKEY) {
if (surface->format->palette && !format->palette) {
palette_ck_transform = 1;
palette_ck_transform = SDL_TRUE;
palette_has_alpha = SDL_TRUE;
palette_ck_value = surface->format->palette->colors[surface->map->info.colorkey].a;
surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
}
@ -1036,11 +1073,20 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
ret = SDL_LowerBlit(surface, &bounds, convert, &bounds);
/* Restore value */
/* Restore colorkey alpha value */
if (palette_ck_transform) {
surface->format->palette->colors[surface->map->info.colorkey].a = palette_ck_value;
}
/* Restore palette alpha values */
if (palette_saved_alpha) {
int i;
for (i = 0; i < surface->format->palette->ncolors; i++) {
surface->format->palette->colors[i].a = palette_saved_alpha[i];
}
SDL_stack_free(palette_saved_alpha);
}
/* Clean up the original surface, and update converted surface */
convert->map->info.r = copy_color.r;
convert->map->info.g = copy_color.g;
@ -1066,7 +1112,6 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
if (copy_flags & SDL_COPY_COLORKEY) {
SDL_bool set_colorkey_by_color = SDL_FALSE;
SDL_bool ignore_alpha = SDL_TRUE; /* Ignore, or not, alpha in colorkey comparison */
if (surface->format->palette) {
if (format->palette &&
@ -1077,9 +1122,6 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
} else if (!format->palette) {
/* Was done by 'palette_ck_transform' */
}else if (format->Amask) {
set_colorkey_by_color = SDL_TRUE;
ignore_alpha = SDL_FALSE;
} else {
set_colorkey_by_color = SDL_TRUE;
}
@ -1120,7 +1162,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
SDL_SetColorKey(convert, 1, converted_colorkey);
/* This is needed when converting for 3D texture upload */
SDL_ConvertColorkeyToAlpha(convert, ignore_alpha);
SDL_ConvertColorkeyToAlpha(convert, SDL_TRUE);
}
}
SDL_SetClipRect(convert, &surface->clip_rect);
@ -1128,6 +1170,7 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format,
/* Enable alpha blending by default if the new surface has an
* alpha channel or alpha modulation */
if ((surface->format->Amask && format->Amask) ||
(palette_has_alpha && format->Amask) ||
(copy_flags & SDL_COPY_MODULATE_ALPHA)) {
SDL_SetSurfaceBlendMode(convert, SDL_BLENDMODE_BLEND);
}

View File

@ -116,7 +116,7 @@ struct SDL_WindowData
NSView *sdlContentView; /* nil if window is created via CreateWindowFrom */
NSMutableArray *nscontexts;
SDL_bool created;
SDL_bool inWindowMove;
SDL_bool inWindowFullscreenTransition;
Cocoa_WindowListener *listener;
struct SDL_VideoData *videodata;
#if SDL_VIDEO_OPENGL_EGL

View File

@ -876,7 +876,7 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
button = [nswindow standardWindowButton:NSWindowMiniaturizeButton];
if (button) {
int iterations = 0;
while (![button isEnabled]) {
while (![button isEnabled] && (iterations < 100)) {
SDL_Delay(10);
SDL_PumpEvents();
iterations++;
@ -1740,8 +1740,6 @@ Cocoa_MinimizeWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
printf("Cocoa_MinimizeWindow begin %u\n", (unsigned int) SDL_GetTicks());
if ([data->listener isInFullscreenSpaceTransition]) {
[data->listener addPendingWindowOperation:PENDING_OPERATION_MINIMIZE];
} else {
@ -2032,6 +2030,11 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
SDL_bool succeeded = SDL_FALSE;
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data->inWindowFullscreenTransition) {
return SDL_FALSE;
}
data->inWindowFullscreenTransition = SDL_TRUE;
if ([data->listener setFullscreenSpace:(state ? YES : NO)]) {
const int maxattempts = 3;
int attempt = 0;
@ -2058,6 +2061,7 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
/* Return TRUE to prevent non-space fullscreen logic from running */
succeeded = SDL_TRUE;
}
data->inWindowFullscreenTransition = SDL_FALSE;
return succeeded;
}}

View File

@ -206,14 +206,14 @@ static const SDL_Scancode emscripten_scancode_table[] = {
/* 160 */ SDL_SCANCODE_UNKNOWN,
/* 161 */ SDL_SCANCODE_UNKNOWN,
/* 162 */ SDL_SCANCODE_UNKNOWN,
/* 163 */ SDL_SCANCODE_UNKNOWN,
/* 163 */ SDL_SCANCODE_KP_HASH, /*KaiOS phone keypad*/
/* 164 */ SDL_SCANCODE_UNKNOWN,
/* 165 */ SDL_SCANCODE_UNKNOWN,
/* 166 */ SDL_SCANCODE_UNKNOWN,
/* 167 */ SDL_SCANCODE_UNKNOWN,
/* 168 */ SDL_SCANCODE_UNKNOWN,
/* 169 */ SDL_SCANCODE_UNKNOWN,
/* 170 */ SDL_SCANCODE_UNKNOWN,
/* 170 */ SDL_SCANCODE_KP_MULTIPLY, /*KaiOS phone keypad*/
/* 171 */ SDL_SCANCODE_UNKNOWN,
/* 172 */ SDL_SCANCODE_UNKNOWN,
/* 173 */ SDL_SCANCODE_MINUS, /*FX*/

View File

@ -37,7 +37,8 @@
int
KMSDRM_GLES_LoadLibrary(_THIS, const char *path) {
return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA);
NativeDisplayType display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm;
return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA);
}
SDL_EGL_CreateContext_impl(KMSDRM)

View File

@ -349,10 +349,9 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout) {
/* SDL Video and Display initialization/handling functions */
/* _this is a SDL_VideoDevice * */
/*****************************************************************************/
static int
static void
KMSDRM_DestroySurfaces(_THIS, SDL_Window * window)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
KMSDRM_WaitPageFlip(_this, windata, -1);
@ -651,7 +650,7 @@ KMSDRM_VideoQuit(_THIS)
viddata->num_windows = 0;
/* Restore saved CRTC settings */
if (viddata->drm_fd >= 0 && dispdata->conn && dispdata->saved_crtc) {
if (viddata->drm_fd >= 0 && dispdata && dispdata->conn && dispdata->saved_crtc) {
drmModeConnector *conn = dispdata->conn;
drmModeCrtc *crtc = dispdata->saved_crtc;
@ -662,11 +661,11 @@ KMSDRM_VideoQuit(_THIS)
SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
}
}
if (dispdata->conn) {
if (dispdata && dispdata->conn) {
KMSDRM_drmModeFreeConnector(dispdata->conn);
dispdata->conn = NULL;
}
if (dispdata->saved_crtc) {
if (dispdata && dispdata->saved_crtc) {
KMSDRM_drmModeFreeCrtc(dispdata->saved_crtc);
dispdata->saved_crtc = NULL;
}
@ -809,6 +808,10 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
viddata->windows[viddata->num_windows++] = window;
/* Focus on the newly created window */
SDL_SetMouseFocus(window);
SDL_SetKeyboardFocus(window);
return 0;
error: