~ubuntu-branches/ubuntu/raring/mame/raring-proposed

« back to all changes in this revision

Viewing changes to mess/src/osd/windows/input.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//============================================================
2
 
//
3
 
//  input.c - Win32 implementation of MAME input routines
4
 
//
5
 
//============================================================
6
 
//
7
 
//  Copyright Aaron Giles
8
 
//  All rights reserved.
9
 
//
10
 
//  Redistribution and use in source and binary forms, with or
11
 
//  without modification, are permitted provided that the
12
 
//  following conditions are met:
13
 
//
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.
25
 
//
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.
39
 
//
40
 
//============================================================
41
 
 
42
 
// For testing purposes: force DirectInput
43
 
#define FORCE_DIRECTINPUT       0
44
 
 
45
 
// standard windows headers
46
 
#define WIN32_LEAN_AND_MEAN
47
 
#include <windows.h>
48
 
#include <winioctl.h>
49
 
#include <tchar.h>
50
 
 
51
 
// undef WINNT for dinput.h to prevent duplicate definition
52
 
#undef WINNT
53
 
#include <dinput.h>
54
 
#undef interface
55
 
 
56
 
// standard C headers
57
 
#include <conio.h>
58
 
#include <ctype.h>
59
 
#include <stddef.h>
60
 
 
61
 
// MAME headers
62
 
#include "osdepend.h"
63
 
#include "emu.h"
64
 
#include "ui.h"
65
 
 
66
 
// MAMEOS headers
67
 
#include "winmain.h"
68
 
#include "window.h"
69
 
#include "input.h"
70
 
#include "debugwin.h"
71
 
#include "video.h"
72
 
#include "strconv.h"
73
 
#include "config.h"
74
 
 
75
 
//============================================================
76
 
//  PARAMETERS
77
 
//============================================================
78
 
 
79
 
enum
80
 
{
81
 
        POVDIR_LEFT = 0,
82
 
        POVDIR_RIGHT,
83
 
        POVDIR_UP,
84
 
        POVDIR_DOWN
85
 
};
86
 
 
87
 
#define MAX_KEYS                        256
88
 
 
89
 
#define MAME_KEY                        0
90
 
#define DI_KEY                          1
91
 
#define VIRTUAL_KEY                     2
92
 
#define ASCII_KEY                       3
93
 
 
94
 
 
95
 
 
96
 
//============================================================
97
 
//  MACROS
98
 
//============================================================
99
 
 
100
 
#define STRUCTSIZE(x)           ((dinput_version == 0x0300) ? sizeof(x##_DX3) : sizeof(x))
101
 
 
102
 
#ifdef UNICODE
103
 
#define UNICODE_SUFFIX          "W"
104
 
#else
105
 
#define UNICODE_SUFFIX          "A"
106
 
#endif
107
 
 
108
 
 
109
 
 
110
 
//============================================================
111
 
//  TYPEDEFS
112
 
//============================================================
113
 
 
114
 
// state information for a keyboard; DirectInput state must be first element
115
 
typedef struct _keyboard_state keyboard_state;
116
 
struct _keyboard_state
117
 
{
118
 
        UINT8                                   state[MAX_KEYS];
119
 
        INT8                                    oldkey[MAX_KEYS];
120
 
        INT8                                    currkey[MAX_KEYS];
121
 
};
122
 
 
123
 
 
124
 
// state information for a mouse; DirectInput state must be first element
125
 
typedef struct _mouse_state mouse_state;
126
 
struct _mouse_state
127
 
{
128
 
        DIMOUSESTATE2                   state;
129
 
        LONG                                    raw_x, raw_y, raw_z;
130
 
};
131
 
 
132
 
 
133
 
// state information for a joystick; DirectInput state must be first element
134
 
typedef struct _joystick_state joystick_state;
135
 
struct _joystick_state
136
 
{
137
 
        DIJOYSTATE                              state;
138
 
        LONG                                    rangemin[8];
139
 
        LONG                                    rangemax[8];
140
 
};
141
 
 
142
 
 
143
 
// DirectInput-specific information about a device
144
 
typedef struct _dinput_device_info dinput_device_info;
145
 
struct _dinput_device_info
146
 
{
147
 
        LPDIRECTINPUTDEVICE             device;
148
 
        LPDIRECTINPUTDEVICE2    device2;
149
 
        DIDEVCAPS                               caps;
150
 
        LPCDIDATAFORMAT                 format;
151
 
};
152
 
 
153
 
 
154
 
// RawInput-specific information about a device
155
 
typedef struct _rawinput_device_info rawinput_device_info;
156
 
struct _rawinput_device_info
157
 
{
158
 
        HANDLE                                  device;
159
 
};
160
 
 
161
 
 
162
 
// generic device information
163
 
class device_info
164
 
{
165
 
public:
166
 
        device_info(running_machine &machine)
167
 
                : m_machine(machine) { }
168
 
 
169
 
        running_machine &machine() const { return m_machine; }
170
 
 
171
 
        // device information
172
 
        device_info **                  head;
173
 
        device_info *                   next;
174
 
        const char *                    name;
175
 
        void                                    (*poll)(device_info *info);
176
 
 
177
 
        // MAME information
178
 
        input_device *                  device;
179
 
 
180
 
        // device state
181
 
        union
182
 
        {
183
 
                keyboard_state          keyboard;
184
 
                mouse_state                     mouse;
185
 
                joystick_state          joystick;
186
 
        };
187
 
 
188
 
        // DirectInput/RawInput-specific state
189
 
        dinput_device_info              dinput;
190
 
        rawinput_device_info    rawinput;
191
 
 
192
 
private:
193
 
        running_machine &               m_machine;
194
 
};
195
 
 
196
 
 
197
 
// RawInput APIs
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);
202
 
 
203
 
 
204
 
 
205
 
//============================================================
206
 
//  LOCAL VARIABLES
207
 
//============================================================
208
 
 
209
 
// global states
210
 
static UINT8                            input_enabled;
211
 
static osd_lock *                       input_lock;
212
 
static UINT8                            input_paused;
213
 
static DWORD                            last_poll;
214
 
 
215
 
// DirectInput variables
216
 
static LPDIRECTINPUT            dinput;
217
 
static int                                      dinput_version;
218
 
 
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;
224
 
 
225
 
// keyboard states
226
 
static UINT8                            keyboard_win32_reported_key_down;
227
 
static device_info *            keyboard_list;
228
 
 
229
 
// mouse states
230
 
static UINT8                            mouse_enabled;
231
 
static device_info *            mouse_list;
232
 
 
233
 
// lightgun states
234
 
static UINT8                            lightgun_shared_axis_mode;
235
 
static UINT8                            lightgun_enabled;
236
 
static device_info *            lightgun_list;
237
 
 
238
 
// joystick states
239
 
static device_info *            joystick_list;
240
 
 
241
 
// default axis names
242
 
static const TCHAR *const default_axis_name[] =
243
 
{
244
 
        TEXT("X"), TEXT("Y"), TEXT("Z"), TEXT("RX"),
245
 
        TEXT("RY"), TEXT("RZ"), TEXT("SL1"), TEXT("SL2")
246
 
};
247
 
 
248
 
 
249
 
 
250
 
//============================================================
251
 
//  PROTOTYPES
252
 
//============================================================
253
 
 
254
 
static void wininput_pause(running_machine &machine);
255
 
static void wininput_resume(running_machine &machine);
256
 
static void wininput_exit(running_machine &machine);
257
 
 
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);
261
 
 
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);
269
 
 
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);
275
 
 
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);
291
 
 
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);
303
 
 
304
 
// misc utilities
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);
308
 
 
309
 
 
310
 
 
311
 
//============================================================
312
 
//  KEYBOARD/JOYSTICK LIST
313
 
//============================================================
314
 
 
315
 
// master keyboard translation table
316
 
static const int win_key_trans_table[][4] =
317
 
{
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 },
428
 
 
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.
436
 
 
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 },
449
 
};
450
 
 
451
 
 
452
 
//============================================================
453
 
//  INLINE FUNCTIONS
454
 
//============================================================
455
 
 
456
 
INLINE void poll_if_necessary(running_machine &machine)
457
 
{
458
 
        // make sure we poll at least once every 1/4 second
459
 
        if (GetTickCount() > last_poll + 1000 / 4)
460
 
                wininput_poll(machine);
461
 
}
462
 
 
463
 
 
464
 
INLINE input_item_id keyboard_map_scancode_to_itemid(int scancode)
465
 
{
466
 
        int tablenum;
467
 
 
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];
472
 
 
473
 
        // default to an "other" switch
474
 
        return ITEM_ID_OTHER_SWITCH;
475
 
}
476
 
 
477
 
 
478
 
INLINE INT32 normalize_absolute_axis(INT32 raw, INT32 rawmin, INT32 rawmax)
479
 
{
480
 
        INT32 center = (rawmax + rawmin) / 2;
481
 
 
482
 
        // make sure we have valid data
483
 
        if (rawmin >= rawmax)
484
 
                return raw;
485
 
 
486
 
        // above center
487
 
        if (raw >= center)
488
 
        {
489
 
                INT32 result = (INT64)(raw - center) * (INT64)INPUT_ABSOLUTE_MAX / (INT64)(rawmax - center);
490
 
                return MIN(result, INPUT_ABSOLUTE_MAX);
491
 
        }
492
 
 
493
 
        // below center
494
 
        else
495
 
        {
496
 
                INT32 result = -((INT64)(center - raw) * (INT64)-INPUT_ABSOLUTE_MIN / (INT64)(center - rawmin));
497
 
                return MAX(result, INPUT_ABSOLUTE_MIN);
498
 
        }
499
 
}
500
 
 
501
 
 
502
 
 
503
 
//============================================================
504
 
//  wininput_init
505
 
//============================================================
506
 
 
507
 
void wininput_init(running_machine &machine)
508
 
{
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));
513
 
 
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");
517
 
 
518
 
        // decode the options
519
 
        lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun();
520
 
 
521
 
        // initialize RawInput and DirectInput (RawInput first so we can fall back)
522
 
        rawinput_init(machine);
523
 
        dinput_init(machine);
524
 
        win32_init(machine);
525
 
 
526
 
        // poll once to get the initial states
527
 
        input_enabled = TRUE;
528
 
        wininput_poll(machine);
529
 
}
530
 
 
531
 
 
532
 
//============================================================
533
 
//  wininput_pause
534
 
//============================================================
535
 
 
536
 
static void wininput_pause(running_machine &machine)
537
 
{
538
 
        // keep track of the paused state
539
 
        input_paused = true;
540
 
}
541
 
 
542
 
static void wininput_resume(running_machine &machine)
543
 
{
544
 
        // keep track of the paused state
545
 
        input_paused = false;
546
 
}
547
 
 
548
 
 
549
 
//============================================================
550
 
//  wininput_exit
551
 
//============================================================
552
 
 
553
 
static void wininput_exit(running_machine &machine)
554
 
{
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);
559
 
 
560
 
        // free the lock
561
 
        osd_lock_free(input_lock);
562
 
}
563
 
 
564
 
 
565
 
//============================================================
566
 
//  wininput_poll
567
 
//============================================================
568
 
 
569
 
void wininput_poll(running_machine &machine)
570
 
{
571
 
        int hasfocus = winwindow_has_focus() && input_enabled;
572
 
 
573
 
        // ignore if not enabled
574
 
        if (input_enabled)
575
 
        {
576
 
                // remember when this happened
577
 
                last_poll = GetTickCount();
578
 
 
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);
582
 
 
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();
586
 
        }
587
 
 
588
 
        // poll all of the devices
589
 
        if (hasfocus)
590
 
        {
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);
595
 
        }
596
 
        else
597
 
        {
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);
602
 
        }
603
 
}
604
 
 
605
 
 
606
 
//============================================================
607
 
//  wininput_should_hide_mouse
608
 
//============================================================
609
 
 
610
 
int wininput_should_hide_mouse(void)
611
 
{
612
 
        // if we are paused or disabled, no
613
 
        if (input_paused || !input_enabled)
614
 
                return FALSE;
615
 
 
616
 
        // if neither mice nor lightguns enabled in the core, then no
617
 
        if (!mouse_enabled && !lightgun_enabled)
618
 
                return FALSE;
619
 
 
620
 
        // if the window has a menu, no
621
 
        if (win_window_list != NULL && win_has_menu(win_window_list))
622
 
                return FALSE;
623
 
 
624
 
        // otherwise, yes
625
 
        return TRUE;
626
 
}
627
 
 
628
 
 
629
 
//============================================================
630
 
//  wininput_handle_mouse_button
631
 
//============================================================
632
 
 
633
 
BOOL wininput_handle_mouse_button(int button, int down, int x, int y)
634
 
{
635
 
        device_info *devinfo;
636
 
 
637
 
        // ignore if not enabled
638
 
        if (!input_enabled)
639
 
                return FALSE;
640
 
 
641
 
        // only need this for shared axis hack
642
 
        if (!lightgun_shared_axis_mode || button >= 4)
643
 
                return FALSE;
644
 
 
645
 
        // choose a device based on the button
646
 
        devinfo = lightgun_list;
647
 
        if (button >= 2 && devinfo != NULL)
648
 
        {
649
 
                button -= 2;
650
 
                devinfo = devinfo->next;
651
 
        }
652
 
 
653
 
        // take the lock
654
 
        osd_lock_acquire(input_lock);
655
 
 
656
 
        // set the button state
657
 
        devinfo->mouse.state.rgbButtons[button] = down ? 0x80 : 0x00;
658
 
        if (down)
659
 
        {
660
 
                RECT client_rect;
661
 
                POINT mousepos;
662
 
 
663
 
                // get the position relative to the window
664
 
                GetClientRect(win_window_list->hwnd, &client_rect);
665
 
                mousepos.x = x;
666
 
                mousepos.y = y;
667
 
                ScreenToClient(win_window_list->hwnd, &mousepos);
668
 
 
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);
672
 
        }
673
 
 
674
 
        // release the lock
675
 
        osd_lock_release(input_lock);
676
 
        return TRUE;
677
 
}
678
 
 
679
 
 
680
 
//============================================================
681
 
//  wininput_handle_raw
682
 
//============================================================
683
 
 
684
 
BOOL wininput_handle_raw(HANDLE device)
685
 
{
686
 
        BYTE small_buffer[4096];
687
 
        LPBYTE data = small_buffer;
688
 
        BOOL result = FALSE;
689
 
        int size;
690
 
 
691
 
        // ignore if not enabled
692
 
        if (!input_enabled)
693
 
                return result;
694
 
 
695
 
        // determine the size of databuffer we need
696
 
        if ((*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) != 0)
697
 
                return result;
698
 
 
699
 
        // if necessary, allocate a temporary buffer and fetch the data
700
 
        if (size > sizeof(small_buffer))
701
 
        {
702
 
                data = global_alloc_array(BYTE, size);
703
 
                if (data == NULL)
704
 
                        return result;
705
 
        }
706
 
 
707
 
        // fetch the data and process the appropriate message types
708
 
        result = (*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
709
 
        if (result != 0)
710
 
        {
711
 
                RAWINPUT *input = (RAWINPUT *)data;
712
 
 
713
 
                // handle keyboard input
714
 
                if (input->header.dwType == RIM_TYPEKEYBOARD)
715
 
                {
716
 
                        osd_lock_acquire(input_lock);
717
 
                        rawinput_keyboard_update(input->header.hDevice, &input->data.keyboard);
718
 
                        osd_lock_release(input_lock);
719
 
                        result = TRUE;
720
 
                }
721
 
 
722
 
                // handle mouse input
723
 
                else if (input->header.dwType == RIM_TYPEMOUSE)
724
 
                {
725
 
                        osd_lock_acquire(input_lock);
726
 
                        rawinput_mouse_update(input->header.hDevice, &input->data.mouse);
727
 
                        osd_lock_release(input_lock);
728
 
                        result = TRUE;
729
 
                }
730
 
        }
731
 
 
732
 
        // free the temporary buffer and return the result
733
 
        if (data != small_buffer)
734
 
                global_free(data);
735
 
        return result;
736
 
}
737
 
 
738
 
 
739
 
//============================================================
740
 
//  wininput_vkey_for_mame_code
741
 
//============================================================
742
 
 
743
 
int wininput_vkey_for_mame_code(input_code code)
744
 
{
745
 
        // only works for keyboard switches
746
 
        if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.item_class() == ITEM_CLASS_SWITCH)
747
 
        {
748
 
                input_item_id id = code.item_id();
749
 
                int tablenum;
750
 
 
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];
755
 
        }
756
 
        return 0;
757
 
}
758
 
 
759
 
 
760
 
//============================================================
761
 
//  customize_input_type_list
762
 
//============================================================
763
 
 
764
 
void windows_osd_interface::customize_input_type_list(simple_list<input_type_entry> &typelist)
765
 
{
766
 
        input_type_entry *entry;
767
 
 
768
 
        // loop over the defaults
769
 
        for (entry = typelist.first(); entry != NULL; entry = entry->next())
770
 
                switch (entry->type)
771
 
                {
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);
776
 
                                break;
777
 
 
778
 
                        // alt-enter for fullscreen
779
 
                        case IPT_OSD_1:
780
 
                                entry->token = "TOGGLE_FULLSCREEN";
781
 
                                entry->name = "Toggle Fullscreen";
782
 
                                entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_ENTER);
783
 
                                break;
784
 
 
785
 
                        // alt-F12 for fullscreen snap
786
 
                        case IPT_OSD_2:
787
 
                                entry->token = "RENDER_SNAP";
788
 
                                entry->name = "Take Rendered Snapshot";
789
 
                                entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_F12);
790
 
                                break;
791
 
 
792
 
                        // alt-F11 for fullscreen video
793
 
                        case IPT_OSD_3:
794
 
                                entry->token = "RENDER_AVI";
795
 
                                entry->name = "Record Rendered Video";
796
 
                                entry->defseq[SEQ_TYPE_STANDARD].set(KEYCODE_LALT, KEYCODE_F11);
797
 
                                break;
798
 
                }
799
 
}
800
 
 
801
 
 
802
 
//============================================================
803
 
//  device_list_poll_devices
804
 
//============================================================
805
 
 
806
 
static void device_list_poll_devices(device_info *devlist_head)
807
 
{
808
 
        device_info *curdev;
809
 
 
810
 
        for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
811
 
                if (curdev->poll != NULL)
812
 
                        (*curdev->poll)(curdev);
813
 
}
814
 
 
815
 
 
816
 
//============================================================
817
 
//  device_list_reset_devices
818
 
//============================================================
819
 
 
820
 
static void device_list_reset_devices(device_info *devlist_head)
821
 
{
822
 
        device_info *curdev;
823
 
 
824
 
        for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
825
 
                generic_device_reset(curdev);
826
 
}
827
 
 
828
 
 
829
 
//============================================================
830
 
//  generic_device_alloc
831
 
//============================================================
832
 
 
833
 
static device_info *generic_device_alloc(running_machine &machine, device_info **devlist_head_ptr, const TCHAR *name)
834
 
{
835
 
        device_info **curdev_ptr;
836
 
        device_info *devinfo;
837
 
 
838
 
        // allocate memory for the device object
839
 
        devinfo = global_alloc_clear(device_info(machine));
840
 
        devinfo->head = devlist_head_ptr;
841
 
 
842
 
        // allocate a UTF8 copy of the name
843
 
        devinfo->name = utf8_from_tstring(name);
844
 
        if (devinfo->name == NULL)
845
 
                goto error;
846
 
 
847
 
        // append us to the list
848
 
        for (curdev_ptr = devinfo->head; *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
849
 
        *curdev_ptr = devinfo;
850
 
 
851
 
        return devinfo;
852
 
 
853
 
error:
854
 
        global_free(devinfo);
855
 
        return NULL;
856
 
}
857
 
 
858
 
 
859
 
//============================================================
860
 
//  generic_device_free
861
 
//============================================================
862
 
 
863
 
static void generic_device_free(device_info *devinfo)
864
 
{
865
 
        device_info **curdev_ptr;
866
 
 
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;
871
 
 
872
 
        // free the copy of the name if present
873
 
        if (devinfo->name != NULL)
874
 
                osd_free((void *)devinfo->name);
875
 
        devinfo->name = NULL;
876
 
 
877
 
        // and now free the info
878
 
        global_free(devinfo);
879
 
}
880
 
 
881
 
 
882
 
//============================================================
883
 
//  generic_device_index
884
 
//============================================================
885
 
 
886
 
static int generic_device_index(device_info *devlist_head, device_info *devinfo)
887
 
{
888
 
        int index = 0;
889
 
        while (devlist_head != NULL)
890
 
        {
891
 
                if (devlist_head == devinfo)
892
 
                        return index;
893
 
                index++;
894
 
                devlist_head = devlist_head->next;
895
 
        }
896
 
        return -1;
897
 
}
898
 
 
899
 
 
900
 
//============================================================
901
 
//  generic_device_reset
902
 
//============================================================
903
 
 
904
 
static void generic_device_reset(device_info *devinfo)
905
 
{
906
 
        // keyboard case
907
 
        if (devinfo->head == &keyboard_list)
908
 
                memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
909
 
 
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));
913
 
 
914
 
        // joystick case
915
 
        else if (devinfo->head == &joystick_list)
916
 
        {
917
 
                int povnum;
918
 
 
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;
922
 
        }
923
 
}
924
 
 
925
 
 
926
 
//============================================================
927
 
//  generic_button_get_state
928
 
//============================================================
929
 
 
930
 
static INT32 generic_button_get_state(void *device_internal, void *item_internal)
931
 
{
932
 
        device_info *devinfo = (device_info *)device_internal;
933
 
        BYTE *itemdata = (BYTE *)item_internal;
934
 
 
935
 
        // return the current state
936
 
        poll_if_necessary(devinfo->machine());
937
 
        return *itemdata >> 7;
938
 
}
939
 
 
940
 
 
941
 
//============================================================
942
 
//  generic_axis_get_state
943
 
//============================================================
944
 
 
945
 
static INT32 generic_axis_get_state(void *device_internal, void *item_internal)
946
 
{
947
 
        device_info *devinfo = (device_info *)device_internal;
948
 
        LONG *axisdata = (LONG *)item_internal;
949
 
 
950
 
        // return the current state
951
 
        poll_if_necessary(devinfo->machine());
952
 
        return *axisdata;
953
 
}
954
 
 
955
 
 
956
 
//============================================================
957
 
//  win32_init
958
 
//============================================================
959
 
 
960
 
static void win32_init(running_machine &machine)
961
 
{
962
 
        int gunnum;
963
 
 
964
 
        // we don't need any initialization unless we are using shared axis mode for lightguns
965
 
        if (!lightgun_shared_axis_mode)
966
 
                return;
967
 
 
968
 
        // we need an exit callback
969
 
        machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(win32_exit), &machine));
970
 
 
971
 
        // allocate two lightgun devices
972
 
        for (gunnum = 0; gunnum < 2; gunnum++)
973
 
        {
974
 
                static const TCHAR *const gun_names[] = { TEXT("Shared Axis Gun 1"), TEXT("Shared Axis Gun 2") };
975
 
                device_info *devinfo;
976
 
                int axisnum, butnum;
977
 
 
978
 
                // allocate a device
979
 
                devinfo = generic_device_alloc(machine, &lightgun_list, gun_names[gunnum]);
980
 
                if (devinfo == NULL)
981
 
                        break;
982
 
 
983
 
                // add the device
984
 
                devinfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(devinfo->name, devinfo);
985
 
 
986
 
                // populate the axes
987
 
                for (axisnum = 0; axisnum < 2; axisnum++)
988
 
                {
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);
991
 
                        osd_free(name);
992
 
                }
993
 
 
994
 
                // populate the buttons
995
 
                for (butnum = 0; butnum < 2; butnum++)
996
 
                {
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]);
999
 
                        osd_free(name);
1000
 
                }
1001
 
        }
1002
 
}
1003
 
 
1004
 
 
1005
 
//============================================================
1006
 
//  win32_exit
1007
 
//============================================================
1008
 
 
1009
 
static void win32_exit(running_machine &machine)
1010
 
{
1011
 
        // skip if we're in shared axis mode
1012
 
        if (!lightgun_shared_axis_mode)
1013
 
                return;
1014
 
 
1015
 
        // delete the lightgun devices
1016
 
        while (lightgun_list != NULL)
1017
 
                generic_device_free(lightgun_list);
1018
 
}
1019
 
 
1020
 
 
1021
 
//============================================================
1022
 
//  win32_keyboard_poll
1023
 
//============================================================
1024
 
 
1025
 
static void win32_keyboard_poll(device_info *devinfo)
1026
 
{
1027
 
        int keynum;
1028
 
 
1029
 
        // clear the flag that says we detected a key down via win32
1030
 
        keyboard_win32_reported_key_down = FALSE;
1031
 
 
1032
 
        // reset the keyboard state and then repopulate
1033
 
        memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
1034
 
 
1035
 
        // iterate over keys
1036
 
        for (keynum = 0; keynum < ARRAY_LENGTH(win_key_trans_table); keynum++)
1037
 
        {
1038
 
                int vk = win_key_trans_table[keynum][VIRTUAL_KEY];
1039
 
                if (vk != 0 && (GetAsyncKeyState(vk) & 0x8000) != 0)
1040
 
                {
1041
 
                        int dik = win_key_trans_table[keynum][DI_KEY];
1042
 
 
1043
 
                        // conver the VK code to a scancode (DIK code)
1044
 
                        if (dik != 0)
1045
 
                                devinfo->keyboard.state[dik] = 0x80;
1046
 
 
1047
 
                        // set this flag so that we continue to use win32 until all keys are up
1048
 
                        keyboard_win32_reported_key_down = TRUE;
1049
 
                }
1050
 
        }
1051
 
}
1052
 
 
1053
 
 
1054
 
//============================================================
1055
 
//  win32_lightgun_poll
1056
 
//============================================================
1057
 
 
1058
 
static void win32_lightgun_poll(device_info *devinfo)
1059
 
{
1060
 
        INT32 xpos = 0, ypos = 0;
1061
 
        POINT mousepos;
1062
 
 
1063
 
        // if we are using the shared axis hack, the data is updated via Windows messages only
1064
 
        if (lightgun_shared_axis_mode)
1065
 
                return;
1066
 
 
1067
 
        // get the cursor position and transform into final results
1068
 
        GetCursorPos(&mousepos);
1069
 
        if (win_window_list != NULL)
1070
 
        {
1071
 
                RECT client_rect;
1072
 
 
1073
 
                // get the position relative to the window
1074
 
                GetClientRect(win_window_list->hwnd, &client_rect);
1075
 
                ScreenToClient(win_window_list->hwnd, &mousepos);
1076
 
 
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);
1080
 
        }
1081
 
 
1082
 
        // update the X/Y positions
1083
 
        devinfo->mouse.state.lX = xpos;
1084
 
        devinfo->mouse.state.lY = ypos;
1085
 
}
1086
 
 
1087
 
 
1088
 
//============================================================
1089
 
//  dinput_init
1090
 
//============================================================
1091
 
 
1092
 
static void dinput_init(running_machine &machine)
1093
 
{
1094
 
        HRESULT result;
1095
 
#if DIRECTINPUT_VERSION >= 0x800
1096
 
        int didevtype_keyboard = DI8DEVCLASS_KEYBOARD;
1097
 
        int didevtype_mouse = DI8DEVCLASS_POINTER;
1098
 
        int didevtype_joystick = DI8DEVCLASS_GAMECTRL;
1099
 
 
1100
 
        dinput_version = DIRECTINPUT_VERSION;
1101
 
        result = DirectInput8Create(GetModuleHandle(NULL), dinput_version, IID_IDirectInput8, (void **)&dinput, NULL);
1102
 
        if (result != DI_OK)
1103
 
        {
1104
 
                dinput_version = 0;
1105
 
                return;
1106
 
        }
1107
 
#else
1108
 
        int didevtype_keyboard = DIDEVTYPE_KEYBOARD;
1109
 
        int didevtype_mouse = DIDEVTYPE_MOUSE;
1110
 
        int didevtype_joystick = DIDEVTYPE_JOYSTICK;
1111
 
 
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)
1116
 
        {
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)
1121
 
                {
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)
1126
 
                        {
1127
 
                                dinput_version = 0;
1128
 
                                return;
1129
 
                        }
1130
 
                }
1131
 
        }
1132
 
#endif
1133
 
 
1134
 
        mame_printf_verbose("DirectInput: Using DirectInput %d\n", dinput_version >> 8);
1135
 
 
1136
 
        // we need an exit callback
1137
 
        machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(dinput_exit), &machine));
1138
 
 
1139
 
        // initialize keyboard devices, but only if we don't have any yet
1140
 
        if (keyboard_list == NULL)
1141
 
        {
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);
1146
 
        }
1147
 
 
1148
 
        // initialize mouse & lightgun devices, but only if we don't have any yet
1149
 
        if (mouse_list == NULL)
1150
 
        {
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);
1155
 
        }
1156
 
 
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);
1161
 
}
1162
 
 
1163
 
 
1164
 
//============================================================
1165
 
//  dinput_exit
1166
 
//============================================================
1167
 
 
1168
 
static void dinput_exit(running_machine &machine)
1169
 
{
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);
1179
 
 
1180
 
        // release DirectInput
1181
 
        if (dinput != NULL)
1182
 
                IDirectInput_Release(dinput);
1183
 
        dinput = NULL;
1184
 
}
1185
 
 
1186
 
 
1187
 
//============================================================
1188
 
//  dinput_set_dword_property
1189
 
//============================================================
1190
 
 
1191
 
static HRESULT dinput_set_dword_property(LPDIRECTINPUTDEVICE device, REFGUID property_guid, DWORD object, DWORD how, DWORD value)
1192
 
{
1193
 
        DIPROPDWORD dipdw;
1194
 
 
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;
1200
 
 
1201
 
        return IDirectInputDevice_SetProperty(device, property_guid, &dipdw.diph);
1202
 
}
1203
 
 
1204
 
 
1205
 
//============================================================
1206
 
//  dinput_device_create
1207
 
//============================================================
1208
 
 
1209
 
static device_info *dinput_device_create(running_machine &machine, device_info **devlist_head_ptr, LPCDIDEVICEINSTANCE instance, LPCDIDATAFORMAT format1, LPCDIDATAFORMAT format2, DWORD cooperative_level)
1210
 
{
1211
 
        device_info *devinfo;
1212
 
        HRESULT result;
1213
 
 
1214
 
        // allocate memory for the device object
1215
 
        devinfo = generic_device_alloc(machine, devlist_head_ptr, instance->tszInstanceName);
1216
 
 
1217
 
        // attempt to create a device
1218
 
        result = IDirectInput_CreateDevice(dinput, WRAP_REFIID(instance->guidInstance), &devinfo->dinput.device, NULL);
1219
 
        if (result != DI_OK)
1220
 
                goto error;
1221
 
 
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;
1226
 
 
1227
 
        // get the caps
1228
 
        devinfo->dinput.caps.dwSize = STRUCTSIZE(DIDEVCAPS);
1229
 
        result = IDirectInputDevice_GetCapabilities(devinfo->dinput.device, &devinfo->dinput.caps);
1230
 
        if (result != DI_OK)
1231
 
                goto error;
1232
 
 
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)
1237
 
        {
1238
 
                // use the secondary format if available
1239
 
                if (format2 != NULL)
1240
 
                {
1241
 
                        devinfo->dinput.format = format2;
1242
 
                        result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device, devinfo->dinput.format);
1243
 
                }
1244
 
                if (result != DI_OK)
1245
 
                        goto error;
1246
 
        }
1247
 
 
1248
 
        // set the cooperative level
1249
 
        result = IDirectInputDevice_SetCooperativeLevel(devinfo->dinput.device, win_window_list->hwnd, cooperative_level);
1250
 
        if (result != DI_OK)
1251
 
                goto error;
1252
 
        return devinfo;
1253
 
 
1254
 
error:
1255
 
        dinput_device_release(devinfo);
1256
 
        return NULL;
1257
 
}
1258
 
 
1259
 
 
1260
 
//============================================================
1261
 
//  dinput_device_release
1262
 
//============================================================
1263
 
 
1264
 
static void dinput_device_release(device_info *devinfo)
1265
 
{
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;
1270
 
 
1271
 
        // release the regular device if present
1272
 
        if (devinfo->dinput.device != NULL)
1273
 
                IDirectInputDevice_Release(devinfo->dinput.device);
1274
 
        devinfo->dinput.device = NULL;
1275
 
 
1276
 
        // free the item list
1277
 
        generic_device_free(devinfo);
1278
 
}
1279
 
 
1280
 
 
1281
 
//============================================================
1282
 
//  dinput_device_item_name
1283
 
//============================================================
1284
 
 
1285
 
static char *dinput_device_item_name(device_info *devinfo, int offset, const TCHAR *defstring, const TCHAR *suffix)
1286
 
{
1287
 
        DIDEVICEOBJECTINSTANCE instance = { 0 };
1288
 
        const TCHAR *namestring = instance.tszName;
1289
 
        TCHAR *combined;
1290
 
        HRESULT result;
1291
 
        char *utf8;
1292
 
 
1293
 
        // query the key name
1294
 
        instance.dwSize = STRUCTSIZE(DIDEVICEOBJECTINSTANCE);
1295
 
        result = IDirectInputDevice_GetObjectInfo(devinfo->dinput.device, &instance, offset, DIPH_BYOFFSET);
1296
 
 
1297
 
        // if we got an error and have no default string, just return NULL
1298
 
        if (result != DI_OK)
1299
 
        {
1300
 
                if (defstring == NULL)
1301
 
                        return NULL;
1302
 
                namestring = defstring;
1303
 
        }
1304
 
 
1305
 
        // if no suffix, return as-is
1306
 
        if (suffix == NULL)
1307
 
                return utf8_from_tstring(namestring);
1308
 
 
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);
1314
 
 
1315
 
        // convert to UTF8, free the temporary string, and return
1316
 
        utf8 = utf8_from_tstring(combined);
1317
 
        global_free(combined);
1318
 
        return utf8;
1319
 
}
1320
 
 
1321
 
 
1322
 
//============================================================
1323
 
//  dinput_device_poll
1324
 
//============================================================
1325
 
 
1326
 
static HRESULT dinput_device_poll(device_info *devinfo)
1327
 
{
1328
 
        HRESULT result;
1329
 
 
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);
1334
 
 
1335
 
        // handle lost inputs here
1336
 
        if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
1337
 
        {
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);
1341
 
        }
1342
 
 
1343
 
        return result;
1344
 
}
1345
 
 
1346
 
 
1347
 
//============================================================
1348
 
//  dinput_keyboard_enum
1349
 
//============================================================
1350
 
 
1351
 
static BOOL CALLBACK dinput_keyboard_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1352
 
{
1353
 
        running_machine &machine = *(running_machine *)ref;
1354
 
        device_info *devinfo;
1355
 
        int keynum;
1356
 
 
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)
1360
 
                goto exit;
1361
 
 
1362
 
        // add the device
1363
 
        devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
1364
 
        devinfo->poll = dinput_keyboard_poll;
1365
 
 
1366
 
        // populate it
1367
 
        for (keynum = 0; keynum < MAX_KEYS; keynum++)
1368
 
        {
1369
 
                input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
1370
 
                TCHAR defname[20];
1371
 
                char *name;
1372
 
 
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);
1376
 
 
1377
 
                // add the item to the device
1378
 
                devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
1379
 
                osd_free(name);
1380
 
        }
1381
 
 
1382
 
exit:
1383
 
        return DIENUM_CONTINUE;
1384
 
}
1385
 
 
1386
 
 
1387
 
//============================================================
1388
 
//  dinput_keyboard_poll
1389
 
//============================================================
1390
 
 
1391
 
static void dinput_keyboard_poll(device_info *devinfo)
1392
 
{
1393
 
        HRESULT result = dinput_device_poll(devinfo);
1394
 
 
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);
1399
 
}
1400
 
 
1401
 
 
1402
 
//============================================================
1403
 
//  dinput_mouse_enum
1404
 
//============================================================
1405
 
 
1406
 
static BOOL CALLBACK dinput_mouse_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1407
 
{
1408
 
        device_info *devinfo, *guninfo = NULL;
1409
 
        running_machine &machine = *(running_machine *)ref;
1410
 
        int axisnum, butnum;
1411
 
        HRESULT result;
1412
 
 
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)
1416
 
                goto exit;
1417
 
 
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)
1421
 
        {
1422
 
                guninfo = generic_device_alloc(machine, &lightgun_list, instance->tszInstanceName);
1423
 
                if (guninfo == NULL)
1424
 
                        goto exit;
1425
 
        }
1426
 
 
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)
1430
 
        {
1431
 
                mame_printf_error("DirectInput: Unable to set relative mode for mouse %d (%s)\n", generic_device_index(mouse_list, devinfo), devinfo->name);
1432
 
                goto error;
1433
 
        }
1434
 
 
1435
 
        // add the device
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)
1439
 
        {
1440
 
                guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
1441
 
                guninfo->poll = win32_lightgun_poll;
1442
 
        }
1443
 
 
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);
1447
 
 
1448
 
        // populate the axes
1449
 
        for (axisnum = 0; axisnum < devinfo->dinput.caps.dwAxes; axisnum++)
1450
 
        {
1451
 
                char *name = dinput_device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
1452
 
 
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);
1457
 
 
1458
 
                osd_free(name);
1459
 
        }
1460
 
 
1461
 
        // populate the buttons
1462
 
        for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
1463
 
        {
1464
 
                FPTR offset = (FPTR)(&((DIMOUSESTATE *)NULL)->rgbButtons[butnum]);
1465
 
                char *name = dinput_device_item_name(devinfo, offset, default_button_name(butnum), NULL);
1466
 
 
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]);
1472
 
 
1473
 
                osd_free(name);
1474
 
        }
1475
 
 
1476
 
exit:
1477
 
        return DIENUM_CONTINUE;
1478
 
 
1479
 
error:
1480
 
        if (guninfo != NULL)
1481
 
                generic_device_free(guninfo);
1482
 
        if (devinfo != NULL)
1483
 
                dinput_device_release(devinfo);
1484
 
        goto exit;
1485
 
}
1486
 
 
1487
 
 
1488
 
//============================================================
1489
 
//  dinput_mouse_poll
1490
 
//============================================================
1491
 
 
1492
 
static void dinput_mouse_poll(device_info *devinfo)
1493
 
{
1494
 
        // poll
1495
 
        dinput_device_poll(devinfo);
1496
 
 
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;
1501
 
}
1502
 
 
1503
 
 
1504
 
//============================================================
1505
 
//  dinput_joystick_enum
1506
 
//============================================================
1507
 
 
1508
 
static BOOL CALLBACK dinput_joystick_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
1509
 
{
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;
1514
 
        HRESULT result;
1515
 
 
1516
 
        if (win_window_list != NULL && win_has_menu(win_window_list)) {
1517
 
                cooperative_level = DISCL_BACKGROUND | DISCL_EXCLUSIVE;
1518
 
        }
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)
1522
 
                goto exit;
1523
 
 
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);
1528
 
 
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);
1533
 
 
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);
1538
 
 
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);
1543
 
 
1544
 
        // add the device
1545
 
        devinfo->device = machine.input().device_class(DEVICE_CLASS_JOYSTICK).add_device(devinfo->name, devinfo);
1546
 
        devinfo->poll = dinput_joystick_poll;
1547
 
 
1548
 
        // populate the axes
1549
 
        for (axisnum = axiscount = 0; axiscount < devinfo->dinput.caps.dwAxes && axisnum < 8; axisnum++)
1550
 
        {
1551
 
                DIPROPRANGE dipr;
1552
 
                char *name;
1553
 
 
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)
1561
 
                        continue;
1562
 
                devinfo->joystick.rangemin[axisnum] = dipr.lMin;
1563
 
                devinfo->joystick.rangemax[axisnum] = dipr.lMax;
1564
 
 
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);
1568
 
                osd_free(name);
1569
 
 
1570
 
                axiscount++;
1571
 
        }
1572
 
 
1573
 
        // populate the POVs
1574
 
        for (povnum = 0; povnum < devinfo->dinput.caps.dwPOVs; povnum++)
1575
 
        {
1576
 
                char *name;
1577
 
 
1578
 
                // left
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));
1581
 
                osd_free(name);
1582
 
 
1583
 
                // right
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));
1586
 
                osd_free(name);
1587
 
 
1588
 
                // up
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));
1591
 
                osd_free(name);
1592
 
 
1593
 
                // down
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));
1596
 
                osd_free(name);
1597
 
        }
1598
 
 
1599
 
        // populate the buttons
1600
 
        for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
1601
 
        {
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]);
1605
 
                osd_free(name);
1606
 
        }
1607
 
 
1608
 
exit:
1609
 
        return DIENUM_CONTINUE;
1610
 
}
1611
 
 
1612
 
 
1613
 
//============================================================
1614
 
//  dinput_joystick_poll
1615
 
//============================================================
1616
 
 
1617
 
static void dinput_joystick_poll(device_info *devinfo)
1618
 
{
1619
 
        int axisnum;
1620
 
 
1621
 
        // poll the device first
1622
 
        dinput_device_poll(devinfo);
1623
 
 
1624
 
        // normalize axis values
1625
 
        for (axisnum = 0; axisnum < 8; axisnum++)
1626
 
        {
1627
 
                LONG *axis = (&devinfo->joystick.state.lX) + axisnum;
1628
 
                *axis = normalize_absolute_axis(*axis, devinfo->joystick.rangemin[axisnum], devinfo->joystick.rangemax[axisnum]);
1629
 
        }
1630
 
}
1631
 
 
1632
 
 
1633
 
//============================================================
1634
 
//  dinput_joystick_pov_get_state
1635
 
//============================================================
1636
 
 
1637
 
static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
1638
 
{
1639
 
        device_info *devinfo = (device_info *)device_internal;
1640
 
        int povnum = (FPTR)item_internal / 4;
1641
 
        int povdir = (FPTR)item_internal % 4;
1642
 
        INT32 result = 0;
1643
 
        DWORD pov;
1644
 
 
1645
 
        // get the current state
1646
 
        poll_if_necessary(devinfo->machine());
1647
 
        pov = devinfo->joystick.state.rgdwPOV[povnum];
1648
 
 
1649
 
        // if invalid, return 0
1650
 
        if ((pov & 0xffff) == 0xffff)
1651
 
                return result;
1652
 
 
1653
 
        // return the current state
1654
 
        switch (povdir)
1655
 
        {
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;
1660
 
        }
1661
 
        return result;
1662
 
}
1663
 
 
1664
 
 
1665
 
//============================================================
1666
 
//  rawinput_init
1667
 
//============================================================
1668
 
 
1669
 
static void rawinput_init(running_machine &machine)
1670
 
{
1671
 
        RAWINPUTDEVICELIST *devlist = NULL;
1672
 
        int device_count, devnum, regcount;
1673
 
        RAWINPUTDEVICE reglist[2];
1674
 
        HMODULE user32;
1675
 
 
1676
 
        // we need pause and exit callbacks
1677
 
        machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(rawinput_exit), &machine));
1678
 
 
1679
 
        // look in user32 for the raw input APIs
1680
 
        user32 = LoadLibrary(TEXT("user32.dll"));
1681
 
        if (user32 == NULL)
1682
 
                goto error;
1683
 
 
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)
1690
 
                goto error;
1691
 
        mame_printf_verbose("RawInput: APIs detected\n");
1692
 
 
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)
1695
 
                goto error;
1696
 
        if (device_count == 0)
1697
 
                goto error;
1698
 
        devlist = global_alloc_array(RAWINPUTDEVICELIST, device_count);
1699
 
        if ((*get_rawinput_device_list)(devlist, &device_count, sizeof(*devlist)) == -1)
1700
 
                goto error;
1701
 
 
1702
 
        // iterate backwards through devices; new devices are added at the head
1703
 
        for (devnum = device_count - 1; devnum >= 0; devnum--)
1704
 
        {
1705
 
                RAWINPUTDEVICELIST *device = &devlist[devnum];
1706
 
 
1707
 
                // handle keyboards
1708
 
                if (device->dwType == RIM_TYPEKEYBOARD && !FORCE_DIRECTINPUT)
1709
 
                        rawinput_keyboard_enum(machine, device);
1710
 
 
1711
 
                // handle mice
1712
 
                else if (device->dwType == RIM_TYPEMOUSE && !FORCE_DIRECTINPUT)
1713
 
                        rawinput_mouse_enum(machine, device);
1714
 
        }
1715
 
 
1716
 
        // finally, register to receive raw input WM_INPUT messages
1717
 
        regcount = 0;
1718
 
        if (keyboard_list != NULL)
1719
 
        {
1720
 
                reglist[regcount].usUsagePage = 0x01;
1721
 
                reglist[regcount].usUsage = 0x06;
1722
 
                reglist[regcount].dwFlags = RIDEV_INPUTSINK;
1723
 
                reglist[regcount].hwndTarget = win_window_list->hwnd;
1724
 
                regcount++;
1725
 
        }
1726
 
        if (mouse_list != NULL)
1727
 
        {
1728
 
                reglist[regcount].usUsagePage = 0x01;
1729
 
                reglist[regcount].usUsage = 0x02;
1730
 
                reglist[regcount].dwFlags = 0;
1731
 
                reglist[regcount].hwndTarget = win_window_list->hwnd;
1732
 
                regcount++;
1733
 
        }
1734
 
 
1735
 
        // if the registration fails, we need to back off
1736
 
        if (regcount > 0)
1737
 
                if (!(*register_rawinput_devices)(reglist, regcount, sizeof(reglist[0])))
1738
 
                        goto error;
1739
 
 
1740
 
        global_free(devlist);
1741
 
        return;
1742
 
 
1743
 
error:
1744
 
        if (devlist != NULL)
1745
 
                global_free(devlist);
1746
 
}
1747
 
 
1748
 
 
1749
 
//============================================================
1750
 
//  rawinput_exit
1751
 
//============================================================
1752
 
 
1753
 
static void rawinput_exit(running_machine &machine)
1754
 
{
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);
1762
 
}
1763
 
 
1764
 
 
1765
 
//============================================================
1766
 
//  rawinput_device_create
1767
 
//============================================================
1768
 
 
1769
 
static device_info *rawinput_device_create(running_machine &machine, device_info **devlist_head_ptr, PRAWINPUTDEVICELIST device)
1770
 
{
1771
 
        device_info *devinfo = NULL;
1772
 
        TCHAR *tname = NULL;
1773
 
        INT name_length;
1774
 
 
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)
1777
 
                goto error;
1778
 
        tname = global_alloc_array(TCHAR, name_length);
1779
 
        if ((*get_rawinput_device_info)(device->hDevice, RIDI_DEVICENAME, tname, &name_length) == -1)
1780
 
                goto error;
1781
 
 
1782
 
        // if this is an RDP name, skip it
1783
 
        if (_tcsstr(tname, TEXT("Root#RDP_")) != NULL)
1784
 
                goto error;
1785
 
 
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);
1789
 
        global_free(tname);
1790
 
 
1791
 
        // copy the handle
1792
 
        devinfo->rawinput.device = device->hDevice;
1793
 
        return devinfo;
1794
 
 
1795
 
error:
1796
 
        if (tname != NULL)
1797
 
                global_free(tname);
1798
 
        if (devinfo != NULL)
1799
 
                rawinput_device_release(devinfo);
1800
 
        return NULL;
1801
 
}
1802
 
 
1803
 
 
1804
 
//============================================================
1805
 
//  rawinput_device_release
1806
 
//============================================================
1807
 
 
1808
 
static void rawinput_device_release(device_info *devinfo)
1809
 
{
1810
 
        // free the item list
1811
 
        generic_device_free(devinfo);
1812
 
}
1813
 
 
1814
 
 
1815
 
//============================================================
1816
 
//  rawinput_device_improve_name
1817
 
//============================================================
1818
 
 
1819
 
static TCHAR *rawinput_device_improve_name(TCHAR *name)
1820
 
{
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;
1826
 
        const TCHAR *chsrc;
1827
 
        HKEY regkey = NULL;
1828
 
        int usbindex;
1829
 
        TCHAR *chdst;
1830
 
        LONG result;
1831
 
 
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 "\\?\"
1836
 
 
1837
 
        // ensure the name is something we can handle
1838
 
        if (_tcsncmp(name, TEXT("\\\\?\\"), 4) != 0 && _tcsncmp(name, TEXT("\\??\\"), 4) != 0)
1839
 
                return name;
1840
 
 
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);
1845
 
 
1846
 
        // convert all # to \ in the name
1847
 
        for (chsrc = name + 4; *chsrc != 0; chsrc++)
1848
 
                *chdst++ = (*chsrc == '#') ? '\\' : *chsrc;
1849
 
        *chdst = 0;
1850
 
 
1851
 
        // remove the final chunk
1852
 
        chdst = _tcsrchr(regpath, '\\');
1853
 
        if (chdst == NULL)
1854
 
                goto exit;
1855
 
        *chdst = 0;
1856
 
 
1857
 
        // now try to open the registry key
1858
 
        result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &regkey);
1859
 
        if (result != ERROR_SUCCESS)
1860
 
                goto exit;
1861
 
 
1862
 
        // fetch the device description; if it exists, we are finished
1863
 
        regstring = reg_query_string(regkey, TEXT("DeviceDesc"));
1864
 
        if (regstring != NULL)
1865
 
                goto convert;
1866
 
 
1867
 
        // close this key
1868
 
        RegCloseKey(regkey);
1869
 
        regkey = NULL;
1870
 
 
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)
1873
 
                goto exit;
1874
 
 
1875
 
        // extract the expected parent ID from the regpath
1876
 
        parentid = _tcsrchr(regpath, '\\');
1877
 
        if (parentid == NULL)
1878
 
                goto exit;
1879
 
        parentid++;
1880
 
 
1881
 
        // open the USB key
1882
 
        result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, usbbasepath, 0, KEY_READ, &regkey);
1883
 
        if (result != ERROR_SUCCESS)
1884
 
                goto exit;
1885
 
 
1886
 
        // enumerate the USB key
1887
 
        for (usbindex = 0; result == ERROR_SUCCESS && regstring == NULL; usbindex++)
1888
 
        {
1889
 
                TCHAR keyname[MAX_PATH];
1890
 
                DWORD namelen;
1891
 
 
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)
1896
 
                {
1897
 
                        LONG subresult;
1898
 
                        int subindex;
1899
 
                        HKEY subkey;
1900
 
 
1901
 
                        // open the subkey
1902
 
                        subresult = RegOpenKeyEx(regkey, keyname, 0, KEY_READ, &subkey);
1903
 
                        if (subresult != ERROR_SUCCESS)
1904
 
                                continue;
1905
 
 
1906
 
                        // enumerate the subkey
1907
 
                        for (subindex = 0; subresult == ERROR_SUCCESS && regstring == NULL; subindex++)
1908
 
                        {
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)
1913
 
                                {
1914
 
                                        TCHAR *endparentid;
1915
 
                                        LONG endresult;
1916
 
                                        HKEY endkey;
1917
 
 
1918
 
                                        // open this final key
1919
 
                                        endresult = RegOpenKeyEx(subkey, keyname, 0, KEY_READ, &endkey);
1920
 
                                        if (endresult != ERROR_SUCCESS)
1921
 
                                                continue;
1922
 
 
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"));
1927
 
 
1928
 
                                        // free memory and close the key
1929
 
                                        if (endparentid != NULL)
1930
 
                                                global_free(endparentid);
1931
 
                                        RegCloseKey(endkey);
1932
 
                                }
1933
 
                        }
1934
 
 
1935
 
                        // close the subkey
1936
 
                        RegCloseKey(subkey);
1937
 
                }
1938
 
        }
1939
 
 
1940
 
        // if we didn't find anything, go to the exit
1941
 
        if (regstring == NULL)
1942
 
                goto exit;
1943
 
 
1944
 
convert:
1945
 
        // replace the name with the nicer one
1946
 
        global_free(name);
1947
 
 
1948
 
        // remove anything prior to the final semicolon
1949
 
        chsrc = _tcsrchr(regstring, ';');
1950
 
        if (chsrc != NULL)
1951
 
                chsrc++;
1952
 
        else
1953
 
                chsrc = regstring;
1954
 
        name = global_alloc_array(TCHAR, _tcslen(chsrc) + 1);
1955
 
        _tcscpy(name, chsrc);
1956
 
 
1957
 
exit:
1958
 
        if (regstring != NULL)
1959
 
                global_free(regstring);
1960
 
        if (regpath != NULL)
1961
 
                global_free(regpath);
1962
 
        if (regkey != NULL)
1963
 
                RegCloseKey(regkey);
1964
 
 
1965
 
        return name;
1966
 
}
1967
 
 
1968
 
 
1969
 
//============================================================
1970
 
//  rawinput_keyboard_enum
1971
 
//============================================================
1972
 
 
1973
 
static void rawinput_keyboard_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
1974
 
{
1975
 
        device_info *devinfo;
1976
 
        int keynum;
1977
 
 
1978
 
        // allocate and link in a new device
1979
 
        devinfo = rawinput_device_create(machine, &keyboard_list, device);
1980
 
        if (devinfo == NULL)
1981
 
                return;
1982
 
 
1983
 
        // add the device
1984
 
        devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
1985
 
 
1986
 
        // populate it
1987
 
        for (keynum = 0; keynum < MAX_KEYS; keynum++)
1988
 
        {
1989
 
                input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
1990
 
                TCHAR keyname[100];
1991
 
                char *name;
1992
 
 
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);
1997
 
 
1998
 
                // add the item to the device
1999
 
                devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
2000
 
                osd_free(name);
2001
 
        }
2002
 
}
2003
 
 
2004
 
 
2005
 
//============================================================
2006
 
//  rawinput_keyboard_update
2007
 
//============================================================
2008
 
 
2009
 
static void rawinput_keyboard_update(HANDLE device, RAWKEYBOARD *data)
2010
 
{
2011
 
        device_info *devinfo;
2012
 
 
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)
2016
 
                {
2017
 
                        // determine the full DIK-compatible scancode
2018
 
                        UINT8 scancode = (data->MakeCode & 0x7f) | ((data->Flags & RI_KEY_E0) ? 0x80 : 0x00);
2019
 
 
2020
 
                        // scancode 0xaa is a special shift code we need to ignore
2021
 
                        if (scancode == 0xaa)
2022
 
                                break;
2023
 
 
2024
 
                        // set or clear the key
2025
 
                        if (!(data->Flags & RI_KEY_BREAK))
2026
 
                                devinfo->keyboard.state[scancode] = 0x80;
2027
 
                        else
2028
 
                                devinfo->keyboard.state[scancode] = 0x00;
2029
 
                        break;
2030
 
                }
2031
 
}
2032
 
 
2033
 
 
2034
 
//============================================================
2035
 
//  rawinput_mouse_enum
2036
 
//============================================================
2037
 
 
2038
 
static void rawinput_mouse_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
2039
 
{
2040
 
        device_info *devinfo, *guninfo = NULL;
2041
 
        int axisnum, butnum;
2042
 
 
2043
 
        // allocate and link in a new mouse device
2044
 
        devinfo = rawinput_device_create(machine, &mouse_list, device);
2045
 
        if (devinfo == NULL)
2046
 
                return;
2047
 
        devinfo->poll = rawinput_mouse_poll;
2048
 
 
2049
 
        // allocate a second device for the gun (unless we are using the shared axis mode)
2050
 
        if (!lightgun_shared_axis_mode)
2051
 
        {
2052
 
                guninfo = rawinput_device_create(machine, &lightgun_list, device);
2053
 
                assert(guninfo != NULL);
2054
 
        }
2055
 
 
2056
 
        // add the device
2057
 
        devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name, devinfo);
2058
 
        if (guninfo != NULL)
2059
 
        {
2060
 
                guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
2061
 
                guninfo->poll = NULL;
2062
 
        }
2063
 
 
2064
 
        // populate the axes
2065
 
        for (axisnum = 0; axisnum < 3; axisnum++)
2066
 
        {
2067
 
                char *name = utf8_from_tstring(default_axis_name[axisnum]);
2068
 
 
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);
2073
 
 
2074
 
                osd_free(name);
2075
 
        }
2076
 
 
2077
 
        // populate the buttons
2078
 
        for (butnum = 0; butnum < 5; butnum++)
2079
 
        {
2080
 
                char *name = utf8_from_tstring(default_button_name(butnum));
2081
 
 
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]);
2086
 
 
2087
 
                osd_free(name);
2088
 
        }
2089
 
}
2090
 
 
2091
 
 
2092
 
//============================================================
2093
 
//  rawinput_mouse_update
2094
 
//============================================================
2095
 
 
2096
 
static void rawinput_mouse_update(HANDLE device, RAWMOUSE *data)
2097
 
{
2098
 
        device_info *devlist = (data->usFlags & MOUSE_MOVE_ABSOLUTE) ? lightgun_list : mouse_list;
2099
 
        device_info *devinfo;
2100
 
 
2101
 
        // find the mouse in the list and process
2102
 
        for (devinfo = devlist; devinfo != NULL; devinfo = devinfo->next)
2103
 
                if (devinfo->rawinput.device == device)
2104
 
                {
2105
 
                        // if we got relative data, update it as a mouse
2106
 
                        if (!(data->usFlags & MOUSE_MOVE_ABSOLUTE))
2107
 
                        {
2108
 
                                devinfo->mouse.raw_x += data->lLastX * INPUT_RELATIVE_PER_PIXEL;
2109
 
                                devinfo->mouse.raw_y += data->lLastY * INPUT_RELATIVE_PER_PIXEL;
2110
 
 
2111
 
                                // update zaxis
2112
 
                                if (data->usButtonFlags & RI_MOUSE_WHEEL)
2113
 
                                        devinfo->mouse.raw_z += (INT16)data->usButtonData * INPUT_RELATIVE_PER_PIXEL;
2114
 
                        }
2115
 
 
2116
 
                        // otherwise, update it as a lightgun
2117
 
                        else
2118
 
                        {
2119
 
                                devinfo->mouse.state.lX = normalize_absolute_axis(data->lLastX, 0, 0xffff);
2120
 
                                devinfo->mouse.state.lY = normalize_absolute_axis(data->lLastY, 0, 0xffff);
2121
 
                        }
2122
 
 
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;
2134
 
                        break;
2135
 
                }
2136
 
}
2137
 
 
2138
 
 
2139
 
//============================================================
2140
 
//  rawinput_mouse_poll
2141
 
//============================================================
2142
 
 
2143
 
static void rawinput_mouse_poll(device_info *devinfo)
2144
 
{
2145
 
        poll_if_necessary(devinfo->machine());
2146
 
 
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);
2156
 
}
2157
 
 
2158
 
 
2159
 
//============================================================
2160
 
//  reg_query_string
2161
 
//============================================================
2162
 
 
2163
 
static TCHAR *reg_query_string(HKEY key, const TCHAR *path)
2164
 
{
2165
 
        TCHAR *buffer;
2166
 
        DWORD datalen;
2167
 
        LONG result;
2168
 
 
2169
 
        // first query to get the length
2170
 
        result = RegQueryValueEx(key, path, NULL, NULL, NULL, &datalen);
2171
 
        if (result != ERROR_SUCCESS)
2172
 
                return NULL;
2173
 
 
2174
 
        // allocate a buffer
2175
 
        buffer = global_alloc_array(TCHAR, datalen + sizeof(*buffer));
2176
 
        buffer[datalen / sizeof(*buffer)] = 0;
2177
 
 
2178
 
        // now get the actual data
2179
 
        result = RegQueryValueEx(key, path, NULL, NULL, (LPBYTE)buffer, &datalen);
2180
 
        if (result == ERROR_SUCCESS)
2181
 
                return buffer;
2182
 
 
2183
 
        // otherwise return a NULL buffer
2184
 
        global_free(buffer);
2185
 
        return NULL;
2186
 
}
2187
 
 
2188
 
 
2189
 
//============================================================
2190
 
//  default_button_name
2191
 
//============================================================
2192
 
 
2193
 
static const TCHAR *default_button_name(int which)
2194
 
{
2195
 
        static TCHAR buffer[20];
2196
 
        _sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("B%d"), which);
2197
 
        return buffer;
2198
 
}
2199
 
 
2200
 
 
2201
 
//============================================================
2202
 
//  default_pov_name
2203
 
//============================================================
2204
 
 
2205
 
static const TCHAR *default_pov_name(int which)
2206
 
{
2207
 
        static TCHAR buffer[20];
2208
 
        _sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("POV%d"), which);
2209
 
        return buffer;
2210
 
}