1
//============================================================
3
// input.c - Win32 implementation of MAME input routines
5
//============================================================
7
// Copyright Aaron Giles
8
// All rights reserved.
10
// Redistribution and use in source and binary forms, with or
11
// without modification, are permitted provided that the
12
// following conditions are met:
14
// * Redistributions of source code must retain the above
15
// copyright notice, this list of conditions and the
16
// following disclaimer.
17
// * Redistributions in binary form must reproduce the
18
// above copyright notice, this list of conditions and
19
// the following disclaimer in the documentation and/or
20
// other materials provided with the distribution.
21
// * Neither the name 'MAME' nor the names of its
22
// contributors may be used to endorse or promote
23
// products derived from this software without specific
24
// prior written permission.
26
// THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND
27
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30
// EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
31
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32
// DAMAGE (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
35
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
38
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
//============================================================
42
// For testing purposes: force DirectInput
43
#define FORCE_DIRECTINPUT 0
45
// standard windows headers
46
#define WIN32_LEAN_AND_MEAN
51
// undef WINNT for dinput.h to prevent duplicate definition
75
//============================================================
77
//============================================================
96
//============================================================
98
//============================================================
100
#define STRUCTSIZE(x) ((dinput_version == 0x0300) ? sizeof(x##_DX3) : sizeof(x))
103
#define UNICODE_SUFFIX "W"
105
#define UNICODE_SUFFIX "A"
110
//============================================================
112
//============================================================
114
// state information for a keyboard; DirectInput state must be first element
115
typedef struct _keyboard_state keyboard_state;
116
struct _keyboard_state
118
UINT8 state[MAX_KEYS];
119
INT8 oldkey[MAX_KEYS];
120
INT8 currkey[MAX_KEYS];
124
// state information for a mouse; DirectInput state must be first element
125
typedef struct _mouse_state mouse_state;
129
LONG raw_x, raw_y, raw_z;
133
// state information for a joystick; DirectInput state must be first element
134
typedef struct _joystick_state joystick_state;
135
struct _joystick_state
143
// DirectInput-specific information about a device
144
typedef struct _dinput_device_info dinput_device_info;
145
struct _dinput_device_info
147
LPDIRECTINPUTDEVICE device;
148
LPDIRECTINPUTDEVICE2 device2;
150
LPCDIDATAFORMAT format;
154
// RawInput-specific information about a device
155
typedef struct _rawinput_device_info rawinput_device_info;
156
struct _rawinput_device_info
162
// generic device information
166
device_info(running_machine &machine)
167
: m_machine(machine) { }
169
running_machine &machine() const { return m_machine; }
171
// device information
175
void (*poll)(device_info *info);
178
input_device * device;
183
keyboard_state keyboard;
185
joystick_state joystick;
188
// DirectInput/RawInput-specific state
189
dinput_device_info dinput;
190
rawinput_device_info rawinput;
193
running_machine & m_machine;
198
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_list_ptr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PINT puiNumDevices, IN UINT cbSize);
199
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_data_ptr)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize, IN UINT cbSizeHeader);
200
typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_info_ptr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize);
201
typedef /*WINUSERAPI*/ BOOL (WINAPI *register_rawinput_devices_ptr)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
205
//============================================================
207
//============================================================
210
static UINT8 input_enabled;
211
static osd_lock * input_lock;
212
static UINT8 input_paused;
213
static DWORD last_poll;
215
// DirectInput variables
216
static LPDIRECTINPUT dinput;
217
static int dinput_version;
219
// RawInput variables
220
static get_rawinput_device_list_ptr get_rawinput_device_list;
221
static get_rawinput_data_ptr get_rawinput_data;
222
static get_rawinput_device_info_ptr get_rawinput_device_info;
223
static register_rawinput_devices_ptr register_rawinput_devices;
226
static UINT8 keyboard_win32_reported_key_down;
227
static device_info * keyboard_list;
230
static UINT8 mouse_enabled;
231
static device_info * mouse_list;
234
static UINT8 lightgun_shared_axis_mode;
235
static UINT8 lightgun_enabled;
236
static device_info * lightgun_list;
239
static device_info * joystick_list;
241
// default axis names
242
static const TCHAR *const default_axis_name[] =
244
TEXT("X"), TEXT("Y"), TEXT("Z"), TEXT("RX"),
245
TEXT("RY"), TEXT("RZ"), TEXT("SL1"), TEXT("SL2")
250
//============================================================
252
//============================================================
254
static void wininput_pause(running_machine &machine);
255
static void wininput_resume(running_machine &machine);
256
static void wininput_exit(running_machine &machine);
258
// device list management
259
static void device_list_poll_devices(device_info *devlist_head);
260
static void device_list_reset_devices(device_info *devlist_head);
262
// generic device management
263
static device_info *generic_device_alloc(running_machine &machine, device_info **devlist_head_ptr, const TCHAR *name);
264
static void generic_device_free(device_info *devinfo);
265
static int generic_device_index(device_info *devlist_head, device_info *devinfo);
266
static void generic_device_reset(device_info *devinfo);
267
static INT32 generic_button_get_state(void *device_internal, void *item_internal);
268
static INT32 generic_axis_get_state(void *device_internal, void *item_internal);
270
// Win32-specific input code
271
static void win32_init(running_machine &machine);
272
static void win32_exit(running_machine &machine);
273
static void win32_keyboard_poll(device_info *devinfo);
274
static void win32_lightgun_poll(device_info *devinfo);
276
// DirectInput-specific code
277
static void dinput_init(running_machine &machine);
278
static void dinput_exit(running_machine &machine);
279
static HRESULT dinput_set_dword_property(LPDIRECTINPUTDEVICE device, REFGUID property_guid, DWORD object, DWORD how, DWORD value);
280
static device_info *dinput_device_create(running_machine &machine, device_info **devlist_head_ptr, LPCDIDEVICEINSTANCE instance, LPCDIDATAFORMAT format1, LPCDIDATAFORMAT format2, DWORD cooperative_level);
281
static void dinput_device_release(device_info *devinfo);
282
static char *dinput_device_item_name(device_info *devinfo, int offset, const TCHAR *defstring, const TCHAR *suffix);
283
static HRESULT dinput_device_poll(device_info *devinfo);
284
static BOOL CALLBACK dinput_keyboard_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
285
static void dinput_keyboard_poll(device_info *devinfo);
286
static BOOL CALLBACK dinput_mouse_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
287
static void dinput_mouse_poll(device_info *devinfo);
288
static BOOL CALLBACK dinput_joystick_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
289
static void dinput_joystick_poll(device_info *devinfo);
290
static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal);
292
// RawInput-specific code
293
static void rawinput_init(running_machine &machine);
294
static void rawinput_exit(running_machine &machine);
295
static device_info *rawinput_device_create(running_machine &machine, device_info **devlist_head_ptr, PRAWINPUTDEVICELIST device);
296
static void rawinput_device_release(device_info *info);
297
static TCHAR *rawinput_device_improve_name(TCHAR *name);
298
static void rawinput_keyboard_enum(running_machine &machine, PRAWINPUTDEVICELIST device);
299
static void rawinput_keyboard_update(HANDLE device, RAWKEYBOARD *data);
300
static void rawinput_mouse_enum(running_machine &machine, PRAWINPUTDEVICELIST device);
301
static void rawinput_mouse_update(HANDLE device, RAWMOUSE *data);
302
static void rawinput_mouse_poll(device_info *devinfo);
305
static TCHAR *reg_query_string(HKEY key, const TCHAR *path);
306
static const TCHAR *default_button_name(int which);
307
static const TCHAR *default_pov_name(int which);
311
//============================================================
312
// KEYBOARD/JOYSTICK LIST
313
//============================================================
315
// master keyboard translation table
316
static const int win_key_trans_table[][4] =
318
// MAME key dinput key virtual key ascii
319
{ ITEM_ID_ESC, DIK_ESCAPE, VK_ESCAPE, 27 },
320
{ ITEM_ID_1, DIK_1, '1', '1' },
321
{ ITEM_ID_2, DIK_2, '2', '2' },
322
{ ITEM_ID_3, DIK_3, '3', '3' },
323
{ ITEM_ID_4, DIK_4, '4', '4' },
324
{ ITEM_ID_5, DIK_5, '5', '5' },
325
{ ITEM_ID_6, DIK_6, '6', '6' },
326
{ ITEM_ID_7, DIK_7, '7', '7' },
327
{ ITEM_ID_8, DIK_8, '8', '8' },
328
{ ITEM_ID_9, DIK_9, '9', '9' },
329
{ ITEM_ID_0, DIK_0, '0', '0' },
330
{ ITEM_ID_MINUS, DIK_MINUS, VK_OEM_MINUS, '-' },
331
{ ITEM_ID_EQUALS, DIK_EQUALS, VK_OEM_PLUS, '=' },
332
{ ITEM_ID_BACKSPACE, DIK_BACK, VK_BACK, 8 },
333
{ ITEM_ID_TAB, DIK_TAB, VK_TAB, 9 },
334
{ ITEM_ID_Q, DIK_Q, 'Q', 'Q' },
335
{ ITEM_ID_W, DIK_W, 'W', 'W' },
336
{ ITEM_ID_E, DIK_E, 'E', 'E' },
337
{ ITEM_ID_R, DIK_R, 'R', 'R' },
338
{ ITEM_ID_T, DIK_T, 'T', 'T' },
339
{ ITEM_ID_Y, DIK_Y, 'Y', 'Y' },
340
{ ITEM_ID_U, DIK_U, 'U', 'U' },
341
{ ITEM_ID_I, DIK_I, 'I', 'I' },
342
{ ITEM_ID_O, DIK_O, 'O', 'O' },
343
{ ITEM_ID_P, DIK_P, 'P', 'P' },
344
{ ITEM_ID_OPENBRACE, DIK_LBRACKET, VK_OEM_4, '[' },
345
{ ITEM_ID_CLOSEBRACE, DIK_RBRACKET, VK_OEM_6, ']' },
346
{ ITEM_ID_ENTER, DIK_RETURN, VK_RETURN, 13 },
347
{ ITEM_ID_LCONTROL, DIK_LCONTROL, VK_LCONTROL, 0 },
348
{ ITEM_ID_A, DIK_A, 'A', 'A' },
349
{ ITEM_ID_S, DIK_S, 'S', 'S' },
350
{ ITEM_ID_D, DIK_D, 'D', 'D' },
351
{ ITEM_ID_F, DIK_F, 'F', 'F' },
352
{ ITEM_ID_G, DIK_G, 'G', 'G' },
353
{ ITEM_ID_H, DIK_H, 'H', 'H' },
354
{ ITEM_ID_J, DIK_J, 'J', 'J' },
355
{ ITEM_ID_K, DIK_K, 'K', 'K' },
356
{ ITEM_ID_L, DIK_L, 'L', 'L' },
357
{ ITEM_ID_COLON, DIK_SEMICOLON, VK_OEM_1, ';' },
358
{ ITEM_ID_QUOTE, DIK_APOSTROPHE, VK_OEM_7, '\'' },
359
{ ITEM_ID_TILDE, DIK_GRAVE, VK_OEM_3, '`' },
360
{ ITEM_ID_LSHIFT, DIK_LSHIFT, VK_LSHIFT, 0 },
361
{ ITEM_ID_BACKSLASH, DIK_BACKSLASH, VK_OEM_5, '\\' },
362
{ ITEM_ID_BACKSLASH2, DIK_OEM_102, VK_OEM_102, '<' },
363
{ ITEM_ID_Z, DIK_Z, 'Z', 'Z' },
364
{ ITEM_ID_X, DIK_X, 'X', 'X' },
365
{ ITEM_ID_C, DIK_C, 'C', 'C' },
366
{ ITEM_ID_V, DIK_V, 'V', 'V' },
367
{ ITEM_ID_B, DIK_B, 'B', 'B' },
368
{ ITEM_ID_N, DIK_N, 'N', 'N' },
369
{ ITEM_ID_M, DIK_M, 'M', 'M' },
370
{ ITEM_ID_COMMA, DIK_COMMA, VK_OEM_COMMA, ',' },
371
{ ITEM_ID_STOP, DIK_PERIOD, VK_OEM_PERIOD, '.' },
372
{ ITEM_ID_SLASH, DIK_SLASH, VK_OEM_2, '/' },
373
{ ITEM_ID_RSHIFT, DIK_RSHIFT, VK_RSHIFT, 0 },
374
{ ITEM_ID_ASTERISK, DIK_MULTIPLY, VK_MULTIPLY, '*' },
375
{ ITEM_ID_LALT, DIK_LMENU, VK_LMENU, 0 },
376
{ ITEM_ID_SPACE, DIK_SPACE, VK_SPACE, ' ' },
377
{ ITEM_ID_CAPSLOCK, DIK_CAPITAL, VK_CAPITAL, 0 },
378
{ ITEM_ID_F1, DIK_F1, VK_F1, 0 },
379
{ ITEM_ID_F2, DIK_F2, VK_F2, 0 },
380
{ ITEM_ID_F3, DIK_F3, VK_F3, 0 },
381
{ ITEM_ID_F4, DIK_F4, VK_F4, 0 },
382
{ ITEM_ID_F5, DIK_F5, VK_F5, 0 },
383
{ ITEM_ID_F6, DIK_F6, VK_F6, 0 },
384
{ ITEM_ID_F7, DIK_F7, VK_F7, 0 },
385
{ ITEM_ID_F8, DIK_F8, VK_F8, 0 },
386
{ ITEM_ID_F9, DIK_F9, VK_F9, 0 },
387
{ ITEM_ID_F10, DIK_F10, VK_F10, 0 },
388
{ ITEM_ID_NUMLOCK, DIK_NUMLOCK, VK_NUMLOCK, 0 },
389
{ ITEM_ID_SCRLOCK, DIK_SCROLL, VK_SCROLL, 0 },
390
{ ITEM_ID_7_PAD, DIK_NUMPAD7, VK_NUMPAD7, 0 },
391
{ ITEM_ID_8_PAD, DIK_NUMPAD8, VK_NUMPAD8, 0 },
392
{ ITEM_ID_9_PAD, DIK_NUMPAD9, VK_NUMPAD9, 0 },
393
{ ITEM_ID_MINUS_PAD, DIK_SUBTRACT, VK_SUBTRACT, 0 },
394
{ ITEM_ID_4_PAD, DIK_NUMPAD4, VK_NUMPAD4, 0 },
395
{ ITEM_ID_5_PAD, DIK_NUMPAD5, VK_NUMPAD5, 0 },
396
{ ITEM_ID_6_PAD, DIK_NUMPAD6, VK_NUMPAD6, 0 },
397
{ ITEM_ID_PLUS_PAD, DIK_ADD, VK_ADD, 0 },
398
{ ITEM_ID_1_PAD, DIK_NUMPAD1, VK_NUMPAD1, 0 },
399
{ ITEM_ID_2_PAD, DIK_NUMPAD2, VK_NUMPAD2, 0 },
400
{ ITEM_ID_3_PAD, DIK_NUMPAD3, VK_NUMPAD3, 0 },
401
{ ITEM_ID_0_PAD, DIK_NUMPAD0, VK_NUMPAD0, 0 },
402
{ ITEM_ID_DEL_PAD, DIK_DECIMAL, VK_DECIMAL, 0 },
403
{ ITEM_ID_F11, DIK_F11, VK_F11, 0 },
404
{ ITEM_ID_F12, DIK_F12, VK_F12, 0 },
405
{ ITEM_ID_F13, DIK_F13, VK_F13, 0 },
406
{ ITEM_ID_F14, DIK_F14, VK_F14, 0 },
407
{ ITEM_ID_F15, DIK_F15, VK_F15, 0 },
408
{ ITEM_ID_ENTER_PAD, DIK_NUMPADENTER, VK_RETURN, 0 },
409
{ ITEM_ID_RCONTROL, DIK_RCONTROL, VK_RCONTROL, 0 },
410
{ ITEM_ID_SLASH_PAD, DIK_DIVIDE, VK_DIVIDE, 0 },
411
{ ITEM_ID_PRTSCR, DIK_SYSRQ, 0, 0 },
412
{ ITEM_ID_RALT, DIK_RMENU, VK_RMENU, 0 },
413
{ ITEM_ID_HOME, DIK_HOME, VK_HOME, 0 },
414
{ ITEM_ID_UP, DIK_UP, VK_UP, 0 },
415
{ ITEM_ID_PGUP, DIK_PRIOR, VK_PRIOR, 0 },
416
{ ITEM_ID_LEFT, DIK_LEFT, VK_LEFT, 0 },
417
{ ITEM_ID_RIGHT, DIK_RIGHT, VK_RIGHT, 0 },
418
{ ITEM_ID_END, DIK_END, VK_END, 0 },
419
{ ITEM_ID_DOWN, DIK_DOWN, VK_DOWN, 0 },
420
{ ITEM_ID_PGDN, DIK_NEXT, VK_NEXT, 0 },
421
{ ITEM_ID_INSERT, DIK_INSERT, VK_INSERT, 0 },
422
{ ITEM_ID_DEL, DIK_DELETE, VK_DELETE, 0 },
423
{ ITEM_ID_LWIN, DIK_LWIN, VK_LWIN, 0 },
424
{ ITEM_ID_RWIN, DIK_RWIN, VK_RWIN, 0 },
425
{ ITEM_ID_MENU, DIK_APPS, VK_APPS, 0 },
426
{ ITEM_ID_PAUSE, DIK_PAUSE, VK_PAUSE, 0 },
427
{ ITEM_ID_CANCEL, 0, VK_CANCEL, 0 },
429
// New keys introduced in Windows 2000. These have no MAME codes to
430
// preserve compatibility with old config files that may refer to them
431
// as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table
432
// entries anyway because otherwise they aren't recognized when
433
// GetAsyncKeyState polling is used (as happens currently when MAME is
434
// paused). Some codes are missing because the mapping to vkey codes
435
// isn't clear, and MapVirtualKey is no help.
437
{ ITEM_ID_OTHER_SWITCH, DIK_MUTE, VK_VOLUME_MUTE, 0 },
438
{ ITEM_ID_OTHER_SWITCH, DIK_VOLUMEDOWN, VK_VOLUME_DOWN, 0 },
439
{ ITEM_ID_OTHER_SWITCH, DIK_VOLUMEUP, VK_VOLUME_UP, 0 },
440
{ ITEM_ID_OTHER_SWITCH, DIK_WEBHOME, VK_BROWSER_HOME, 0 },
441
{ ITEM_ID_OTHER_SWITCH, DIK_WEBSEARCH, VK_BROWSER_SEARCH, 0 },
442
{ ITEM_ID_OTHER_SWITCH, DIK_WEBFAVORITES, VK_BROWSER_FAVORITES, 0 },
443
{ ITEM_ID_OTHER_SWITCH, DIK_WEBREFRESH, VK_BROWSER_REFRESH, 0 },
444
{ ITEM_ID_OTHER_SWITCH, DIK_WEBSTOP, VK_BROWSER_STOP, 0 },
445
{ ITEM_ID_OTHER_SWITCH, DIK_WEBFORWARD, VK_BROWSER_FORWARD, 0 },
446
{ ITEM_ID_OTHER_SWITCH, DIK_WEBBACK, VK_BROWSER_BACK, 0 },
447
{ ITEM_ID_OTHER_SWITCH, DIK_MAIL, VK_LAUNCH_MAIL, 0 },
448
{ ITEM_ID_OTHER_SWITCH, DIK_MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0 },
452
//============================================================
454
//============================================================
456
INLINE void poll_if_necessary(running_machine &machine)
458
// make sure we poll at least once every 1/4 second
459
if (GetTickCount() > last_poll + 1000 / 4)
460
wininput_poll(machine);
464
INLINE input_item_id keyboard_map_scancode_to_itemid(int scancode)
468
// scan the table for a match
469
for (tablenum = 0; tablenum < ARRAY_LENGTH(win_key_trans_table); tablenum++)
470
if (win_key_trans_table[tablenum][DI_KEY] == scancode)
471
return (input_item_id)win_key_trans_table[tablenum][MAME_KEY];
473
// default to an "other" switch
474
return ITEM_ID_OTHER_SWITCH;
478
INLINE INT32 normalize_absolute_axis(INT32 raw, INT32 rawmin, INT32 rawmax)
480
INT32 center = (rawmax + rawmin) / 2;
482
// make sure we have valid data
483
if (rawmin >= rawmax)
489
INT32 result = (INT64)(raw - center) * (INT64)INPUT_ABSOLUTE_MAX / (INT64)(rawmax - center);
490
return MIN(result, INPUT_ABSOLUTE_MAX);
496
INT32 result = -((INT64)(center - raw) * (INT64)-INPUT_ABSOLUTE_MIN / (INT64)(center - rawmin));
497
return MAX(result, INPUT_ABSOLUTE_MIN);
503
//============================================================
505
//============================================================
507
void wininput_init(running_machine &machine)
509
// we need pause and exit callbacks
510
machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(wininput_pause), &machine));
511
machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(wininput_resume), &machine));
512
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(wininput_exit), &machine));
514
// allocate a lock for input synchronizations, since messages sometimes come from another thread
515
input_lock = osd_lock_alloc();
516
assert_always(input_lock != NULL, "Failed to allocate input_lock");
518
// decode the options
519
lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun();
521
// initialize RawInput and DirectInput (RawInput first so we can fall back)
522
rawinput_init(machine);
523
dinput_init(machine);
526
// poll once to get the initial states
527
input_enabled = TRUE;
528
wininput_poll(machine);
532
//============================================================
534
//============================================================
536
static void wininput_pause(running_machine &machine)
538
// keep track of the paused state
542
static void wininput_resume(running_machine &machine)
544
// keep track of the paused state
545
input_paused = false;
549
//============================================================
551
//============================================================
553
static void wininput_exit(running_machine &machine)
555
// acquire the lock and turn off input (this ensures everyone is done)
556
osd_lock_acquire(input_lock);
557
input_enabled = FALSE;
558
osd_lock_release(input_lock);
561
osd_lock_free(input_lock);
565
//============================================================
567
//============================================================
569
void wininput_poll(running_machine &machine)
571
int hasfocus = winwindow_has_focus() && input_enabled;
573
// ignore if not enabled
576
// remember when this happened
577
last_poll = GetTickCount();
579
// periodically process events, in case they're not coming through
580
// this also will make sure the mouse state is up-to-date
581
winwindow_process_events_periodic(machine);
583
// track if mouse/lightgun is enabled, for mouse hiding purposes
584
mouse_enabled = machine.input().device_class(DEVICE_CLASS_MOUSE).enabled();
585
lightgun_enabled = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).enabled();
588
// poll all of the devices
591
device_list_poll_devices(keyboard_list);
592
device_list_poll_devices(mouse_list);
593
device_list_poll_devices(lightgun_list);
594
device_list_poll_devices(joystick_list);
598
device_list_reset_devices(keyboard_list);
599
device_list_reset_devices(mouse_list);
600
device_list_reset_devices(lightgun_list);
601
device_list_reset_devices(joystick_list);
606
//============================================================
607
// wininput_should_hide_mouse
608
//============================================================
610
int wininput_should_hide_mouse(void)
612
// if we are paused or disabled, no
613
if (input_paused || !input_enabled)
616
// if neither mice nor lightguns enabled in the core, then no
617
if (!mouse_enabled && !lightgun_enabled)
620
// if the window has a menu, no
621
if (win_window_list != NULL && win_has_menu(win_window_list))
629
//============================================================
630
// wininput_handle_mouse_button
631
//============================================================
633
BOOL wininput_handle_mouse_button(int button, int down, int x, int y)
635
device_info *devinfo;
637
// ignore if not enabled
641
// only need this for shared axis hack
642
if (!lightgun_shared_axis_mode || button >= 4)
645
// choose a device based on the button
646
devinfo = lightgun_list;
647
if (button >= 2 && devinfo != NULL)
650
devinfo = devinfo->next;
654
osd_lock_acquire(input_lock);
656
// set the button state
657
devinfo->mouse.state.rgbButtons[button] = down ? 0x80 : 0x00;
663
// get the position relative to the window
664
GetClientRect(win_window_list->hwnd, &client_rect);
667
ScreenToClient(win_window_list->hwnd, &mousepos);
669
// convert to absolute coordinates
670
devinfo->mouse.state.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
671
devinfo->mouse.state.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
675
osd_lock_release(input_lock);
680
//============================================================
681
// wininput_handle_raw
682
//============================================================
684
BOOL wininput_handle_raw(HANDLE device)
686
BYTE small_buffer[4096];
687
LPBYTE data = small_buffer;
691
// ignore if not enabled
695
// determine the size of databuffer we need
696
if ((*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) != 0)
699
// if necessary, allocate a temporary buffer and fetch the data
700
if (size > sizeof(small_buffer))
702
data = global_alloc_array(BYTE, size);
707
// fetch the data and process the appropriate message types
708
result = (*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
711
RAWINPUT *input = (RAWINPUT *)data;
713
// handle keyboard input
714
if (input->header.dwType == RIM_TYPEKEYBOARD)
716
osd_lock_acquire(input_lock);
717
rawinput_keyboard_update(input->header.hDevice, &input->data.keyboard);
718
osd_lock_release(input_lock);
722
// handle mouse input
723
else if (input->header.dwType == RIM_TYPEMOUSE)
725
osd_lock_acquire(input_lock);
726
rawinput_mouse_update(input->header.hDevice, &input->data.mouse);
727
osd_lock_release(input_lock);
732
// free the temporary buffer and return the result
733
if (data != small_buffer)
739
//============================================================
740
// wininput_vkey_for_mame_code
741
//============================================================
743
int wininput_vkey_for_mame_code(input_code code)
745
// only works for keyboard switches
746
if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.item_class() == ITEM_CLASS_SWITCH)
748
input_item_id id = code.item_id();
751
// scan the table for a match
752
for (tablenum = 0; tablenum < ARRAY_LENGTH(win_key_trans_table); tablenum++)
753
if (win_key_trans_table[tablenum][MAME_KEY] == id)
754
return win_key_trans_table[tablenum][VIRTUAL_KEY];
760
//============================================================
761
// customize_input_type_list
762
//============================================================
764
void windows_osd_interface::customize_input_type_list(simple_list<input_type_entry> &typelist)
766
input_type_entry *entry;
768
// loop over the defaults
769
for (entry = typelist.first(); entry != NULL; entry = entry->next())
772
// disable the config menu if the ALT key is down
773
// (allows ALT-TAB to switch between windows apps)
774
case IPT_UI_CONFIGURE:
775
entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_TAB, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT);
778
// alt-enter for fullscreen
780
entry->token = "TOGGLE_FULLSCREEN";
781
entry->name = "Toggle Fullscreen";
782
entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_ENTER);
785
// alt-F12 for fullscreen snap
787
entry->token = "RENDER_SNAP";
788
entry->name = "Take Rendered Snapshot";
789
entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_F12);
792
// alt-F11 for fullscreen video
794
entry->token = "RENDER_AVI";
795
entry->name = "Record Rendered Video";
796
entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_F11);
802
//============================================================
803
// device_list_poll_devices
804
//============================================================
806
static void device_list_poll_devices(device_info *devlist_head)
810
for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
811
if (curdev->poll != NULL)
812
(*curdev->poll)(curdev);
816
//============================================================
817
// device_list_reset_devices
818
//============================================================
820
static void device_list_reset_devices(device_info *devlist_head)
824
for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
825
generic_device_reset(curdev);
829
//============================================================
830
// generic_device_alloc
831
//============================================================
833
static device_info *generic_device_alloc(running_machine &machine, device_info **devlist_head_ptr, const TCHAR *name)
835
device_info **curdev_ptr;
836
device_info *devinfo;
838
// allocate memory for the device object
839
devinfo = global_alloc_clear(device_info(machine));
840
devinfo->head = devlist_head_ptr;
842
// allocate a UTF8 copy of the name
843
devinfo->name = utf8_from_tstring(name);
844
if (devinfo->name == NULL)
847
// append us to the list
848
for (curdev_ptr = devinfo->head; *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
849
*curdev_ptr = devinfo;
854
global_free(devinfo);
859
//============================================================
860
// generic_device_free
861
//============================================================
863
static void generic_device_free(device_info *devinfo)
865
device_info **curdev_ptr;
867
// remove us from the list
868
for (curdev_ptr = devinfo->head; *curdev_ptr != devinfo && *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
869
if (*curdev_ptr == devinfo)
870
*curdev_ptr = devinfo->next;
872
// free the copy of the name if present
873
if (devinfo->name != NULL)
874
osd_free((void *)devinfo->name);
875
devinfo->name = NULL;
877
// and now free the info
878
global_free(devinfo);
882
//============================================================
883
// generic_device_index
884
//============================================================
886
static int generic_device_index(device_info *devlist_head, device_info *devinfo)
889
while (devlist_head != NULL)
891
if (devlist_head == devinfo)
894
devlist_head = devlist_head->next;
900
//============================================================
901
// generic_device_reset
902
//============================================================
904
static void generic_device_reset(device_info *devinfo)
907
if (devinfo->head == &keyboard_list)
908
memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
910
// mouse/lightgun case
911
else if (devinfo->head == &mouse_list || devinfo->head == &lightgun_list)
912
memset(&devinfo->mouse.state, 0, sizeof(devinfo->mouse.state));
915
else if (devinfo->head == &joystick_list)
919
memset(&devinfo->joystick.state, 0, sizeof(devinfo->joystick.state));
920
for (povnum = 0; povnum < ARRAY_LENGTH(devinfo->joystick.state.rgdwPOV); povnum++)
921
devinfo->joystick.state.rgdwPOV[povnum] = 0xffff;
926
//============================================================
927
// generic_button_get_state
928
//============================================================
930
static INT32 generic_button_get_state(void *device_internal, void *item_internal)
932
device_info *devinfo = (device_info *)device_internal;
933
BYTE *itemdata = (BYTE *)item_internal;
935
// return the current state
936
poll_if_necessary(devinfo->machine());
937
return *itemdata >> 7;
941
//============================================================
942
// generic_axis_get_state
943
//============================================================
945
static INT32 generic_axis_get_state(void *device_internal, void *item_internal)
947
device_info *devinfo = (device_info *)device_internal;
948
LONG *axisdata = (LONG *)item_internal;
950
// return the current state
951
poll_if_necessary(devinfo->machine());
956
//============================================================
958
//============================================================
960
static void win32_init(running_machine &machine)
964
// we don't need any initialization unless we are using shared axis mode for lightguns
965
if (!lightgun_shared_axis_mode)
968
// we need an exit callback
969
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(win32_exit), &machine));
971
// allocate two lightgun devices
972
for (gunnum = 0; gunnum < 2; gunnum++)
974
static const TCHAR *const gun_names[] = { TEXT("Shared Axis Gun 1"), TEXT("Shared Axis Gun 2") };
975
device_info *devinfo;
979
devinfo = generic_device_alloc(machine, &lightgun_list, gun_names[gunnum]);
984
devinfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(devinfo->name, devinfo);
987
for (axisnum = 0; axisnum < 2; axisnum++)
989
char *name = utf8_from_tstring(default_axis_name[axisnum]);
990
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
994
// populate the buttons
995
for (butnum = 0; butnum < 2; butnum++)
997
char *name = utf8_from_tstring(default_button_name(butnum));
998
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
1005
//============================================================
1007
//============================================================
1009
static void win32_exit(running_machine &machine)
1011
// skip if we're in shared axis mode
1012
if (!lightgun_shared_axis_mode)
1015
// delete the lightgun devices
1016
while (lightgun_list != NULL)
1017
generic_device_free(lightgun_list);
1021
//============================================================
1022
// win32_keyboard_poll
1023
//============================================================
1025
static void win32_keyboard_poll(device_info *devinfo)
1029
// clear the flag that says we detected a key down via win32
1030
keyboard_win32_reported_key_down = FALSE;
1032
// reset the keyboard state and then repopulate
1033
memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
1035
// iterate over keys
1036
for (keynum = 0; keynum < ARRAY_LENGTH(win_key_trans_table); keynum++)
1038
int vk = win_key_trans_table[keynum][VIRTUAL_KEY];
1039
if (vk != 0 && (GetAsyncKeyState(vk) & 0x8000) != 0)
1041
int dik = win_key_trans_table[keynum][DI_KEY];
1043
// conver the VK code to a scancode (DIK code)
1045
devinfo->keyboard.state[dik] = 0x80;
1047
// set this flag so that we continue to use win32 until all keys are up
1048
keyboard_win32_reported_key_down = TRUE;
1054
//============================================================
1055
// win32_lightgun_poll
1056
//============================================================
1058
static void win32_lightgun_poll(device_info *devinfo)
1060
INT32 xpos = 0, ypos = 0;
1063
// if we are using the shared axis hack, the data is updated via Windows messages only
1064
if (lightgun_shared_axis_mode)
1067
// get the cursor position and transform into final results
1068
GetCursorPos(&mousepos);
1069
if (win_window_list != NULL)
1073
// get the position relative to the window
1074
GetClientRect(win_window_list->hwnd, &client_rect);
1075
ScreenToClient(win_window_list->hwnd, &mousepos);
1077
// convert to absolute coordinates
1078
xpos = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
1079
ypos = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
1082
// update the X/Y positions
1083
devinfo->mouse.state.lX = xpos;
1084
devinfo->mouse.state.lY = ypos;
1088
//============================================================
1090
//============================================================
1092
static void dinput_init(running_machine &machine)
1095
#if DIRECTINPUT_VERSION >= 0x800
1096
int didevtype_keyboard = DI8DEVCLASS_KEYBOARD;
1097
int didevtype_mouse = DI8DEVCLASS_POINTER;
1098
int didevtype_joystick = DI8DEVCLASS_GAMECTRL;
1100
dinput_version = DIRECTINPUT_VERSION;
1101
result = DirectInput8Create(GetModuleHandle(NULL), dinput_version, IID_IDirectInput8, (void **)&dinput, NULL);
1102
if (result != DI_OK)
1108
int didevtype_keyboard = DIDEVTYPE_KEYBOARD;
1109
int didevtype_mouse = DIDEVTYPE_MOUSE;
1110
int didevtype_joystick = DIDEVTYPE_JOYSTICK;
1112
// first attempt to initialize DirectInput at the current version
1113
dinput_version = DIRECTINPUT_VERSION;
1114
result = DirectInputCreate(GetModuleHandle(NULL), dinput_version, &dinput, NULL);
1115
if (result != DI_OK)
1117
// if that fails, try version 5
1118
dinput_version = 0x0500;
1119
result = DirectInputCreate(GetModuleHandle(NULL), dinput_version, &dinput, NULL);
1120
if (result != DI_OK)
1122
// if that fails, try version 3
1123
dinput_version = 0x0300;
1124
result = DirectInputCreate(GetModuleHandle(NULL), dinput_version, &dinput, NULL);
1125
if (result != DI_OK)
1134
mame_printf_verbose("DirectInput: Using DirectInput %d\n", dinput_version >> 8);
1136
// we need an exit callback
1137
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(dinput_exit), &machine));
1139
// initialize keyboard devices, but only if we don't have any yet
1140
if (keyboard_list == NULL)
1142
// enumerate the ones we have
1143
result = IDirectInput_EnumDevices(dinput, didevtype_keyboard, dinput_keyboard_enum, &machine, DIEDFL_ATTACHEDONLY);
1144
if (result != DI_OK)
1145
fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", (UINT32)result);
1148
// initialize mouse & lightgun devices, but only if we don't have any yet
1149
if (mouse_list == NULL)
1151
// enumerate the ones we have
1152
result = IDirectInput_EnumDevices(dinput, didevtype_mouse, dinput_mouse_enum, &machine, DIEDFL_ATTACHEDONLY);
1153
if (result != DI_OK)
1154
fatalerror("DirectInput: Unable to enumerate mice (result=%08X)\n", (UINT32)result);
1157
// initialize joystick devices
1158
result = IDirectInput_EnumDevices(dinput, didevtype_joystick, dinput_joystick_enum, &machine, DIEDFL_ATTACHEDONLY);
1159
if (result != DI_OK)
1160
fatalerror("DirectInput: Unable to enumerate joysticks (result=%08X)\n", (UINT32)result);
1164
//============================================================
1166
//============================================================
1168
static void dinput_exit(running_machine &machine)
1170
// release all our devices
1171
while (joystick_list != NULL && joystick_list->dinput.device != NULL)
1172
dinput_device_release(joystick_list);
1173
while (lightgun_list != NULL)
1174
generic_device_free(lightgun_list);
1175
while (mouse_list != NULL && mouse_list->dinput.device != NULL)
1176
dinput_device_release(mouse_list);
1177
while (keyboard_list != NULL && keyboard_list->dinput.device != NULL)
1178
dinput_device_release(keyboard_list);
1180
// release DirectInput
1182
IDirectInput_Release(dinput);
1187
//============================================================
1188
// dinput_set_dword_property
1189
//============================================================
1191
static HRESULT dinput_set_dword_property(LPDIRECTINPUTDEVICE device, REFGUID property_guid, DWORD object, DWORD how, DWORD value)
1195
dipdw.diph.dwSize = sizeof(dipdw);
1196
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
1197
dipdw.diph.dwObj = object;
1198
dipdw.diph.dwHow = how;
1199
dipdw.dwData = value;
1201
return IDirectInputDevice_SetProperty(device, property_guid, &dipdw.diph);
1205
//============================================================
1206
// dinput_device_create
1207
//============================================================
1209
static device_info *dinput_device_create(running_machine &machine, device_info **devlist_head_ptr, LPCDIDEVICEINSTANCE instance, LPCDIDATAFORMAT format1, LPCDIDATAFORMAT format2, DWORD cooperative_level)
1211
device_info *devinfo;
1214
// allocate memory for the device object
1215
devinfo = generic_device_alloc(machine, devlist_head_ptr, instance->tszInstanceName);
1217
// attempt to create a device
1218
result = IDirectInput_CreateDevice(dinput, WRAP_REFIID(instance->guidInstance), &devinfo->dinput.device, NULL);
1219
if (result != DI_OK)
1222
// try to get a version 2 device for it
1223
result = IDirectInputDevice_QueryInterface(devinfo->dinput.device, WRAP_REFIID(IID_IDirectInputDevice2), (void **)&devinfo->dinput.device2);
1224
if (result != DI_OK)
1225
devinfo->dinput.device2 = NULL;
1228
devinfo->dinput.caps.dwSize = STRUCTSIZE(DIDEVCAPS);
1229
result = IDirectInputDevice_GetCapabilities(devinfo->dinput.device, &devinfo->dinput.caps);
1230
if (result != DI_OK)
1233
// attempt to set the data format
1234
devinfo->dinput.format = format1;
1235
result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device, devinfo->dinput.format);
1236
if (result != DI_OK)
1238
// use the secondary format if available
1239
if (format2 != NULL)
1241
devinfo->dinput.format = format2;
1242
result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device, devinfo->dinput.format);
1244
if (result != DI_OK)
1248
// set the cooperative level
1249
result = IDirectInputDevice_SetCooperativeLevel(devinfo->dinput.device, win_window_list->hwnd, cooperative_level);
1250
if (result != DI_OK)
1255
dinput_device_release(devinfo);
1260
//============================================================
1261
// dinput_device_release
1262
//============================================================
1264
static void dinput_device_release(device_info *devinfo)
1266
// release the version 2 device if present
1267
if (devinfo->dinput.device2 != NULL)
1268
IDirectInputDevice_Release(devinfo->dinput.device2);
1269
devinfo->dinput.device2 = NULL;
1271
// release the regular device if present
1272
if (devinfo->dinput.device != NULL)
1273
IDirectInputDevice_Release(devinfo->dinput.device);
1274
devinfo->dinput.device = NULL;
1276
// free the item list
1277
generic_device_free(devinfo);
1281
//============================================================
1282
// dinput_device_item_name
1283
//============================================================
1285
static char *dinput_device_item_name(device_info *devinfo, int offset, const TCHAR *defstring, const TCHAR *suffix)
1287
DIDEVICEOBJECTINSTANCE instance = { 0 };
1288
const TCHAR *namestring = instance.tszName;
1293
// query the key name
1294
instance.dwSize = STRUCTSIZE(DIDEVICEOBJECTINSTANCE);
1295
result = IDirectInputDevice_GetObjectInfo(devinfo->dinput.device, &instance, offset, DIPH_BYOFFSET);
1297
// if we got an error and have no default string, just return NULL
1298
if (result != DI_OK)
1300
if (defstring == NULL)
1302
namestring = defstring;
1305
// if no suffix, return as-is
1307
return utf8_from_tstring(namestring);
1309
// otherwise, allocate space to add the suffix
1310
combined = global_alloc_array(TCHAR, _tcslen(namestring) + 1 + _tcslen(suffix) + 1);
1311
_tcscpy(combined, namestring);
1312
_tcscat(combined, TEXT(" "));
1313
_tcscat(combined, suffix);
1315
// convert to UTF8, free the temporary string, and return
1316
utf8 = utf8_from_tstring(combined);
1317
global_free(combined);
1322
//============================================================
1323
// dinput_device_poll
1324
//============================================================
1326
static HRESULT dinput_device_poll(device_info *devinfo)
1330
// first poll the device, then get the state
1331
if (devinfo->dinput.device2 != NULL)
1332
IDirectInputDevice2_Poll(devinfo->dinput.device2);
1333
result = IDirectInputDevice_GetDeviceState(devinfo->dinput.device, devinfo->dinput.format->dwDataSize, &devinfo->joystick.state);
1335
// handle lost inputs here
1336
if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
1338
result = IDirectInputDevice_Acquire(devinfo->dinput.device);
1339
if (result == DI_OK)
1340
result = IDirectInputDevice_GetDeviceState(devinfo->dinput.device, devinfo->dinput.format->dwDataSize, &devinfo->joystick.state);
1347
//============================================================
1348
// dinput_keyboard_enum
1349
//============================================================
1351
static BOOL CALLBACK dinput_keyboard_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1353
running_machine &machine = *(running_machine *)ref;
1354
device_info *devinfo;
1357
// allocate and link in a new device
1358
devinfo = dinput_device_create(machine, &keyboard_list, instance, &c_dfDIKeyboard, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
1359
if (devinfo == NULL)
1363
devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
1364
devinfo->poll = dinput_keyboard_poll;
1367
for (keynum = 0; keynum < MAX_KEYS; keynum++)
1369
input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
1373
// generate/fetch the name
1374
_sntprintf(defname, ARRAY_LENGTH(defname), TEXT("Scan%03d"), keynum);
1375
name = dinput_device_item_name(devinfo, keynum, defname, NULL);
1377
// add the item to the device
1378
devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
1383
return DIENUM_CONTINUE;
1387
//============================================================
1388
// dinput_keyboard_poll
1389
//============================================================
1391
static void dinput_keyboard_poll(device_info *devinfo)
1393
HRESULT result = dinput_device_poll(devinfo);
1395
// for the first device, if we errored, or if we previously reported win32 keys,
1396
// then ignore the dinput state and poll using win32
1397
if (devinfo == keyboard_list && (result != DI_OK || keyboard_win32_reported_key_down))
1398
win32_keyboard_poll(devinfo);
1402
//============================================================
1403
// dinput_mouse_enum
1404
//============================================================
1406
static BOOL CALLBACK dinput_mouse_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1408
device_info *devinfo, *guninfo = NULL;
1409
running_machine &machine = *(running_machine *)ref;
1410
int axisnum, butnum;
1413
// allocate and link in a new device
1414
devinfo = dinput_device_create(machine, &mouse_list, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
1415
if (devinfo == NULL)
1418
// allocate a second device for the gun (unless we are using the shared axis mode)
1419
// we only support a single gun in dinput mode, so only add one
1420
if (!lightgun_shared_axis_mode && devinfo == mouse_list)
1422
guninfo = generic_device_alloc(machine, &lightgun_list, instance->tszInstanceName);
1423
if (guninfo == NULL)
1427
// set relative mode on the mouse device
1428
result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL);
1429
if (result != DI_OK)
1431
mame_printf_error("DirectInput: Unable to set relative mode for mouse %d (%s)\n", generic_device_index(mouse_list, devinfo), devinfo->name);
1436
devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name, devinfo);
1437
devinfo->poll = dinput_mouse_poll;
1438
if (guninfo != NULL)
1440
guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
1441
guninfo->poll = win32_lightgun_poll;
1444
// cap the number of axes and buttons based on the format
1445
devinfo->dinput.caps.dwAxes = MIN(devinfo->dinput.caps.dwAxes, 3);
1446
devinfo->dinput.caps.dwButtons = MIN(devinfo->dinput.caps.dwButtons, (devinfo->dinput.format == &c_dfDIMouse) ? 4 : 8);
1448
// populate the axes
1449
for (axisnum = 0; axisnum < devinfo->dinput.caps.dwAxes; axisnum++)
1451
char *name = dinput_device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
1453
// add to the mouse device and optionally to the gun device as well
1454
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
1455
if (guninfo != NULL && axisnum < 2)
1456
guninfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &guninfo->mouse.state.lX + axisnum);
1461
// populate the buttons
1462
for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
1464
FPTR offset = (FPTR)(&((DIMOUSESTATE *)NULL)->rgbButtons[butnum]);
1465
char *name = dinput_device_item_name(devinfo, offset, default_button_name(butnum), NULL);
1467
// add to the mouse device and optionally to the gun device as well
1468
// note that the gun device points to the mouse buttons rather than its own
1469
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
1470
if (guninfo != NULL)
1471
guninfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
1477
return DIENUM_CONTINUE;
1480
if (guninfo != NULL)
1481
generic_device_free(guninfo);
1482
if (devinfo != NULL)
1483
dinput_device_release(devinfo);
1488
//============================================================
1489
// dinput_mouse_poll
1490
//============================================================
1492
static void dinput_mouse_poll(device_info *devinfo)
1495
dinput_device_poll(devinfo);
1497
// scale the axis data
1498
devinfo->mouse.state.lX *= INPUT_RELATIVE_PER_PIXEL;
1499
devinfo->mouse.state.lY *= INPUT_RELATIVE_PER_PIXEL;
1500
devinfo->mouse.state.lZ *= INPUT_RELATIVE_PER_PIXEL;
1504
//============================================================
1505
// dinput_joystick_enum
1506
//============================================================
1508
static BOOL CALLBACK dinput_joystick_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1510
DWORD cooperative_level = DISCL_FOREGROUND | DISCL_EXCLUSIVE;
1511
int axisnum, axiscount, povnum, butnum;
1512
running_machine &machine = *(running_machine *)ref;
1513
device_info *devinfo;
1516
if (win_window_list != NULL && win_has_menu(win_window_list)) {
1517
cooperative_level = DISCL_BACKGROUND | DISCL_EXCLUSIVE;
1519
// allocate and link in a new device
1520
devinfo = dinput_device_create(machine, &joystick_list, instance, &c_dfDIJoystick, NULL, cooperative_level);
1521
if (devinfo == NULL)
1524
// set absolute mode
1525
result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS);
1526
if (result != DI_OK)
1527
mame_printf_warning("DirectInput: Unable to set absolute mode for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
1529
// turn off deadzone; we do our own calculations
1530
result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0);
1531
if (result != DI_OK)
1532
mame_printf_warning("DirectInput: Unable to reset deadzone for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
1534
// turn off saturation; we do our own calculations
1535
result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000);
1536
if (result != DI_OK)
1537
mame_printf_warning("DirectInput: Unable to reset saturation for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
1539
// cap the number of axes, POVs, and buttons based on the format
1540
devinfo->dinput.caps.dwAxes = MIN(devinfo->dinput.caps.dwAxes, 8);
1541
devinfo->dinput.caps.dwPOVs = MIN(devinfo->dinput.caps.dwPOVs, 4);
1542
devinfo->dinput.caps.dwButtons = MIN(devinfo->dinput.caps.dwButtons, 128);
1545
devinfo->device = machine.input().device_class(DEVICE_CLASS_JOYSTICK).add_device(devinfo->name, devinfo);
1546
devinfo->poll = dinput_joystick_poll;
1548
// populate the axes
1549
for (axisnum = axiscount = 0; axiscount < devinfo->dinput.caps.dwAxes && axisnum < 8; axisnum++)
1554
// fetch the range of this axis
1555
dipr.diph.dwSize = sizeof(dipr);
1556
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
1557
dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG);
1558
dipr.diph.dwHow = DIPH_BYOFFSET;
1559
result = IDirectInputDevice_GetProperty(devinfo->dinput.device, DIPROP_RANGE, &dipr.diph);
1560
if (result != DI_OK)
1562
devinfo->joystick.rangemin[axisnum] = dipr.lMin;
1563
devinfo->joystick.rangemax[axisnum] = dipr.lMax;
1565
// populate the item description as well
1566
name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
1567
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->joystick.state.lX + axisnum);
1573
// populate the POVs
1574
for (povnum = 0; povnum < devinfo->dinput.caps.dwPOVs; povnum++)
1579
name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("L"));
1580
devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_LEFT));
1584
name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("R"));
1585
devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_RIGHT));
1589
name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("U"));
1590
devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_UP));
1594
name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("D"));
1595
devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_DOWN));
1599
// populate the buttons
1600
for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
1602
FPTR offset = (FPTR)(&((DIJOYSTATE2 *)NULL)->rgbButtons[butnum]);
1603
char *name = dinput_device_item_name(devinfo, offset, default_button_name(butnum), NULL);
1604
devinfo->device->add_item(name, (butnum < 16) ? (input_item_id)(ITEM_ID_BUTTON1 + butnum) : ITEM_ID_OTHER_SWITCH, generic_button_get_state, &devinfo->joystick.state.rgbButtons[butnum]);
1609
return DIENUM_CONTINUE;
1613
//============================================================
1614
// dinput_joystick_poll
1615
//============================================================
1617
static void dinput_joystick_poll(device_info *devinfo)
1621
// poll the device first
1622
dinput_device_poll(devinfo);
1624
// normalize axis values
1625
for (axisnum = 0; axisnum < 8; axisnum++)
1627
LONG *axis = (&devinfo->joystick.state.lX) + axisnum;
1628
*axis = normalize_absolute_axis(*axis, devinfo->joystick.rangemin[axisnum], devinfo->joystick.rangemax[axisnum]);
1633
//============================================================
1634
// dinput_joystick_pov_get_state
1635
//============================================================
1637
static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
1639
device_info *devinfo = (device_info *)device_internal;
1640
int povnum = (FPTR)item_internal / 4;
1641
int povdir = (FPTR)item_internal % 4;
1645
// get the current state
1646
poll_if_necessary(devinfo->machine());
1647
pov = devinfo->joystick.state.rgdwPOV[povnum];
1649
// if invalid, return 0
1650
if ((pov & 0xffff) == 0xffff)
1653
// return the current state
1656
case POVDIR_LEFT: result = (pov >= 22500 && pov <= 31500); break;
1657
case POVDIR_RIGHT: result = (pov >= 4500 && pov <= 13500); break;
1658
case POVDIR_UP: result = (pov >= 31500 || pov <= 4500); break;
1659
case POVDIR_DOWN: result = (pov >= 13500 && pov <= 22500); break;
1665
//============================================================
1667
//============================================================
1669
static void rawinput_init(running_machine &machine)
1671
RAWINPUTDEVICELIST *devlist = NULL;
1672
int device_count, devnum, regcount;
1673
RAWINPUTDEVICE reglist[2];
1676
// we need pause and exit callbacks
1677
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(rawinput_exit), &machine));
1679
// look in user32 for the raw input APIs
1680
user32 = LoadLibrary(TEXT("user32.dll"));
1684
// look up the entry points
1685
register_rawinput_devices = (register_rawinput_devices_ptr)GetProcAddress(user32, "RegisterRawInputDevices");
1686
get_rawinput_device_list = (get_rawinput_device_list_ptr)GetProcAddress(user32, "GetRawInputDeviceList");
1687
get_rawinput_device_info = (get_rawinput_device_info_ptr)GetProcAddress(user32, "GetRawInputDeviceInfo" UNICODE_SUFFIX);
1688
get_rawinput_data = (get_rawinput_data_ptr)GetProcAddress(user32, "GetRawInputData");
1689
if (register_rawinput_devices == NULL || get_rawinput_device_list == NULL || get_rawinput_device_info == NULL || get_rawinput_data == NULL)
1691
mame_printf_verbose("RawInput: APIs detected\n");
1693
// get the number of devices, allocate a device list, and fetch it
1694
if ((*get_rawinput_device_list)(NULL, &device_count, sizeof(*devlist)) != 0)
1696
if (device_count == 0)
1698
devlist = global_alloc_array(RAWINPUTDEVICELIST, device_count);
1699
if ((*get_rawinput_device_list)(devlist, &device_count, sizeof(*devlist)) == -1)
1702
// iterate backwards through devices; new devices are added at the head
1703
for (devnum = device_count - 1; devnum >= 0; devnum--)
1705
RAWINPUTDEVICELIST *device = &devlist[devnum];
1708
if (device->dwType == RIM_TYPEKEYBOARD && !FORCE_DIRECTINPUT)
1709
rawinput_keyboard_enum(machine, device);
1712
else if (device->dwType == RIM_TYPEMOUSE && !FORCE_DIRECTINPUT)
1713
rawinput_mouse_enum(machine, device);
1716
// finally, register to receive raw input WM_INPUT messages
1718
if (keyboard_list != NULL)
1720
reglist[regcount].usUsagePage = 0x01;
1721
reglist[regcount].usUsage = 0x06;
1722
reglist[regcount].dwFlags = RIDEV_INPUTSINK;
1723
reglist[regcount].hwndTarget = win_window_list->hwnd;
1726
if (mouse_list != NULL)
1728
reglist[regcount].usUsagePage = 0x01;
1729
reglist[regcount].usUsage = 0x02;
1730
reglist[regcount].dwFlags = 0;
1731
reglist[regcount].hwndTarget = win_window_list->hwnd;
1735
// if the registration fails, we need to back off
1737
if (!(*register_rawinput_devices)(reglist, regcount, sizeof(reglist[0])))
1740
global_free(devlist);
1744
if (devlist != NULL)
1745
global_free(devlist);
1749
//============================================================
1751
//============================================================
1753
static void rawinput_exit(running_machine &machine)
1755
// release all our devices
1756
while (lightgun_list != NULL && lightgun_list->rawinput.device != NULL)
1757
rawinput_device_release(lightgun_list);
1758
while (mouse_list != NULL && mouse_list->rawinput.device != NULL)
1759
rawinput_device_release(mouse_list);
1760
while (keyboard_list != NULL && keyboard_list->rawinput.device != NULL)
1761
rawinput_device_release(keyboard_list);
1765
//============================================================
1766
// rawinput_device_create
1767
//============================================================
1769
static device_info *rawinput_device_create(running_machine &machine, device_info **devlist_head_ptr, PRAWINPUTDEVICELIST device)
1771
device_info *devinfo = NULL;
1772
TCHAR *tname = NULL;
1775
// determine the length of the device name, allocate it, and fetch it
1776
if ((*get_rawinput_device_info)(device->hDevice, RIDI_DEVICENAME, NULL, &name_length) != 0)
1778
tname = global_alloc_array(TCHAR, name_length);
1779
if ((*get_rawinput_device_info)(device->hDevice, RIDI_DEVICENAME, tname, &name_length) == -1)
1782
// if this is an RDP name, skip it
1783
if (_tcsstr(tname, TEXT("Root#RDP_")) != NULL)
1786
// improve the name and then allocate a device
1787
tname = rawinput_device_improve_name(tname);
1788
devinfo = generic_device_alloc(machine, devlist_head_ptr, tname);
1792
devinfo->rawinput.device = device->hDevice;
1798
if (devinfo != NULL)
1799
rawinput_device_release(devinfo);
1804
//============================================================
1805
// rawinput_device_release
1806
//============================================================
1808
static void rawinput_device_release(device_info *devinfo)
1810
// free the item list
1811
generic_device_free(devinfo);
1815
//============================================================
1816
// rawinput_device_improve_name
1817
//============================================================
1819
static TCHAR *rawinput_device_improve_name(TCHAR *name)
1821
static const TCHAR usbbasepath[] = TEXT("SYSTEM\\CurrentControlSet\\Enum\\USB");
1822
static const TCHAR basepath[] = TEXT("SYSTEM\\CurrentControlSet\\Enum\\");
1823
TCHAR *regstring = NULL;
1824
TCHAR *parentid = NULL;
1825
TCHAR *regpath = NULL;
1832
// The RAW name received is formatted as:
1833
// \??\type-id#hardware-id#instance-id#{DeviceClasses-id}
1834
// XP starts with "\??\"
1835
// Vista64 starts with "\\?\"
1837
// ensure the name is something we can handle
1838
if (_tcsncmp(name, TEXT("\\\\?\\"), 4) != 0 && _tcsncmp(name, TEXT("\\??\\"), 4) != 0)
1841
// allocate a temporary string and concatenate the base path plus the name
1842
regpath = global_alloc_array(TCHAR, _tcslen(basepath) + 1 + _tcslen(name));
1843
_tcscpy(regpath, basepath);
1844
chdst = regpath + _tcslen(regpath);
1846
// convert all # to \ in the name
1847
for (chsrc = name + 4; *chsrc != 0; chsrc++)
1848
*chdst++ = (*chsrc == '#') ? '\\' : *chsrc;
1851
// remove the final chunk
1852
chdst = _tcsrchr(regpath, '\\');
1857
// now try to open the registry key
1858
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, ®key);
1859
if (result != ERROR_SUCCESS)
1862
// fetch the device description; if it exists, we are finished
1863
regstring = reg_query_string(regkey, TEXT("DeviceDesc"));
1864
if (regstring != NULL)
1868
RegCloseKey(regkey);
1871
// if the key name does not contain "HID", it's not going to be in the USB tree; give up
1872
if (_tcsstr(regpath, TEXT("HID")) == NULL)
1875
// extract the expected parent ID from the regpath
1876
parentid = _tcsrchr(regpath, '\\');
1877
if (parentid == NULL)
1882
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, usbbasepath, 0, KEY_READ, ®key);
1883
if (result != ERROR_SUCCESS)
1886
// enumerate the USB key
1887
for (usbindex = 0; result == ERROR_SUCCESS && regstring == NULL; usbindex++)
1889
TCHAR keyname[MAX_PATH];
1892
// get the next enumerated subkey and scan it
1893
namelen = ARRAY_LENGTH(keyname) - 1;
1894
result = RegEnumKeyEx(regkey, usbindex, keyname, &namelen, NULL, NULL, NULL, NULL);
1895
if (result == ERROR_SUCCESS)
1902
subresult = RegOpenKeyEx(regkey, keyname, 0, KEY_READ, &subkey);
1903
if (subresult != ERROR_SUCCESS)
1906
// enumerate the subkey
1907
for (subindex = 0; subresult == ERROR_SUCCESS && regstring == NULL; subindex++)
1909
// get the next enumerated subkey and scan it
1910
namelen = ARRAY_LENGTH(keyname) - 1;
1911
subresult = RegEnumKeyEx(subkey, subindex, keyname, &namelen, NULL, NULL, NULL, NULL);
1912
if (subresult == ERROR_SUCCESS)
1918
// open this final key
1919
endresult = RegOpenKeyEx(subkey, keyname, 0, KEY_READ, &endkey);
1920
if (endresult != ERROR_SUCCESS)
1923
// do we have a match?
1924
endparentid = reg_query_string(endkey, TEXT("ParentIdPrefix"));
1925
if (endparentid != NULL && _tcsncmp(parentid, endparentid, _tcslen(endparentid)) == 0)
1926
regstring = reg_query_string(endkey, TEXT("DeviceDesc"));
1928
// free memory and close the key
1929
if (endparentid != NULL)
1930
global_free(endparentid);
1931
RegCloseKey(endkey);
1936
RegCloseKey(subkey);
1940
// if we didn't find anything, go to the exit
1941
if (regstring == NULL)
1945
// replace the name with the nicer one
1948
// remove anything prior to the final semicolon
1949
chsrc = _tcsrchr(regstring, ';');
1954
name = global_alloc_array(TCHAR, _tcslen(chsrc) + 1);
1955
_tcscpy(name, chsrc);
1958
if (regstring != NULL)
1959
global_free(regstring);
1960
if (regpath != NULL)
1961
global_free(regpath);
1963
RegCloseKey(regkey);
1969
//============================================================
1970
// rawinput_keyboard_enum
1971
//============================================================
1973
static void rawinput_keyboard_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
1975
device_info *devinfo;
1978
// allocate and link in a new device
1979
devinfo = rawinput_device_create(machine, &keyboard_list, device);
1980
if (devinfo == NULL)
1984
devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
1987
for (keynum = 0; keynum < MAX_KEYS; keynum++)
1989
input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
1993
// generate the name
1994
if (GetKeyNameText(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, ARRAY_LENGTH(keyname)) == 0)
1995
_sntprintf(keyname, ARRAY_LENGTH(keyname), TEXT("Scan%03d"), keynum);
1996
name = utf8_from_tstring(keyname);
1998
// add the item to the device
1999
devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
2005
//============================================================
2006
// rawinput_keyboard_update
2007
//============================================================
2009
static void rawinput_keyboard_update(HANDLE device, RAWKEYBOARD *data)
2011
device_info *devinfo;
2013
// find the keyboard in the list and process
2014
for (devinfo = keyboard_list; devinfo != NULL; devinfo = devinfo->next)
2015
if (devinfo->rawinput.device == device)
2017
// determine the full DIK-compatible scancode
2018
UINT8 scancode = (data->MakeCode & 0x7f) | ((data->Flags & RI_KEY_E0) ? 0x80 : 0x00);
2020
// scancode 0xaa is a special shift code we need to ignore
2021
if (scancode == 0xaa)
2024
// set or clear the key
2025
if (!(data->Flags & RI_KEY_BREAK))
2026
devinfo->keyboard.state[scancode] = 0x80;
2028
devinfo->keyboard.state[scancode] = 0x00;
2034
//============================================================
2035
// rawinput_mouse_enum
2036
//============================================================
2038
static void rawinput_mouse_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
2040
device_info *devinfo, *guninfo = NULL;
2041
int axisnum, butnum;
2043
// allocate and link in a new mouse device
2044
devinfo = rawinput_device_create(machine, &mouse_list, device);
2045
if (devinfo == NULL)
2047
devinfo->poll = rawinput_mouse_poll;
2049
// allocate a second device for the gun (unless we are using the shared axis mode)
2050
if (!lightgun_shared_axis_mode)
2052
guninfo = rawinput_device_create(machine, &lightgun_list, device);
2053
assert(guninfo != NULL);
2057
devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name, devinfo);
2058
if (guninfo != NULL)
2060
guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
2061
guninfo->poll = NULL;
2064
// populate the axes
2065
for (axisnum = 0; axisnum < 3; axisnum++)
2067
char *name = utf8_from_tstring(default_axis_name[axisnum]);
2069
// add to the mouse device and optionally to the gun device as well
2070
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
2071
if (guninfo != NULL && axisnum < 2)
2072
guninfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &guninfo->mouse.state.lX + axisnum);
2077
// populate the buttons
2078
for (butnum = 0; butnum < 5; butnum++)
2080
char *name = utf8_from_tstring(default_button_name(butnum));
2082
// add to the mouse device and optionally to the gun device as well
2083
devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
2084
if (guninfo != NULL)
2085
guninfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &guninfo->mouse.state.rgbButtons[butnum]);
2092
//============================================================
2093
// rawinput_mouse_update
2094
//============================================================
2096
static void rawinput_mouse_update(HANDLE device, RAWMOUSE *data)
2098
device_info *devlist = (data->usFlags & MOUSE_MOVE_ABSOLUTE) ? lightgun_list : mouse_list;
2099
device_info *devinfo;
2101
// find the mouse in the list and process
2102
for (devinfo = devlist; devinfo != NULL; devinfo = devinfo->next)
2103
if (devinfo->rawinput.device == device)
2105
// if we got relative data, update it as a mouse
2106
if (!(data->usFlags & MOUSE_MOVE_ABSOLUTE))
2108
devinfo->mouse.raw_x += data->lLastX * INPUT_RELATIVE_PER_PIXEL;
2109
devinfo->mouse.raw_y += data->lLastY * INPUT_RELATIVE_PER_PIXEL;
2112
if (data->usButtonFlags & RI_MOUSE_WHEEL)
2113
devinfo->mouse.raw_z += (INT16)data->usButtonData * INPUT_RELATIVE_PER_PIXEL;
2116
// otherwise, update it as a lightgun
2119
devinfo->mouse.state.lX = normalize_absolute_axis(data->lLastX, 0, 0xffff);
2120
devinfo->mouse.state.lY = normalize_absolute_axis(data->lLastY, 0, 0xffff);
2123
// update the button states; always update the corresponding mouse buttons
2124
if (data->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) devinfo->mouse.state.rgbButtons[0] = 0x80;
2125
if (data->usButtonFlags & RI_MOUSE_BUTTON_1_UP) devinfo->mouse.state.rgbButtons[0] = 0x00;
2126
if (data->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) devinfo->mouse.state.rgbButtons[1] = 0x80;
2127
if (data->usButtonFlags & RI_MOUSE_BUTTON_2_UP) devinfo->mouse.state.rgbButtons[1] = 0x00;
2128
if (data->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) devinfo->mouse.state.rgbButtons[2] = 0x80;
2129
if (data->usButtonFlags & RI_MOUSE_BUTTON_3_UP) devinfo->mouse.state.rgbButtons[2] = 0x00;
2130
if (data->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) devinfo->mouse.state.rgbButtons[3] = 0x80;
2131
if (data->usButtonFlags & RI_MOUSE_BUTTON_4_UP) devinfo->mouse.state.rgbButtons[3] = 0x00;
2132
if (data->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) devinfo->mouse.state.rgbButtons[4] = 0x80;
2133
if (data->usButtonFlags & RI_MOUSE_BUTTON_5_UP) devinfo->mouse.state.rgbButtons[4] = 0x00;
2139
//============================================================
2140
// rawinput_mouse_poll
2141
//============================================================
2143
static void rawinput_mouse_poll(device_info *devinfo)
2145
poll_if_necessary(devinfo->machine());
2147
// copy the accumulated raw state to the actual state
2148
osd_lock_acquire(input_lock);
2149
devinfo->mouse.state.lX = devinfo->mouse.raw_x;
2150
devinfo->mouse.state.lY = devinfo->mouse.raw_y;
2151
devinfo->mouse.state.lZ = devinfo->mouse.raw_z;
2152
devinfo->mouse.raw_x = 0;
2153
devinfo->mouse.raw_y = 0;
2154
devinfo->mouse.raw_z = 0;
2155
osd_lock_release(input_lock);
2159
//============================================================
2161
//============================================================
2163
static TCHAR *reg_query_string(HKEY key, const TCHAR *path)
2169
// first query to get the length
2170
result = RegQueryValueEx(key, path, NULL, NULL, NULL, &datalen);
2171
if (result != ERROR_SUCCESS)
2174
// allocate a buffer
2175
buffer = global_alloc_array(TCHAR, datalen + sizeof(*buffer));
2176
buffer[datalen / sizeof(*buffer)] = 0;
2178
// now get the actual data
2179
result = RegQueryValueEx(key, path, NULL, NULL, (LPBYTE)buffer, &datalen);
2180
if (result == ERROR_SUCCESS)
2183
// otherwise return a NULL buffer
2184
global_free(buffer);
2189
//============================================================
2190
// default_button_name
2191
//============================================================
2193
static const TCHAR *default_button_name(int which)
2195
static TCHAR buffer[20];
2196
_sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("B%d"), which);
2201
//============================================================
2203
//============================================================
2205
static const TCHAR *default_pov_name(int which)
2207
static TCHAR buffer[20];
2208
_sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("POV%d"), which);