SDL  2.0
SDL_hidapi_gamecube.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #ifdef SDL_JOYSTICK_HIDAPI
24 
25 #include "SDL_hints.h"
26 #include "SDL_events.h"
27 #include "SDL_timer.h"
28 #include "SDL_haptic.h"
29 #include "SDL_joystick.h"
30 #include "SDL_gamecontroller.h"
31 #include "../../SDL_hints_c.h"
32 #include "../SDL_sysjoystick.h"
33 #include "SDL_hidapijoystick_c.h"
34 #include "SDL_hidapi_rumble.h"
35 
36 
37 #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
38 
39 #define MAX_CONTROLLERS 4
40 
41 typedef struct {
42  SDL_JoystickID joysticks[MAX_CONTROLLERS];
43  Uint8 wireless[MAX_CONTROLLERS];
44  Uint8 min_axis[MAX_CONTROLLERS*SDL_CONTROLLER_AXIS_MAX];
45  Uint8 max_axis[MAX_CONTROLLERS*SDL_CONTROLLER_AXIS_MAX];
46  Uint8 rumbleAllowed[MAX_CONTROLLERS];
47  Uint8 rumble[1+MAX_CONTROLLERS];
48  /* Without this variable, hid_write starts to lag a TON */
49  SDL_bool rumbleUpdate;
50  SDL_bool m_bUseButtonLabels;
51 } SDL_DriverGameCube_Context;
52 
53 static SDL_bool
54 HIDAPI_DriverGameCube_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)
55 {
56  if (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER) {
57  /* Nintendo Co., Ltd. Wii U GameCube Controller Adapter */
58  return SDL_TRUE;
59  }
60  return SDL_FALSE;
61 }
62 
63 static const char *
64 HIDAPI_DriverGameCube_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
65 {
66  return "Nintendo GameCube Controller";
67 }
68 
69 static void
70 ResetAxisRange(SDL_DriverGameCube_Context *ctx, int joystick_index)
71 {
72  SDL_memset(&ctx->min_axis[joystick_index*SDL_CONTROLLER_AXIS_MAX], 128-88, SDL_CONTROLLER_AXIS_MAX);
73  SDL_memset(&ctx->max_axis[joystick_index*SDL_CONTROLLER_AXIS_MAX], 128+88, SDL_CONTROLLER_AXIS_MAX);
74 
75  /* Trigger axes may have a higher resting value */
76  ctx->min_axis[joystick_index*SDL_CONTROLLER_AXIS_MAX+SDL_CONTROLLER_AXIS_TRIGGERLEFT] = 40;
77  ctx->min_axis[joystick_index*SDL_CONTROLLER_AXIS_MAX+SDL_CONTROLLER_AXIS_TRIGGERRIGHT] = 40;
78 }
79 
80 static float fsel(float fComparand, float fValGE, float fLT)
81 {
82  return fComparand >= 0 ? fValGE : fLT;
83 }
84 
85 static float RemapVal(float val, float A, float B, float C, float D)
86 {
87  if (A == B) {
88  return fsel(val - B , D , C);
89  }
90  if (val < A) {
91  val = A;
92  }
93  if (val > B) {
94  val = B;
95  }
96  return C + (D - C) * (val - A) / (B - A);
97 }
98 
99 static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
100 {
101  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
102  ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
103 }
104 
105 static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
106 {
107  if (!ctx->m_bUseButtonLabels) {
108  /* Use button positions */
109  switch (button) {
114  default:
115  break;
116  }
117  }
118  return button;
119 }
120 
121 static SDL_bool
122 HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
123 {
124  SDL_DriverGameCube_Context *ctx;
125  Uint8 packet[37];
126  Uint8 *curSlot;
127  Uint8 i;
128  int size;
129  Uint8 initMagic = 0x13;
130  Uint8 rumbleMagic = 0x11;
131 
132  ctx = (SDL_DriverGameCube_Context *)SDL_calloc(1, sizeof(*ctx));
133  if (!ctx) {
134  SDL_OutOfMemory();
135  return SDL_FALSE;
136  }
137 
138  device->dev = hid_open_path(device->path, 0);
139  if (!device->dev) {
140  SDL_free(ctx);
141  SDL_SetError("Couldn't open %s", device->path);
142  return SDL_FALSE;
143  }
144  device->context = ctx;
145 
146  ctx->joysticks[0] = -1;
147  ctx->joysticks[1] = -1;
148  ctx->joysticks[2] = -1;
149  ctx->joysticks[3] = -1;
150  ctx->rumble[0] = rumbleMagic;
151 
152  /* This is all that's needed to initialize the device. Really! */
153  if (hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
154  SDL_SetError("Couldn't initialize WUP-028");
155  goto error;
156  }
157 
158  /* Wait for the adapter to initialize */
159  SDL_Delay(10);
160 
161  /* Add all the applicable joysticks */
162  while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
163  if (size < 37 || packet[0] != 0x21) {
164  continue; /* Nothing to do yet...? */
165  }
166 
167  /* Go through all 4 slots */
168  curSlot = packet + 1;
169  for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
170  ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
171 
172  /* Only allow rumble if the adapter's second USB cable is connected */
173  ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) != 0 && !ctx->wireless[i];
174 
175  if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
176  if (ctx->joysticks[i] == -1) {
177  ResetAxisRange(ctx, i);
178  HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
179  }
180  } else {
181  if (ctx->joysticks[i] != -1) {
182  HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
183  ctx->joysticks[i] = -1;
184  }
185  continue;
186  }
187  }
188  }
189 
191  SDL_GameControllerButtonReportingHintChanged, ctx);
192 
193  return SDL_TRUE;
194 
195 error:
196  if (device->dev) {
197  hid_close(device->dev);
198  device->dev = NULL;
199  }
200  if (device->context) {
201  SDL_free(device->context);
202  device->context = NULL;
203  }
204  return SDL_FALSE;
205 }
206 
207 static int
208 HIDAPI_DriverGameCube_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
209 {
210  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
211  Uint8 i;
212 
213  for (i = 0; i < 4; ++i) {
214  if (instance_id == ctx->joysticks[i]) {
215  return i;
216  }
217  }
218  return -1;
219 }
220 
221 static void
222 HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
223 {
224 }
225 
226 static SDL_bool
227 HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
228 {
229  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
230  SDL_Joystick *joystick;
231  Uint8 packet[37];
232  Uint8 *curSlot;
233  Uint8 i;
234  Sint16 axis_value;
235  int size;
236 
237  /* Read input packet */
238  while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
239  if (size < 37 || packet[0] != 0x21) {
240  continue; /* Nothing to do right now...? */
241  }
242 
243  /* Go through all 4 slots */
244  curSlot = packet + 1;
245  for (i = 0; i < MAX_CONTROLLERS; i += 1, curSlot += 9) {
246  ctx->wireless[i] = (curSlot[0] & 0x20) != 0;
247 
248  /* Only allow rumble if the adapter's second USB cable is connected */
249  ctx->rumbleAllowed[i] = (curSlot[0] & 0x04) != 0 && !ctx->wireless[i];
250 
251  if (curSlot[0] & 0x30) { /* 0x10 - Wired, 0x20 - Wireless */
252  if (ctx->joysticks[i] == -1) {
253  ResetAxisRange(ctx, i);
254  HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
255  }
256  joystick = SDL_JoystickFromInstanceID(ctx->joysticks[i]);
257 
258  /* Hasn't been opened yet, skip */
259  if (joystick == NULL) {
260  continue;
261  }
262  } else {
263  if (ctx->joysticks[i] != -1) {
264  HIDAPI_JoystickDisconnected(device, ctx->joysticks[i]);
265  ctx->joysticks[i] = -1;
266  }
267  continue;
268  }
269 
270  #define READ_BUTTON(off, flag, button) \
271  SDL_PrivateJoystickButton( \
272  joystick, \
273  RemapButton(ctx, button), \
274  (curSlot[off] & flag) ? SDL_PRESSED : SDL_RELEASED \
275  );
276  READ_BUTTON(1, 0x01, 0) /* A */
277  READ_BUTTON(1, 0x04, 1) /* B */
278  READ_BUTTON(1, 0x02, 2) /* X */
279  READ_BUTTON(1, 0x08, 3) /* Y */
280  READ_BUTTON(1, 0x10, 4) /* DPAD_LEFT */
281  READ_BUTTON(1, 0x20, 5) /* DPAD_RIGHT */
282  READ_BUTTON(1, 0x40, 6) /* DPAD_DOWN */
283  READ_BUTTON(1, 0x80, 7) /* DPAD_UP */
284  READ_BUTTON(2, 0x01, 8) /* START */
285  READ_BUTTON(2, 0x02, 9) /* RIGHTSHOULDER */
286  /* These two buttons are for the bottoms of the analog triggers.
287  * More than likely, you're going to want to read the axes instead!
288  * -flibit
289  */
290  READ_BUTTON(2, 0x04, 10) /* TRIGGERRIGHT */
291  READ_BUTTON(2, 0x08, 11) /* TRIGGERLEFT */
292  #undef READ_BUTTON
293 
294  #define READ_AXIS(off, axis) \
295  if (axis < SDL_CONTROLLER_AXIS_TRIGGERLEFT) \
296  if (curSlot[off] < ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis]) ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis] = curSlot[off]; \
297  if (curSlot[off] > ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis]) ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis] = curSlot[off]; \
298  axis_value = (Sint16)(RemapVal(curSlot[off], ctx->min_axis[i*SDL_CONTROLLER_AXIS_MAX+axis], ctx->max_axis[i*SDL_CONTROLLER_AXIS_MAX+axis], SDL_MIN_SINT16, SDL_MAX_SINT16)); \
299  SDL_PrivateJoystickAxis( \
300  joystick, \
301  axis, axis_value \
302  );
303  READ_AXIS(3, SDL_CONTROLLER_AXIS_LEFTX)
304  READ_AXIS(4, SDL_CONTROLLER_AXIS_LEFTY)
305  READ_AXIS(5, SDL_CONTROLLER_AXIS_RIGHTX)
306  READ_AXIS(6, SDL_CONTROLLER_AXIS_RIGHTY)
307  READ_AXIS(7, SDL_CONTROLLER_AXIS_TRIGGERLEFT)
309  #undef READ_AXIS
310  }
311  }
312 
313  /* Write rumble packet */
314  if (ctx->rumbleUpdate) {
315  SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
316  ctx->rumbleUpdate = SDL_FALSE;
317  }
318 
319  /* If we got here, nothing bad happened! */
320  return SDL_TRUE;
321 }
322 
323 static SDL_bool
324 HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
325 {
326  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
327  Uint8 i;
328  for (i = 0; i < MAX_CONTROLLERS; i += 1) {
329  if (joystick->instance_id == ctx->joysticks[i]) {
330  joystick->nbuttons = 12;
332  joystick->epowerlevel = ctx->wireless[i] ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
333  return SDL_TRUE;
334  }
335  }
336  return SDL_FALSE; /* Should never get here! */
337 }
338 
339 static int
340 HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
341 {
342  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
343  Uint8 i, val;
344  for (i = 0; i < MAX_CONTROLLERS; i += 1) {
345  if (joystick->instance_id == ctx->joysticks[i]) {
346  if (ctx->wireless[i]) {
347  return SDL_SetError("Ninteno GameCube WaveBird controllers do not support rumble");
348  }
349  if (!ctx->rumbleAllowed[i]) {
350  return SDL_SetError("Second USB cable for WUP-028 not connected");
351  }
352  val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
353  if (val != ctx->rumble[i + 1]) {
354  ctx->rumble[i + 1] = val;
355  ctx->rumbleUpdate = SDL_TRUE;
356  }
357  return 0;
358  }
359  }
360 
361  /* Should never get here! */
362  SDL_SetError("Couldn't find joystick");
363  return -1;
364 }
365 
366 static int
367 HIDAPI_DriverGameCube_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
368 {
369  return SDL_Unsupported();
370 }
371 
372 static SDL_bool
373 HIDAPI_DriverGameCube_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
374 {
375  return SDL_FALSE;
376 }
377 
378 static int
379 HIDAPI_DriverGameCube_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
380 {
381  return SDL_Unsupported();
382 }
383 
384 static int
385 HIDAPI_DriverGameCube_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
386 {
387  return SDL_Unsupported();
388 }
389 
390 static void
391 HIDAPI_DriverGameCube_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
392 {
393  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
394 
395  /* Stop rumble activity */
396  if (ctx->rumbleUpdate) {
397  SDL_HIDAPI_SendRumble(device, ctx->rumble, sizeof(ctx->rumble));
398  ctx->rumbleUpdate = SDL_FALSE;
399  }
400 }
401 
402 static void
403 HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
404 {
405  SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
406 
407  hid_close(device->dev);
408  device->dev = NULL;
409 
411  SDL_GameControllerButtonReportingHintChanged, ctx);
412 
413  SDL_free(device->context);
414  device->context = NULL;
415 }
416 
418 {
420  SDL_TRUE,
421  HIDAPI_DriverGameCube_IsSupportedDevice,
422  HIDAPI_DriverGameCube_GetDeviceName,
423  HIDAPI_DriverGameCube_InitDevice,
424  HIDAPI_DriverGameCube_GetDevicePlayerIndex,
425  HIDAPI_DriverGameCube_SetDevicePlayerIndex,
426  HIDAPI_DriverGameCube_UpdateDevice,
427  HIDAPI_DriverGameCube_OpenJoystick,
428  HIDAPI_DriverGameCube_RumbleJoystick,
429  HIDAPI_DriverGameCube_RumbleJoystickTriggers,
430  HIDAPI_DriverGameCube_HasJoystickLED,
431  HIDAPI_DriverGameCube_SetJoystickLED,
432  HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,
433  HIDAPI_DriverGameCube_CloseJoystick,
434  HIDAPI_DriverGameCube_FreeDevice,
435 };
436 
437 #endif /* SDL_JOYSTICK_HIDAPI_GAMECUBE */
438 
439 #endif /* SDL_JOYSTICK_HIDAPI */
440 
441 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_SetError
#define SDL_memset
#define SDL_DelHintCallback
#define SDL_JoystickFromInstanceID
#define SDL_free
#define SDL_Delay
#define SDL_AddHintCallback
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_Unsupported()
Definition: SDL_error.h:89
@ SDL_CONTROLLER_AXIS_LEFTX
@ SDL_CONTROLLER_AXIS_TRIGGERRIGHT
@ SDL_CONTROLLER_AXIS_RIGHTY
@ SDL_CONTROLLER_AXIS_RIGHTX
@ SDL_CONTROLLER_AXIS_MAX
@ SDL_CONTROLLER_AXIS_TRIGGERLEFT
@ SDL_CONTROLLER_AXIS_LEFTY
@ SDL_CONTROLLER_BUTTON_B
@ SDL_CONTROLLER_BUTTON_X
SDL_GameControllerType
const GLubyte GLuint red
Definition: SDL_glfuncs.h:80
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
SDL_bool HIDAPI_JoystickConnected(SDL_HIDAPI_Device *device, SDL_JoystickID *pJoystickID)
void HIDAPI_JoystickDisconnected(SDL_HIDAPI_Device *device, SDL_JoystickID joystickID)
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube
SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value)
Definition: SDL_hints.c:123
#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS
If set, game controller face buttons report their values according to their labels instead of their p...
Definition: SDL_hints.h:570
#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE
A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
Definition: SDL_hints.h:688
#define SDLCALL
Definition: SDL_internal.h:49
@ SDL_JOYSTICK_POWER_UNKNOWN
Definition: SDL_joystick.h:99
@ SDL_JOYSTICK_POWER_WIRED
Definition: SDL_joystick.h:104
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLbyte GLbyte blue
GLuint GLfloat * val
GLuint const GLchar * name
GLsizeiptr size
GLbyte green
uint16_t Uint16
Definition: SDL_stdinc.h:197
int16_t Sint16
Definition: SDL_stdinc.h:191
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
uint8_t Uint8
Definition: SDL_stdinc.h:185
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
EGLContext ctx
Definition: eglext.h:208
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned char *data, size_t length, int milliseconds)
Read an Input report from a HID device with timeout.
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path, int bExclusive)
Open a HID device by its path name.
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device)
Close a HID device.
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length)
Write an Output report to a HID device.
static SDL_AudioDeviceID device
Definition: loopwave.c:37
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
SDL_Texture * button
static SDL_Joystick * joystick
Definition: testjoystick.c:37
#define USB_VENDOR_NINTENDO
Definition: usb_ids.h:30
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER
Definition: usb_ids.h:38