summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/windows/input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/windows/input.cpp')
-rw-r--r--src/osd/windows/input.cpp2255
1 files changed, 0 insertions, 2255 deletions
diff --git a/src/osd/windows/input.cpp b/src/osd/windows/input.cpp
deleted file mode 100644
index 6a9d534a2f6..00000000000
--- a/src/osd/windows/input.cpp
+++ /dev/null
@@ -1,2255 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// input.c - Win32 implementation of MAME input routines
-//
-//============================================================
-
-// For testing purposes: force DirectInput
-#define FORCE_DIRECTINPUT 0
-
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winioctl.h>
-#include <tchar.h>
-
-// undef WINNT for dinput.h to prevent duplicate definition
-#undef WINNT
-#include <dinput.h>
-#undef interface
-
-// standard C headers
-#include <conio.h>
-#include <ctype.h>
-#include <stddef.h>
-
-// MAME headers
-#include "emu.h"
-#include "osdepend.h"
-#include "ui/ui.h"
-
-// MAMEOS headers
-#include "winmain.h"
-#include "window.h"
-#include "input.h"
-#include "video.h"
-#include "strconv.h"
-#include "config.h"
-
-#include "winutil.h"
-#include <mutex>
-
-//============================================================
-// PARAMETERS
-//============================================================
-
-enum
-{
- POVDIR_LEFT = 0,
- POVDIR_RIGHT,
- POVDIR_UP,
- POVDIR_DOWN
-};
-
-#define MAX_KEYS 256
-
-
-
-//============================================================
-// MACROS
-//============================================================
-
-#define STRUCTSIZE(x) ((dinput_version == 0x0300) ? sizeof(x##_DX3) : sizeof(x))
-
-#ifdef UNICODE
-#define UNICODE_SUFFIX "W"
-#else
-#define UNICODE_SUFFIX "A"
-#endif
-
-
-
-//============================================================
-// TYPEDEFS
-//============================================================
-
-// state information for a keyboard; DirectInput state must be first element
-struct keyboard_state
-{
- UINT8 state[MAX_KEYS];
- INT8 oldkey[MAX_KEYS];
- INT8 currkey[MAX_KEYS];
-};
-
-
-// state information for a mouse; DirectInput state must be first element
-struct mouse_state
-{
- DIMOUSESTATE2 state;
- LONG raw_x, raw_y, raw_z;
-};
-
-
-// state information for a joystick; DirectInput state must be first element
-struct joystick_state
-{
- DIJOYSTATE state;
- LONG rangemin[8];
- LONG rangemax[8];
-};
-
-
-// DirectInput-specific information about a device
-struct dinput_device_info
-{
- LPDIRECTINPUTDEVICE device;
- LPDIRECTINPUTDEVICE2 device2;
- DIDEVCAPS caps;
- LPCDIDATAFORMAT format;
-};
-
-
-// RawInput-specific information about a device
-struct rawinput_device_info
-{
- HANDLE device;
-};
-
-
-// generic device information
-class device_info
-{
-public:
- device_info(running_machine &machine)
- : head(NULL), next(NULL), name(NULL), poll(NULL), device(NULL), m_machine(machine) { }
-
- running_machine &machine() const { return m_machine; }
-
- // device information
- device_info ** head;
- device_info * next;
- const char * name;
- void (*poll)(device_info *info);
-
- // MAME information
- input_device * device;
-
- // device state
- union
- {
- keyboard_state keyboard;
- mouse_state mouse;
- joystick_state joystick;
- };
-
- // DirectInput/RawInput-specific state
- dinput_device_info dinput;
- rawinput_device_info rawinput;
-
-private:
- running_machine & m_machine;
-};
-
-
-// RawInput APIs
-typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_list_ptr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PINT puiNumDevices, IN UINT cbSize);
-typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_data_ptr)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize, IN UINT cbSizeHeader);
-typedef /*WINUSERAPI*/ INT (WINAPI *get_rawinput_device_info_ptr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize);
-typedef /*WINUSERAPI*/ BOOL (WINAPI *register_rawinput_devices_ptr)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
-
-
-
-//============================================================
-// LOCAL VARIABLES
-//============================================================
-
-// global states
-static bool input_enabled;
-static std::mutex input_lock;
-static bool input_paused;
-static DWORD last_poll;
-
-// DirectInput variables
-static LPDIRECTINPUT dinput;
-static int dinput_version;
-
-// RawInput variables
-static get_rawinput_device_list_ptr get_rawinput_device_list;
-static get_rawinput_data_ptr get_rawinput_data;
-static get_rawinput_device_info_ptr get_rawinput_device_info;
-static register_rawinput_devices_ptr register_rawinput_devices;
-static bool global_inputs_enabled;
-
-// keyboard states
-static bool keyboard_win32_reported_key_down;
-static device_info * keyboard_list;
-
-// mouse states
-static bool mouse_enabled;
-static device_info * mouse_list;
-
-// lightgun states
-static UINT8 lightgun_shared_axis_mode;
-static bool lightgun_enabled;
-static device_info * lightgun_list;
-
-// joystick states
-static device_info * joystick_list;
-
-// default axis names
-static const TCHAR *const default_axis_name[] =
-{
- TEXT("X"), TEXT("Y"), TEXT("Z"), TEXT("RX"),
- TEXT("RY"), TEXT("RZ"), TEXT("SL1"), TEXT("SL2")
-};
-
-
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-// device list management
-static void device_list_poll_devices(device_info *devlist_head);
-static void device_list_reset_devices(device_info *devlist_head);
-
-// generic device management
-static device_info *generic_device_alloc(running_machine &machine, device_info **devlist_head_ptr, const TCHAR *name);
-static void generic_device_free(device_info *devinfo);
-static int generic_device_index(device_info *devlist_head, device_info *devinfo);
-static void generic_device_reset(device_info *devinfo);
-static INT32 generic_button_get_state(void *device_internal, void *item_internal);
-static INT32 generic_axis_get_state(void *device_internal, void *item_internal);
-
-// Win32-specific input code
-static void win32_init(running_machine &machine);
-static void win32_exit(running_machine &machine);
-static void win32_keyboard_poll(device_info *devinfo);
-static void win32_lightgun_poll(device_info *devinfo);
-
-// DirectInput-specific code
-static void dinput_init(running_machine &machine);
-static void dinput_exit(running_machine &machine);
-static HRESULT dinput_set_dword_property(LPDIRECTINPUTDEVICE device, REFGUID property_guid, DWORD object, DWORD how, DWORD value);
-static device_info *dinput_device_create(running_machine &machine, device_info **devlist_head_ptr, LPCDIDEVICEINSTANCE instance, LPCDIDATAFORMAT format1, LPCDIDATAFORMAT format2, DWORD cooperative_level);
-static void dinput_device_release(device_info *devinfo);
-static char *dinput_device_item_name(device_info *devinfo, int offset, const TCHAR *defstring, const TCHAR *suffix);
-static HRESULT dinput_device_poll(device_info *devinfo);
-static BOOL CALLBACK dinput_keyboard_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
-static void dinput_keyboard_poll(device_info *devinfo);
-static BOOL CALLBACK dinput_mouse_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
-static void dinput_mouse_poll(device_info *devinfo);
-static BOOL CALLBACK dinput_joystick_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref);
-static void dinput_joystick_poll(device_info *devinfo);
-static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal);
-
-// RawInput-specific code
-static void rawinput_init(running_machine &machine);
-static void rawinput_exit(running_machine &machine);
-static device_info *rawinput_device_create(running_machine &machine, device_info **devlist_head_ptr, PRAWINPUTDEVICELIST device);
-static void rawinput_device_release(device_info *info);
-static TCHAR *rawinput_device_improve_name(TCHAR *name);
-static void rawinput_keyboard_enum(running_machine &machine, PRAWINPUTDEVICELIST device);
-static void rawinput_keyboard_update(HANDLE device, RAWKEYBOARD *data);
-static void rawinput_mouse_enum(running_machine &machine, PRAWINPUTDEVICELIST device);
-static void rawinput_mouse_update(HANDLE device, RAWMOUSE *data);
-static void rawinput_mouse_poll(device_info *devinfo);
-
-// misc utilities
-static TCHAR *reg_query_string(HKEY key, const TCHAR *path);
-static const TCHAR *default_button_name(int which);
-static const TCHAR *default_pov_name(int which);
-
-
-
-//============================================================
-// KEYBOARD/JOYSTICK LIST
-//============================================================
-
-// master keyboard translation table
-struct key_trans_entry {
- input_item_id mame_key;
- INT32 di_key;
- unsigned char virtual_key;
- char ascii_key;
- char const * mame_key_name;
-};
-#define KEY_TRANS_ENTRY(mame, di, virtual, ascii) { ITEM_ID_##mame, DIK_##di, virtual, ascii, "ITEM_ID_"#mame }
-static const key_trans_entry win_key_trans_table[] =
-{
- // MAME key dinput key virtual key ascii
- KEY_TRANS_ENTRY(ESC, ESCAPE, VK_ESCAPE, 27),
- KEY_TRANS_ENTRY(1, 1, '1', '1'),
- KEY_TRANS_ENTRY(2, 2, '2', '2'),
- KEY_TRANS_ENTRY(3, 3, '3', '3'),
- KEY_TRANS_ENTRY(4, 4, '4', '4'),
- KEY_TRANS_ENTRY(5, 5, '5', '5'),
- KEY_TRANS_ENTRY(6, 6, '6', '6'),
- KEY_TRANS_ENTRY(7, 7, '7', '7'),
- KEY_TRANS_ENTRY(8, 8, '8', '8'),
- KEY_TRANS_ENTRY(9, 9, '9', '9'),
- KEY_TRANS_ENTRY(0, 0, '0', '0'),
- KEY_TRANS_ENTRY(MINUS, MINUS, VK_OEM_MINUS, '-'),
- KEY_TRANS_ENTRY(EQUALS, EQUALS, VK_OEM_PLUS, '='),
- KEY_TRANS_ENTRY(BACKSPACE, BACK, VK_BACK, 8),
- KEY_TRANS_ENTRY(TAB, TAB, VK_TAB, 9),
- KEY_TRANS_ENTRY(Q, Q, 'Q', 'Q'),
- KEY_TRANS_ENTRY(W, W, 'W', 'W'),
- KEY_TRANS_ENTRY(E, E, 'E', 'E'),
- KEY_TRANS_ENTRY(R, R, 'R', 'R'),
- KEY_TRANS_ENTRY(T, T, 'T', 'T'),
- KEY_TRANS_ENTRY(Y, Y, 'Y', 'Y'),
- KEY_TRANS_ENTRY(U, U, 'U', 'U'),
- KEY_TRANS_ENTRY(I, I, 'I', 'I'),
- KEY_TRANS_ENTRY(O, O, 'O', 'O'),
- KEY_TRANS_ENTRY(P, P, 'P', 'P'),
- KEY_TRANS_ENTRY(OPENBRACE, LBRACKET, VK_OEM_4, '['),
- KEY_TRANS_ENTRY(CLOSEBRACE, RBRACKET, VK_OEM_6, ']'),
- KEY_TRANS_ENTRY(ENTER, RETURN, VK_RETURN, 13),
- KEY_TRANS_ENTRY(LCONTROL, LCONTROL, VK_LCONTROL, 0),
- KEY_TRANS_ENTRY(A, A, 'A', 'A'),
- KEY_TRANS_ENTRY(S, S, 'S', 'S'),
- KEY_TRANS_ENTRY(D, D, 'D', 'D'),
- KEY_TRANS_ENTRY(F, F, 'F', 'F'),
- KEY_TRANS_ENTRY(G, G, 'G', 'G'),
- KEY_TRANS_ENTRY(H, H, 'H', 'H'),
- KEY_TRANS_ENTRY(J, J, 'J', 'J'),
- KEY_TRANS_ENTRY(K, K, 'K', 'K'),
- KEY_TRANS_ENTRY(L, L, 'L', 'L'),
- KEY_TRANS_ENTRY(COLON, SEMICOLON, VK_OEM_1, ';'),
- KEY_TRANS_ENTRY(QUOTE, APOSTROPHE, VK_OEM_7, '\''),
- KEY_TRANS_ENTRY(TILDE, GRAVE, VK_OEM_3, '`'),
- KEY_TRANS_ENTRY(LSHIFT, LSHIFT, VK_LSHIFT, 0),
- KEY_TRANS_ENTRY(BACKSLASH, BACKSLASH, VK_OEM_5, '\\'),
- KEY_TRANS_ENTRY(BACKSLASH2, OEM_102, VK_OEM_102, '<'),
- KEY_TRANS_ENTRY(Z, Z, 'Z', 'Z'),
- KEY_TRANS_ENTRY(X, X, 'X', 'X'),
- KEY_TRANS_ENTRY(C, C, 'C', 'C'),
- KEY_TRANS_ENTRY(V, V, 'V', 'V'),
- KEY_TRANS_ENTRY(B, B, 'B', 'B'),
- KEY_TRANS_ENTRY(N, N, 'N', 'N'),
- KEY_TRANS_ENTRY(M, M, 'M', 'M'),
- KEY_TRANS_ENTRY(COMMA, COMMA, VK_OEM_COMMA, ','),
- KEY_TRANS_ENTRY(STOP, PERIOD, VK_OEM_PERIOD, '.'),
- KEY_TRANS_ENTRY(SLASH, SLASH, VK_OEM_2, '/'),
- KEY_TRANS_ENTRY(RSHIFT, RSHIFT, VK_RSHIFT, 0),
- KEY_TRANS_ENTRY(ASTERISK, MULTIPLY, VK_MULTIPLY, '*'),
- KEY_TRANS_ENTRY(LALT, LMENU, VK_LMENU, 0),
- KEY_TRANS_ENTRY(SPACE, SPACE, VK_SPACE, ' '),
- KEY_TRANS_ENTRY(CAPSLOCK, CAPITAL, VK_CAPITAL, 0),
- KEY_TRANS_ENTRY(F1, F1, VK_F1, 0),
- KEY_TRANS_ENTRY(F2, F2, VK_F2, 0),
- KEY_TRANS_ENTRY(F3, F3, VK_F3, 0),
- KEY_TRANS_ENTRY(F4, F4, VK_F4, 0),
- KEY_TRANS_ENTRY(F5, F5, VK_F5, 0),
- KEY_TRANS_ENTRY(F6, F6, VK_F6, 0),
- KEY_TRANS_ENTRY(F7, F7, VK_F7, 0),
- KEY_TRANS_ENTRY(F8, F8, VK_F8, 0),
- KEY_TRANS_ENTRY(F9, F9, VK_F9, 0),
- KEY_TRANS_ENTRY(F10, F10, VK_F10, 0),
- KEY_TRANS_ENTRY(NUMLOCK, NUMLOCK, VK_NUMLOCK, 0),
- KEY_TRANS_ENTRY(SCRLOCK, SCROLL, VK_SCROLL, 0),
- KEY_TRANS_ENTRY(7_PAD, NUMPAD7, VK_NUMPAD7, 0),
- KEY_TRANS_ENTRY(8_PAD, NUMPAD8, VK_NUMPAD8, 0),
- KEY_TRANS_ENTRY(9_PAD, NUMPAD9, VK_NUMPAD9, 0),
- KEY_TRANS_ENTRY(MINUS_PAD, SUBTRACT, VK_SUBTRACT, 0),
- KEY_TRANS_ENTRY(4_PAD, NUMPAD4, VK_NUMPAD4, 0),
- KEY_TRANS_ENTRY(5_PAD, NUMPAD5, VK_NUMPAD5, 0),
- KEY_TRANS_ENTRY(6_PAD, NUMPAD6, VK_NUMPAD6, 0),
- KEY_TRANS_ENTRY(PLUS_PAD, ADD, VK_ADD, 0),
- KEY_TRANS_ENTRY(1_PAD, NUMPAD1, VK_NUMPAD1, 0),
- KEY_TRANS_ENTRY(2_PAD, NUMPAD2, VK_NUMPAD2, 0),
- KEY_TRANS_ENTRY(3_PAD, NUMPAD3, VK_NUMPAD3, 0),
- KEY_TRANS_ENTRY(0_PAD, NUMPAD0, VK_NUMPAD0, 0),
- KEY_TRANS_ENTRY(DEL_PAD, DECIMAL, VK_DECIMAL, 0),
- KEY_TRANS_ENTRY(F11, F11, VK_F11, 0),
- KEY_TRANS_ENTRY(F12, F12, VK_F12, 0),
- KEY_TRANS_ENTRY(F13, F13, VK_F13, 0),
- KEY_TRANS_ENTRY(F14, F14, VK_F14, 0),
- KEY_TRANS_ENTRY(F15, F15, VK_F15, 0),
- KEY_TRANS_ENTRY(ENTER_PAD, NUMPADENTER, VK_RETURN, 0),
- KEY_TRANS_ENTRY(RCONTROL, RCONTROL, VK_RCONTROL, 0),
- KEY_TRANS_ENTRY(SLASH_PAD, DIVIDE, VK_DIVIDE, 0),
- KEY_TRANS_ENTRY(PRTSCR, SYSRQ, 0, 0),
- KEY_TRANS_ENTRY(RALT, RMENU, VK_RMENU, 0),
- KEY_TRANS_ENTRY(HOME, HOME, VK_HOME, 0),
- KEY_TRANS_ENTRY(UP, UP, VK_UP, 0),
- KEY_TRANS_ENTRY(PGUP, PRIOR, VK_PRIOR, 0),
- KEY_TRANS_ENTRY(LEFT, LEFT, VK_LEFT, 0),
- KEY_TRANS_ENTRY(RIGHT, RIGHT, VK_RIGHT, 0),
- KEY_TRANS_ENTRY(END, END, VK_END, 0),
- KEY_TRANS_ENTRY(DOWN, DOWN, VK_DOWN, 0),
- KEY_TRANS_ENTRY(PGDN, NEXT, VK_NEXT, 0),
- KEY_TRANS_ENTRY(INSERT, INSERT, VK_INSERT, 0),
- KEY_TRANS_ENTRY(DEL, DELETE, VK_DELETE, 0),
- KEY_TRANS_ENTRY(LWIN, LWIN, VK_LWIN, 0),
- KEY_TRANS_ENTRY(RWIN, RWIN, VK_RWIN, 0),
- KEY_TRANS_ENTRY(MENU, APPS, VK_APPS, 0),
- KEY_TRANS_ENTRY(PAUSE, PAUSE, VK_PAUSE, 0),
- { ITEM_ID_CANCEL, 0, VK_CANCEL, 0, "ITEM_ID_CANCEL" },
-
- // New keys introduced in Windows 2000. These have no MAME codes to
- // preserve compatibility with old config files that may refer to them
- // as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table
- // entries anyway because otherwise they aren't recognized when
- // GetAsyncKeyState polling is used (as happens currently when MAME is
- // paused). Some codes are missing because the mapping to vkey codes
- // isn't clear, and MapVirtualKey is no help.
-
- KEY_TRANS_ENTRY(OTHER_SWITCH, MUTE, VK_VOLUME_MUTE, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, VOLUMEDOWN, VK_VOLUME_DOWN, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, VOLUMEUP, VK_VOLUME_UP, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBHOME, VK_BROWSER_HOME, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBSEARCH, VK_BROWSER_SEARCH, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBFAVORITES, VK_BROWSER_FAVORITES, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBREFRESH, VK_BROWSER_REFRESH, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBSTOP, VK_BROWSER_STOP, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBFORWARD, VK_BROWSER_FORWARD, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, WEBBACK, VK_BROWSER_BACK, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, MAIL, VK_LAUNCH_MAIL, 0),
- KEY_TRANS_ENTRY(OTHER_SWITCH, MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0),
-};
-
-
-//============================================================
-// INLINE FUNCTIONS
-//============================================================
-
-static inline void poll_if_necessary(running_machine &machine)
-{
- // make sure we poll at least once every 1/4 second
- if (GetTickCount() > last_poll + 1000 / 4)
- wininput_poll(machine);
-}
-
-
-static inline input_item_id keyboard_map_scancode_to_itemid(int scancode)
-{
- int tablenum;
-
- // scan the table for a match
- for (tablenum = 0; tablenum < ARRAY_LENGTH(win_key_trans_table); tablenum++)
- if (win_key_trans_table[tablenum].di_key == scancode)
- return (input_item_id)win_key_trans_table[tablenum].mame_key;
-
- // default to an "other" switch
- return ITEM_ID_OTHER_SWITCH;
-}
-
-
-static inline INT32 normalize_absolute_axis(INT32 raw, INT32 rawmin, INT32 rawmax)
-{
- INT32 center = (rawmax + rawmin) / 2;
-
- // make sure we have valid data
- if (rawmin >= rawmax)
- return raw;
-
- // above center
- if (raw >= center)
- {
- INT32 result = (INT64)(raw - center) * (INT64)INPUT_ABSOLUTE_MAX / (INT64)(rawmax - center);
- return MIN(result, INPUT_ABSOLUTE_MAX);
- }
-
- // below center
- else
- {
- INT32 result = -((INT64)(center - raw) * (INT64)-INPUT_ABSOLUTE_MIN / (INT64)(center - rawmin));
- return MAX(result, INPUT_ABSOLUTE_MIN);
- }
-}
-
-
-
-//============================================================
-// input_init
-//============================================================
-
-bool windows_osd_interface::input_init()
-{
- // decode the options
- lightgun_shared_axis_mode = downcast<windows_options &>(machine().options()).dual_lightgun();
-
- // initialize RawInput and DirectInput (RawInput first so we can fall back)
- rawinput_init(machine());
- dinput_init(machine());
- win32_init(machine());
-
- // poll once to get the initial states
- input_enabled = true;
- wininput_poll(machine());
- return true;
-}
-
-
-//============================================================
-// wininput_pause
-//============================================================
-
-void windows_osd_interface::input_pause()
-{
- // keep track of the paused state
- input_paused = true;
-}
-
-void windows_osd_interface::input_resume()
-{
- // keep track of the paused state
- input_paused = false;
-}
-
-
-//============================================================
-// wininput_exit
-//============================================================
-
-void windows_osd_interface::input_exit()
-{
- // acquire the lock and turn off input (this ensures everyone is done)
- std::lock_guard<std::mutex> lock(input_lock);
- input_enabled = false;
-}
-
-
-//============================================================
-// wininput_poll
-//============================================================
-
-void wininput_poll(running_machine &machine)
-{
- // ignore if not enabled
- if (input_enabled)
- {
- // remember when this happened
- last_poll = GetTickCount();
-
- // periodically process events, in case they're not coming through
- // this also will make sure the mouse state is up-to-date
- winwindow_process_events_periodic(machine);
-
- // track if mouse/lightgun is enabled, for mouse hiding purposes
- mouse_enabled = machine.input().device_class(DEVICE_CLASS_MOUSE).enabled();
- lightgun_enabled = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).enabled();
- }
-
- bool polldevices = input_enabled && (global_inputs_enabled || winwindow_has_focus());
-
- // poll all of the devices
- if (polldevices)
- {
- device_list_poll_devices(keyboard_list);
- device_list_poll_devices(mouse_list);
- device_list_poll_devices(lightgun_list);
- device_list_poll_devices(joystick_list);
- }
- else
- {
- device_list_reset_devices(keyboard_list);
- device_list_reset_devices(mouse_list);
- device_list_reset_devices(lightgun_list);
- device_list_reset_devices(joystick_list);
- }
-}
-
-
-//============================================================
-// wininput_should_hide_mouse
-//============================================================
-
-bool wininput_should_hide_mouse(void)
-{
- // if we are paused or disabled, no
- if (input_paused || !input_enabled)
- return false;
-
- // if neither mice nor lightguns enabled in the core, then no
- if (!mouse_enabled && !lightgun_enabled)
- return false;
-
- // if the window has a menu, no
- if (win_window_list != NULL && win_window_list->win_has_menu())
- return false;
-
- // otherwise, yes
- return true;
-}
-
-
-//============================================================
-// wininput_handle_mouse_button
-//============================================================
-
-BOOL wininput_handle_mouse_button(int button, int down, int x, int y)
-{
- device_info *devinfo;
-
- // ignore if not enabled
- if (!input_enabled)
- return FALSE;
-
- // only need this for shared axis hack
- if (!lightgun_shared_axis_mode || button >= 4)
- return FALSE;
-
- // choose a device based on the button
- devinfo = lightgun_list;
- if (button >= 2 && devinfo != NULL)
- {
- button -= 2;
- devinfo = devinfo->next;
- }
-
- // take the lock
- std::lock_guard<std::mutex> lock(input_lock);
-
- // set the button state
- devinfo->mouse.state.rgbButtons[button] = down ? 0x80 : 0x00;
- if (down)
- {
- RECT client_rect;
- POINT mousepos;
-
- // get the position relative to the window
- GetClientRect(win_window_list->m_hwnd, &client_rect);
- mousepos.x = x;
- mousepos.y = y;
- ScreenToClient(win_window_list->m_hwnd, &mousepos);
-
- // convert to absolute coordinates
- devinfo->mouse.state.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
- devinfo->mouse.state.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
- }
- return TRUE;
-}
-
-
-//============================================================
-// wininput_handle_raw
-//============================================================
-
-BOOL wininput_handle_raw(HANDLE device)
-{
- BYTE small_buffer[4096];
- LPBYTE data = small_buffer;
- BOOL result = FALSE;
- int size;
-
- // ignore if not enabled
- if (!input_enabled)
- return result;
-
- // determine the size of databuffer we need
- if ((*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) != 0)
- return result;
-
- // if necessary, allocate a temporary buffer and fetch the data
- if (size > sizeof(small_buffer))
- {
- data = global_alloc_array_nothrow(BYTE, size);
- if (data == NULL)
- return result;
- }
-
- // fetch the data and process the appropriate message types
- result = (*get_rawinput_data)((HRAWINPUT)device, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
- if (result != 0)
- {
- RAWINPUT *input = (RAWINPUT *)data;
-
- // handle keyboard input
- if (input->header.dwType == RIM_TYPEKEYBOARD)
- {
- std::lock_guard<std::mutex> lock(input_lock);
- rawinput_keyboard_update(input->header.hDevice, &input->data.keyboard);
- result = TRUE;
- }
-
- // handle mouse input
- else if (input->header.dwType == RIM_TYPEMOUSE)
- {
- std::lock_guard<std::mutex> lock(input_lock);
- rawinput_mouse_update(input->header.hDevice, &input->data.mouse);
- result = TRUE;
- }
- }
-
- // free the temporary buffer and return the result
- if (data != small_buffer)
- global_free_array(data);
- return result;
-}
-
-
-//============================================================
-// wininput_vkey_for_mame_code
-//============================================================
-
-int wininput_vkey_for_mame_code(input_code code)
-{
- // only works for keyboard switches
- if (code.device_class() == DEVICE_CLASS_KEYBOARD && code.item_class() == ITEM_CLASS_SWITCH)
- {
- input_item_id id = code.item_id();
- int tablenum;
-
- // scan the table for a match
- for (tablenum = 0; tablenum < ARRAY_LENGTH(win_key_trans_table); tablenum++)
- if (win_key_trans_table[tablenum].mame_key == id)
- return win_key_trans_table[tablenum].virtual_key;
- }
- return 0;
-}
-
-
-//============================================================
-// lookup_mame_code
-//============================================================
-
-static int lookup_mame_index(const char *scode)
-{
- for (int i = 0; i < ARRAY_LENGTH(win_key_trans_table); i++)
- {
- if (!strcmp(scode, win_key_trans_table[i].mame_key_name))
- return i;
- }
- return -1;
-}
-
-static input_item_id lookup_mame_code(const char *scode)
-{
- int const index = lookup_mame_index(scode);
- if (index >= 0)
- return win_key_trans_table[index].mame_key;
- else
- return ITEM_ID_INVALID;
-}
-
-
-//============================================================
-// customize_input_type_list
-//============================================================
-
-void windows_osd_interface::customize_input_type_list(simple_list<input_type_entry> &typelist)
-{
- input_type_entry *entry;
- const char* uimode;
-
- // loop over the defaults
- for (entry = typelist.first(); entry != NULL; entry = entry->next())
- switch (entry->type())
- {
- // disable the config menu if the ALT key is down
- // (allows ALT-TAB to switch between windows apps)
- case IPT_UI_CONFIGURE:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_TAB, input_seq::not_code, KEYCODE_LALT, input_seq::not_code, KEYCODE_RALT);
- break;
-
- // configurable UI mode switch
- case IPT_UI_TOGGLE_UI:
- uimode = options().ui_mode_key();
- if (strcmp(uimode,"auto"))
- {
- std::string fullmode = "ITEM_ID_";
- fullmode += uimode;
- input_item_id const mameid_code = lookup_mame_code(fullmode.c_str());
- if (ITEM_ID_INVALID != mameid_code)
- {
- input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code));
- entry->defseq(SEQ_TYPE_STANDARD).set(ui_code);
- }
- }
- break;
-
- // alt-enter for fullscreen
- case IPT_OSD_1:
- entry->configure_osd("TOGGLE_FULLSCREEN", "Toggle Fullscreen");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, KEYCODE_LALT, input_seq::or_code, KEYCODE_ENTER, KEYCODE_RALT);
- break;
-
- // lalt-F12 for fullscreen snap (HLSL)
- case IPT_OSD_2:
- entry->configure_osd("RENDER_SNAP", "Take Rendered Snapshot");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LALT, input_seq::not_code, KEYCODE_LSHIFT);
- break;
- // add a NOT-lalt to our default F12
- case IPT_UI_SNAPSHOT: // emu/input.c: input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT)
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT);
- break;
-
- // lshift-lalt-F12 for fullscreen video (HLSL)
- case IPT_OSD_3:
- entry->configure_osd("RENDER_AVI", "Record Rendered Video");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT);
- break;
- // add a NOT-lalt to our default shift-F12
- case IPT_UI_RECORD_MOVIE: // emu/input.c: input_seq(KEYCODE_F12, KEYCODE_LSHIFT)
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT);
- break;
-
- // add a NOT-lalt to write timecode file
- case IPT_UI_TIMECODE: // emu/input.c: input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT)
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT);
- break;
-
- // lctrl-lalt-F5 to toggle post-processing
- case IPT_OSD_4:
- entry->configure_osd("POST_PROCESS", "Toggle Post-Processing");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LALT, KEYCODE_LCONTROL);
- break;
- // add a NOT-lctrl-lalt to our default F5
- case IPT_UI_TOGGLE_DEBUG: // emu/input.c: input_seq(KEYCODE_F5)
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LALT);
- break;
-
- // leave everything else alone
- default:
- break;
- }
-}
-
-
-//============================================================
-// device_list_poll_devices
-//============================================================
-
-static void device_list_poll_devices(device_info *devlist_head)
-{
- device_info *curdev;
-
- for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
- if (curdev->poll != NULL)
- (*curdev->poll)(curdev);
-}
-
-
-//============================================================
-// device_list_reset_devices
-//============================================================
-
-static void device_list_reset_devices(device_info *devlist_head)
-{
- device_info *curdev;
-
- for (curdev = devlist_head; curdev != NULL; curdev = curdev->next)
- generic_device_reset(curdev);
-}
-
-
-//============================================================
-// generic_device_alloc
-//============================================================
-
-static device_info *generic_device_alloc(running_machine &machine, device_info **devlist_head_ptr, const TCHAR *name)
-{
- device_info **curdev_ptr;
- device_info *devinfo;
-
- // allocate memory for the device object
- devinfo = global_alloc_clear<device_info>(machine);
- devinfo->head = devlist_head_ptr;
-
- // allocate a UTF8 copy of the name
- devinfo->name = utf8_from_tstring(name);
- if (devinfo->name == NULL)
- goto error;
-
- // append us to the list
- for (curdev_ptr = devinfo->head; *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
- *curdev_ptr = devinfo;
-
- return devinfo;
-
-error:
- global_free(devinfo);
- return NULL;
-}
-
-
-//============================================================
-// generic_device_free
-//============================================================
-
-static void generic_device_free(device_info *devinfo)
-{
- device_info **curdev_ptr;
-
- // remove us from the list
- for (curdev_ptr = devinfo->head; *curdev_ptr != devinfo && *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
- if (*curdev_ptr == devinfo)
- *curdev_ptr = devinfo->next;
-
- // free the copy of the name if present
- if (devinfo->name != NULL)
- osd_free((void *)devinfo->name);
- devinfo->name = NULL;
-
- // and now free the info
- global_free(devinfo);
-}
-
-
-//============================================================
-// generic_device_index
-//============================================================
-
-static int generic_device_index(device_info *devlist_head, device_info *devinfo)
-{
- int index = 0;
- while (devlist_head != NULL)
- {
- if (devlist_head == devinfo)
- return index;
- index++;
- devlist_head = devlist_head->next;
- }
- return -1;
-}
-
-
-//============================================================
-// generic_device_reset
-//============================================================
-
-static void generic_device_reset(device_info *devinfo)
-{
- // keyboard case
- if (devinfo->head == &keyboard_list)
- memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
-
- // mouse/lightgun case
- else if (devinfo->head == &mouse_list || devinfo->head == &lightgun_list)
- memset(&devinfo->mouse.state, 0, sizeof(devinfo->mouse.state));
-
- // joystick case
- else if (devinfo->head == &joystick_list)
- {
- int povnum;
-
- memset(&devinfo->joystick.state, 0, sizeof(devinfo->joystick.state));
- for (povnum = 0; povnum < ARRAY_LENGTH(devinfo->joystick.state.rgdwPOV); povnum++)
- devinfo->joystick.state.rgdwPOV[povnum] = 0xffff;
- }
-}
-
-
-//============================================================
-// generic_button_get_state
-//============================================================
-
-static INT32 generic_button_get_state(void *device_internal, void *item_internal)
-{
- device_info *devinfo = (device_info *)device_internal;
- BYTE *itemdata = (BYTE *)item_internal;
-
- // return the current state
- poll_if_necessary(devinfo->machine());
- return *itemdata >> 7;
-}
-
-
-//============================================================
-// generic_axis_get_state
-//============================================================
-
-static INT32 generic_axis_get_state(void *device_internal, void *item_internal)
-{
- device_info *devinfo = (device_info *)device_internal;
- LONG *axisdata = (LONG *)item_internal;
-
- // return the current state
- poll_if_necessary(devinfo->machine());
- return *axisdata;
-}
-
-
-//============================================================
-// win32_init
-//============================================================
-
-static void win32_init(running_machine &machine)
-{
- int gunnum;
-
- // we don't need any initialization unless we are using shared axis mode for lightguns
- if (!lightgun_shared_axis_mode)
- return;
-
- // we need an exit callback
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(win32_exit), &machine));
-
- // allocate two lightgun devices
- for (gunnum = 0; gunnum < 2; gunnum++)
- {
- static const TCHAR *const gun_names[] = { TEXT("Shared Axis Gun 1"), TEXT("Shared Axis Gun 2") };
- device_info *devinfo;
- int axisnum, butnum;
-
- // allocate a device
- devinfo = generic_device_alloc(machine, &lightgun_list, gun_names[gunnum]);
- if (devinfo == NULL)
- break;
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(devinfo->name, devinfo);
-
- // populate the axes
- for (axisnum = 0; axisnum < 2; axisnum++)
- {
- char *name = utf8_from_tstring(default_axis_name[axisnum]);
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
- osd_free(name);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < 2; butnum++)
- {
- char *name = utf8_from_tstring(default_button_name(butnum));
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
- osd_free(name);
- }
- }
-}
-
-
-//============================================================
-// win32_exit
-//============================================================
-
-static void win32_exit(running_machine &machine)
-{
- // skip if we're in shared axis mode
- if (!lightgun_shared_axis_mode)
- return;
-
- // delete the lightgun devices
- while (lightgun_list != NULL)
- generic_device_free(lightgun_list);
-}
-
-
-//============================================================
-// win32_keyboard_poll
-//============================================================
-
-static void win32_keyboard_poll(device_info *devinfo)
-{
- int keynum;
-
- // clear the flag that says we detected a key down via win32
- keyboard_win32_reported_key_down = false;
-
- // reset the keyboard state and then repopulate
- memset(devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
-
- // iterate over keys
- for (keynum = 0; keynum < ARRAY_LENGTH(win_key_trans_table); keynum++)
- {
- int vk = win_key_trans_table[keynum].virtual_key;
- if (vk != 0 && (GetAsyncKeyState(vk) & 0x8000) != 0)
- {
- int dik = win_key_trans_table[keynum].di_key;
-
- // conver the VK code to a scancode (DIK code)
- if (dik != 0)
- devinfo->keyboard.state[dik] = 0x80;
-
- // set this flag so that we continue to use win32 until all keys are up
- keyboard_win32_reported_key_down = true;
- }
- }
-}
-
-
-//============================================================
-// win32_lightgun_poll
-//============================================================
-
-static void win32_lightgun_poll(device_info *devinfo)
-{
- INT32 xpos = 0, ypos = 0;
- POINT mousepos;
-
- // if we are using the shared axis hack, the data is updated via Windows messages only
- if (lightgun_shared_axis_mode)
- return;
-
- // get the cursor position and transform into final results
- GetCursorPos(&mousepos);
- if (win_window_list != NULL)
- {
- RECT client_rect;
-
- // get the position relative to the window
- GetClientRect(win_window_list->m_hwnd, &client_rect);
- ScreenToClient(win_window_list->m_hwnd, &mousepos);
-
- // convert to absolute coordinates
- xpos = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
- ypos = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
- }
-
- // update the X/Y positions
- devinfo->mouse.state.lX = xpos;
- devinfo->mouse.state.lY = ypos;
-}
-
-
-//============================================================
-// dinput_init
-//============================================================
-
-static void dinput_init(running_machine &machine)
-{
- HRESULT result;
-#if DIRECTINPUT_VERSION >= 0x800
- int didevtype_keyboard = DI8DEVCLASS_KEYBOARD;
- int didevtype_mouse = DI8DEVCLASS_POINTER;
- int didevtype_joystick = DI8DEVCLASS_GAMECTRL;
-
- dinput_version = DIRECTINPUT_VERSION;
- result = DirectInput8Create(GetModuleHandleUni(), dinput_version, IID_IDirectInput8, (void **)&dinput, NULL);
- if (result != DI_OK)
- {
- dinput_version = 0;
- return;
- }
-#else
- int didevtype_keyboard = DIDEVTYPE_KEYBOARD;
- int didevtype_mouse = DIDEVTYPE_MOUSE;
- int didevtype_joystick = DIDEVTYPE_JOYSTICK;
-
- // first attempt to initialize DirectInput at the current version
- dinput_version = DIRECTINPUT_VERSION;
- result = DirectInputCreate(GetModuleHandleUni(), dinput_version, &dinput, NULL);
- if (result != DI_OK)
- {
- // if that fails, try version 5
- dinput_version = 0x0500;
- result = DirectInputCreate(GetModuleHandleUni(), dinput_version, &dinput, NULL);
- if (result != DI_OK)
- {
- // if that fails, try version 3
- dinput_version = 0x0300;
- result = DirectInputCreate(GetModuleHandleUni(), dinput_version, &dinput, NULL);
- if (result != DI_OK)
- {
- dinput_version = 0;
- return;
- }
- }
- }
-#endif
-
- osd_printf_verbose("DirectInput: Using DirectInput %d\n", dinput_version >> 8);
-
- // we need an exit callback
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(dinput_exit), &machine));
-
- // initialize keyboard devices, but only if we don't have any yet
- if (keyboard_list == NULL)
- {
- // enumerate the ones we have
- result = IDirectInput_EnumDevices(dinput, didevtype_keyboard, dinput_keyboard_enum, &machine, DIEDFL_ATTACHEDONLY);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", (UINT32)result);
- }
-
- // initialize mouse & lightgun devices, but only if we don't have any yet
- if (mouse_list == NULL)
- {
- // enumerate the ones we have
- result = IDirectInput_EnumDevices(dinput, didevtype_mouse, dinput_mouse_enum, &machine, DIEDFL_ATTACHEDONLY);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate mice (result=%08X)\n", (UINT32)result);
- }
-
- // initialize joystick devices
- result = IDirectInput_EnumDevices(dinput, didevtype_joystick, dinput_joystick_enum, &machine, DIEDFL_ATTACHEDONLY);
- if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate joysticks (result=%08X)\n", (UINT32)result);
-}
-
-
-//============================================================
-// dinput_exit
-//============================================================
-
-static void dinput_exit(running_machine &machine)
-{
- // release all our devices
- while (joystick_list != NULL && joystick_list->dinput.device != NULL)
- dinput_device_release(joystick_list);
- while (lightgun_list != NULL)
- generic_device_free(lightgun_list);
- while (mouse_list != NULL && mouse_list->dinput.device != NULL)
- dinput_device_release(mouse_list);
- while (keyboard_list != NULL && keyboard_list->dinput.device != NULL)
- dinput_device_release(keyboard_list);
-
- // release DirectInput
- if (dinput != NULL)
- IDirectInput_Release(dinput);
- dinput = NULL;
-}
-
-
-//============================================================
-// dinput_set_dword_property
-//============================================================
-
-static HRESULT dinput_set_dword_property(LPDIRECTINPUTDEVICE device, REFGUID property_guid, DWORD object, DWORD how, DWORD value)
-{
- DIPROPDWORD dipdw;
-
- dipdw.diph.dwSize = sizeof(dipdw);
- dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
- dipdw.diph.dwObj = object;
- dipdw.diph.dwHow = how;
- dipdw.dwData = value;
-
- return IDirectInputDevice_SetProperty(device, property_guid, &dipdw.diph);
-}
-
-
-//============================================================
-// dinput_device_create
-//============================================================
-
-static device_info *dinput_device_create(running_machine &machine, device_info **devlist_head_ptr, LPCDIDEVICEINSTANCE instance, LPCDIDATAFORMAT format1, LPCDIDATAFORMAT format2, DWORD cooperative_level)
-{
- device_info *devinfo;
- HRESULT result;
-
- // allocate memory for the device object
- devinfo = generic_device_alloc(machine, devlist_head_ptr, instance->tszInstanceName);
-
- // attempt to create a device
- result = IDirectInput_CreateDevice(dinput, WRAP_REFIID(instance->guidInstance), &devinfo->dinput.device, NULL);
- if (result != DI_OK)
- goto error;
-
- // try to get a version 2 device for it
- result = IDirectInputDevice_QueryInterface(devinfo->dinput.device, WRAP_REFIID(IID_IDirectInputDevice2), (void **)&devinfo->dinput.device2);
- if (result != DI_OK)
- devinfo->dinput.device2 = NULL;
-
- // get the caps
- devinfo->dinput.caps.dwSize = STRUCTSIZE(DIDEVCAPS);
- result = IDirectInputDevice_GetCapabilities(devinfo->dinput.device, &devinfo->dinput.caps);
- if (result != DI_OK)
- goto error;
-
- // attempt to set the data format
- devinfo->dinput.format = format1;
- result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device, devinfo->dinput.format);
- if (result != DI_OK)
- {
- // use the secondary format if available
- if (format2 != NULL)
- {
- devinfo->dinput.format = format2;
- result = IDirectInputDevice_SetDataFormat(devinfo->dinput.device, devinfo->dinput.format);
- }
- if (result != DI_OK)
- goto error;
- }
-
- // set the cooperative level
- result = IDirectInputDevice_SetCooperativeLevel(devinfo->dinput.device, win_window_list->m_hwnd, cooperative_level);
- if (result != DI_OK)
- goto error;
- return devinfo;
-
-error:
- dinput_device_release(devinfo);
- return NULL;
-}
-
-
-//============================================================
-// dinput_device_release
-//============================================================
-
-static void dinput_device_release(device_info *devinfo)
-{
- // release the version 2 device if present
- if (devinfo->dinput.device2 != NULL)
- IDirectInputDevice_Release(devinfo->dinput.device2);
- devinfo->dinput.device2 = NULL;
-
- // release the regular device if present
- if (devinfo->dinput.device != NULL)
- IDirectInputDevice_Release(devinfo->dinput.device);
- devinfo->dinput.device = NULL;
-
- // free the item list
- generic_device_free(devinfo);
-}
-
-
-//============================================================
-// dinput_device_item_name
-//============================================================
-
-static char *dinput_device_item_name(device_info *devinfo, int offset, const TCHAR *defstring, const TCHAR *suffix)
-{
- DIDEVICEOBJECTINSTANCE instance = { 0 };
- const TCHAR *namestring = instance.tszName;
- TCHAR *combined;
- HRESULT result;
- char *utf8;
-
- // query the key name
- instance.dwSize = STRUCTSIZE(DIDEVICEOBJECTINSTANCE);
- result = IDirectInputDevice_GetObjectInfo(devinfo->dinput.device, &instance, offset, DIPH_BYOFFSET);
-
- // if we got an error and have no default string, just return NULL
- if (result != DI_OK)
- {
- if (defstring == NULL)
- return NULL;
- namestring = defstring;
- }
-
- // if no suffix, return as-is
- if (suffix == NULL)
- return utf8_from_tstring(namestring);
-
- // otherwise, allocate space to add the suffix
- combined = global_alloc_array(TCHAR, _tcslen(namestring) + 1 + _tcslen(suffix) + 1);
- _tcscpy(combined, namestring);
- _tcscat(combined, TEXT(" "));
- _tcscat(combined, suffix);
-
- // convert to UTF8, free the temporary string, and return
- utf8 = utf8_from_tstring(combined);
- global_free_array(combined);
- return utf8;
-}
-
-
-//============================================================
-// dinput_device_poll
-//============================================================
-
-static HRESULT dinput_device_poll(device_info *devinfo)
-{
- HRESULT result;
-
- // first poll the device, then get the state
- if (devinfo->dinput.device2 != NULL)
- IDirectInputDevice2_Poll(devinfo->dinput.device2);
- result = IDirectInputDevice_GetDeviceState(devinfo->dinput.device, devinfo->dinput.format->dwDataSize, &devinfo->joystick.state);
-
- // handle lost inputs here
- if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
- {
- result = IDirectInputDevice_Acquire(devinfo->dinput.device);
- if (result == DI_OK)
- result = IDirectInputDevice_GetDeviceState(devinfo->dinput.device, devinfo->dinput.format->dwDataSize, &devinfo->joystick.state);
- }
-
- return result;
-}
-
-
-//============================================================
-// dinput_keyboard_enum
-//============================================================
-
-static BOOL CALLBACK dinput_keyboard_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
-{
- running_machine &machine = *(running_machine *)ref;
- device_info *devinfo;
- int keynum;
-
- // allocate and link in a new device
- devinfo = dinput_device_create(machine, &keyboard_list, instance, &c_dfDIKeyboard, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
- if (devinfo == NULL)
- goto exit;
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
- devinfo->poll = dinput_keyboard_poll;
-
- // populate it
- for (keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
- TCHAR defname[20];
- char *name;
-
- // generate/fetch the name
- _sntprintf(defname, ARRAY_LENGTH(defname), TEXT("Scan%03d"), keynum);
- name = dinput_device_item_name(devinfo, keynum, defname, NULL);
-
- // add the item to the device
- devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
- osd_free(name);
- }
-
-exit:
- return DIENUM_CONTINUE;
-}
-
-
-//============================================================
-// dinput_keyboard_poll
-//============================================================
-
-static void dinput_keyboard_poll(device_info *devinfo)
-{
- HRESULT result = dinput_device_poll(devinfo);
-
- // for the first device, if we errored, or if we previously reported win32 keys,
- // then ignore the dinput state and poll using win32
- if (devinfo == keyboard_list && (result != DI_OK || keyboard_win32_reported_key_down))
- win32_keyboard_poll(devinfo);
-}
-
-
-//============================================================
-// dinput_mouse_enum
-//============================================================
-
-static BOOL CALLBACK dinput_mouse_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
-{
- device_info *devinfo, *guninfo = NULL;
- running_machine &machine = *(running_machine *)ref;
- int axisnum, butnum;
- HRESULT result;
-
- // allocate and link in a new device
- devinfo = dinput_device_create(machine, &mouse_list, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
- if (devinfo == NULL)
- goto exit;
-
- // allocate a second device for the gun (unless we are using the shared axis mode)
- // we only support a single gun in dinput mode, so only add one
- if (!lightgun_shared_axis_mode && devinfo == mouse_list)
- {
- guninfo = generic_device_alloc(machine, &lightgun_list, instance->tszInstanceName);
- if (guninfo == NULL)
- goto exit;
- }
-
- // set relative mode on the mouse device
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_REL);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- {
- osd_printf_error("DirectInput: Unable to set relative mode for mouse %d (%s)\n", generic_device_index(mouse_list, devinfo), devinfo->name);
- goto error;
- }
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name, devinfo);
- devinfo->poll = dinput_mouse_poll;
- if (guninfo != NULL)
- {
- guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
- guninfo->poll = win32_lightgun_poll;
- }
-
- // cap the number of axes and buttons based on the format
- devinfo->dinput.caps.dwAxes = MIN(devinfo->dinput.caps.dwAxes, 3);
- devinfo->dinput.caps.dwButtons = MIN(devinfo->dinput.caps.dwButtons, (devinfo->dinput.format == &c_dfDIMouse) ? 4 : 8);
-
- // populate the axes
- for (axisnum = 0; axisnum < devinfo->dinput.caps.dwAxes; axisnum++)
- {
- char *name = dinput_device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
-
- // add to the mouse device and optionally to the gun device as well
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
- if (guninfo != NULL && axisnum < 2)
- guninfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &guninfo->mouse.state.lX + axisnum);
-
- osd_free(name);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
- {
- FPTR offset = (FPTR)(&((DIMOUSESTATE *)NULL)->rgbButtons[butnum]);
- char *name = dinput_device_item_name(devinfo, offset, default_button_name(butnum), NULL);
-
- // add to the mouse device and optionally to the gun device as well
- // note that the gun device points to the mouse buttons rather than its own
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
- if (guninfo != NULL)
- guninfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
-
- osd_free(name);
- }
-
-exit:
- return DIENUM_CONTINUE;
-
-error:
- if (guninfo != NULL)
- generic_device_free(guninfo);
- if (devinfo != NULL)
- dinput_device_release(devinfo);
- goto exit;
-}
-
-
-//============================================================
-// dinput_mouse_poll
-//============================================================
-
-static void dinput_mouse_poll(device_info *devinfo)
-{
- // poll
- dinput_device_poll(devinfo);
-
- // scale the axis data
- devinfo->mouse.state.lX *= INPUT_RELATIVE_PER_PIXEL;
- devinfo->mouse.state.lY *= INPUT_RELATIVE_PER_PIXEL;
- devinfo->mouse.state.lZ *= INPUT_RELATIVE_PER_PIXEL;
-}
-
-
-//============================================================
-// dinput_joystick_enum
-//============================================================
-
-static BOOL CALLBACK dinput_joystick_enum(LPCDIDEVICEINSTANCE instance, LPVOID ref)
-{
- DWORD cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
- int axisnum, axiscount, povnum, butnum;
- running_machine &machine = *(running_machine *)ref;
- device_info *devinfo;
- HRESULT result;
-
- if (win_window_list != NULL && win_window_list->win_has_menu()) {
- cooperative_level = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
- }
- // allocate and link in a new device
- devinfo = dinput_device_create(machine, &joystick_list, instance, &c_dfDIJoystick, NULL, cooperative_level);
- if (devinfo == NULL)
- goto exit;
-
- // set absolute mode
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_AXISMODE, 0, DIPH_DEVICE, DIPROPAXISMODE_ABS);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to set absolute mode for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
-
- // turn off deadzone; we do our own calculations
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_DEADZONE, 0, DIPH_DEVICE, 0);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to reset deadzone for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
-
- // turn off saturation; we do our own calculations
- result = dinput_set_dword_property(devinfo->dinput.device, DIPROP_SATURATION, 0, DIPH_DEVICE, 10000);
- if (result != DI_OK && result != DI_PROPNOEFFECT)
- osd_printf_warning("DirectInput: Unable to reset saturation for joystick %d (%s)\n", generic_device_index(joystick_list, devinfo), devinfo->name);
-
- // cap the number of axes, POVs, and buttons based on the format
- devinfo->dinput.caps.dwAxes = MIN(devinfo->dinput.caps.dwAxes, 8);
- devinfo->dinput.caps.dwPOVs = MIN(devinfo->dinput.caps.dwPOVs, 4);
- devinfo->dinput.caps.dwButtons = MIN(devinfo->dinput.caps.dwButtons, 128);
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_JOYSTICK).add_device(devinfo->name, devinfo);
- devinfo->poll = dinput_joystick_poll;
-
- // populate the axes
- for (axisnum = axiscount = 0; axiscount < devinfo->dinput.caps.dwAxes && axisnum < 8; axisnum++)
- {
- DIPROPRANGE dipr;
- char *name;
-
- // fetch the range of this axis
- dipr.diph.dwSize = sizeof(dipr);
- dipr.diph.dwHeaderSize = sizeof(dipr.diph);
- dipr.diph.dwObj = offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG);
- dipr.diph.dwHow = DIPH_BYOFFSET;
- result = IDirectInputDevice_GetProperty(devinfo->dinput.device, DIPROP_RANGE, &dipr.diph);
- if (result != DI_OK)
- continue;
- devinfo->joystick.rangemin[axisnum] = dipr.lMin;
- devinfo->joystick.rangemax[axisnum] = dipr.lMax;
-
- // populate the item description as well
- name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->joystick.state.lX + axisnum);
- osd_free(name);
-
- axiscount++;
- }
-
- // populate the POVs
- for (povnum = 0; povnum < devinfo->dinput.caps.dwPOVs; povnum++)
- {
- char *name;
-
- // left
- name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("L"));
- devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_LEFT));
- osd_free(name);
-
- // right
- name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("R"));
- devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_RIGHT));
- osd_free(name);
-
- // up
- name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("U"));
- devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_UP));
- osd_free(name);
-
- // down
- name = dinput_device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("D"));
- devinfo->device->add_item(name, ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_DOWN));
- osd_free(name);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
- {
- FPTR offset = (FPTR)(&((DIJOYSTATE2 *)NULL)->rgbButtons[butnum]);
- char *name = dinput_device_item_name(devinfo, offset, default_button_name(butnum), NULL);
-
- input_item_id itemid;
-
- if (butnum < INPUT_MAX_BUTTONS)
- itemid = (input_item_id) (ITEM_ID_BUTTON1 + butnum);
- else if (butnum < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
- itemid = (input_item_id) (ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + butnum);
- else
- itemid = ITEM_ID_OTHER_SWITCH;
-
- devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->joystick.state.rgbButtons[butnum]);
- osd_free(name);
- }
-
-exit:
- return DIENUM_CONTINUE;
-}
-
-
-//============================================================
-// dinput_joystick_poll
-//============================================================
-
-static void dinput_joystick_poll(device_info *devinfo)
-{
- int axisnum;
-
- // poll the device first
- dinput_device_poll(devinfo);
-
- // normalize axis values
- for (axisnum = 0; axisnum < 8; axisnum++)
- {
- LONG *axis = (&devinfo->joystick.state.lX) + axisnum;
- *axis = normalize_absolute_axis(*axis, devinfo->joystick.rangemin[axisnum], devinfo->joystick.rangemax[axisnum]);
- }
-}
-
-
-//============================================================
-// dinput_joystick_pov_get_state
-//============================================================
-
-static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
-{
- device_info *devinfo = (device_info *)device_internal;
- int povnum = (FPTR)item_internal / 4;
- int povdir = (FPTR)item_internal % 4;
- INT32 result = 0;
- DWORD pov;
-
- // get the current state
- poll_if_necessary(devinfo->machine());
- pov = devinfo->joystick.state.rgdwPOV[povnum];
-
- // if invalid, return 0
- if ((pov & 0xffff) == 0xffff)
- return result;
-
- // return the current state
- switch (povdir)
- {
- case POVDIR_LEFT: result = (pov >= 22500 && pov <= 31500); break;
- case POVDIR_RIGHT: result = (pov >= 4500 && pov <= 13500); break;
- case POVDIR_UP: result = (pov >= 31500 || pov <= 4500); break;
- case POVDIR_DOWN: result = (pov >= 13500 && pov <= 22500); break;
- }
- return result;
-}
-
-
-//============================================================
-// rawinput_init
-//============================================================
-
-static void rawinput_init(running_machine &machine)
-{
- RAWINPUTDEVICELIST *devlist = NULL;
- int device_count, devnum, regcount;
- RAWINPUTDEVICE reglist[2];
- HMODULE user32;
-
- // we need pause and exit callbacks
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(rawinput_exit), &machine));
-
- // look in user32 for the raw input APIs
- user32 = LoadLibrary(TEXT("user32.dll"));
- if (user32 == NULL)
- goto error;
-
- // look up the entry points
- register_rawinput_devices = (register_rawinput_devices_ptr)GetProcAddress(user32, "RegisterRawInputDevices");
- get_rawinput_device_list = (get_rawinput_device_list_ptr)GetProcAddress(user32, "GetRawInputDeviceList");
- get_rawinput_device_info = (get_rawinput_device_info_ptr)GetProcAddress(user32, "GetRawInputDeviceInfo" UNICODE_SUFFIX);
- get_rawinput_data = (get_rawinput_data_ptr)GetProcAddress(user32, "GetRawInputData");
- if (register_rawinput_devices == NULL || get_rawinput_device_list == NULL || get_rawinput_device_info == NULL || get_rawinput_data == NULL)
- goto error;
- osd_printf_verbose("RawInput: APIs detected\n");
-
- // get the number of devices, allocate a device list, and fetch it
- if ((*get_rawinput_device_list)(NULL, &device_count, sizeof(*devlist)) != 0)
- goto error;
- if (device_count == 0)
- goto error;
- devlist = global_alloc_array(RAWINPUTDEVICELIST, device_count);
- if ((*get_rawinput_device_list)(devlist, &device_count, sizeof(*devlist)) == -1)
- goto error;
-
- // iterate backwards through devices; new devices are added at the head
- for (devnum = device_count - 1; devnum >= 0; devnum--)
- {
- RAWINPUTDEVICELIST *device = &devlist[devnum];
-
- // handle keyboards
- if (!FORCE_DIRECTINPUT && device->dwType == RIM_TYPEKEYBOARD)
- rawinput_keyboard_enum(machine, device);
-
- // handle mice
- else if (!FORCE_DIRECTINPUT && device->dwType == RIM_TYPEMOUSE)
- rawinput_mouse_enum(machine, device);
- }
-
- // don't enable global inputs when testing direct input or debugging
- if (!FORCE_DIRECTINPUT && !machine.options().debug())
- {
- global_inputs_enabled = downcast<windows_options &>(machine.options()).global_inputs();
- }
-
- // finally, register to receive raw input WM_INPUT messages
- regcount = 0;
- if (keyboard_list != NULL)
- {
- reglist[regcount].usUsagePage = 0x01;
- reglist[regcount].usUsage = 0x06;
-
- if (global_inputs_enabled)
- {
- reglist[regcount].dwFlags = 0x00000100;
- }
- else
- {
- reglist[regcount].dwFlags = 0;
- }
-
- reglist[regcount].hwndTarget = win_window_list->m_hwnd;
- regcount++;
- }
- if (mouse_list != NULL)
- {
- reglist[regcount].usUsagePage = 0x01;
- reglist[regcount].usUsage = 0x02;
-
- if (global_inputs_enabled)
- {
- reglist[regcount].dwFlags = 0x00000100;
- }
- else
- {
- reglist[regcount].dwFlags = 0;
- }
-
- reglist[regcount].hwndTarget = win_window_list->m_hwnd;
- regcount++;
- }
-
- // if the registration fails, we need to back off
- if (regcount > 0)
- if (!(*register_rawinput_devices)(reglist, regcount, sizeof(reglist[0])))
- goto error;
-
- global_free_array(devlist);
- return;
-
-error:
- if (devlist != NULL)
- global_free_array(devlist);
-}
-
-
-//============================================================
-// rawinput_exit
-//============================================================
-
-static void rawinput_exit(running_machine &machine)
-{
- // release all our devices
- while (lightgun_list != NULL && lightgun_list->rawinput.device != NULL)
- rawinput_device_release(lightgun_list);
- while (mouse_list != NULL && mouse_list->rawinput.device != NULL)
- rawinput_device_release(mouse_list);
- while (keyboard_list != NULL && keyboard_list->rawinput.device != NULL)
- rawinput_device_release(keyboard_list);
-}
-
-
-//============================================================
-// rawinput_device_create
-//============================================================
-
-static device_info *rawinput_device_create(running_machine &machine, device_info **devlist_head_ptr, PRAWINPUTDEVICELIST device)
-{
- device_info *devinfo = NULL;
- TCHAR *tname = NULL;
- INT name_length = 0;
-
- // determine the length of the device name, allocate it, and fetch it if not nameless
- if ((*get_rawinput_device_info)(device->hDevice, RIDI_DEVICENAME, NULL, &name_length) != 0)
- goto error;
- tname = global_alloc_array_clear<TCHAR>(name_length+1);
- if (name_length > 1 && (*get_rawinput_device_info)(device->hDevice, RIDI_DEVICENAME, tname, &name_length) == -1)
- goto error;
-
- // if this is an RDP name, skip it
- if (_tcsstr(tname, TEXT("Root#RDP_")) != NULL)
- goto error;
-
- // improve the name and then allocate a device
- tname = rawinput_device_improve_name(tname);
- devinfo = generic_device_alloc(machine, devlist_head_ptr, tname);
- global_free_array(tname);
-
- // copy the handle
- devinfo->rawinput.device = device->hDevice;
- return devinfo;
-
-error:
- if (tname != NULL)
- global_free_array(tname);
- if (devinfo != NULL)
- rawinput_device_release(devinfo);
- return NULL;
-}
-
-
-//============================================================
-// rawinput_device_release
-//============================================================
-
-static void rawinput_device_release(device_info *devinfo)
-{
- // free the item list
- generic_device_free(devinfo);
-}
-
-
-//============================================================
-// rawinput_device_improve_name
-//============================================================
-
-static TCHAR *rawinput_device_improve_name(TCHAR *name)
-{
- static const TCHAR usbbasepath[] = TEXT("SYSTEM\\CurrentControlSet\\Enum\\USB");
- static const TCHAR basepath[] = TEXT("SYSTEM\\CurrentControlSet\\Enum\\");
- TCHAR *regstring = NULL;
- TCHAR *parentid = NULL;
- TCHAR *regpath = NULL;
- const TCHAR *chsrc;
- HKEY regkey = NULL;
- int usbindex;
- TCHAR *chdst;
- LONG result;
-
- // The RAW name received is formatted as:
- // \??\type-id#hardware-id#instance-id#{DeviceClasses-id}
- // XP starts with "\??\"
- // Vista64 starts with "\\?\"
-
- // ensure the name is something we can handle
- if (_tcsncmp(name, TEXT("\\\\?\\"), 4) != 0 && _tcsncmp(name, TEXT("\\??\\"), 4) != 0)
- return name;
-
- // allocate a temporary string and concatenate the base path plus the name
- regpath = global_alloc_array(TCHAR, _tcslen(basepath) + 1 + _tcslen(name));
- _tcscpy(regpath, basepath);
- chdst = regpath + _tcslen(regpath);
-
- // convert all # to \ in the name
- for (chsrc = name + 4; *chsrc != 0; chsrc++)
- *chdst++ = (*chsrc == '#') ? '\\' : *chsrc;
- *chdst = 0;
-
- // remove the final chunk
- chdst = _tcsrchr(regpath, '\\');
- if (chdst == NULL)
- goto exit;
- *chdst = 0;
-
- // now try to open the registry key
- result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &regkey);
- if (result != ERROR_SUCCESS)
- goto exit;
-
- // fetch the device description; if it exists, we are finished
- regstring = reg_query_string(regkey, TEXT("DeviceDesc"));
- if (regstring != NULL)
- goto convert;
-
- // close this key
- RegCloseKey(regkey);
- regkey = NULL;
-
- // if the key name does not contain "HID", it's not going to be in the USB tree; give up
- if (_tcsstr(regpath, TEXT("HID")) == NULL)
- goto exit;
-
- // extract the expected parent ID from the regpath
- parentid = _tcsrchr(regpath, '\\');
- if (parentid == NULL)
- goto exit;
- parentid++;
-
- // open the USB key
- result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, usbbasepath, 0, KEY_READ, &regkey);
- if (result != ERROR_SUCCESS)
- goto exit;
-
- // enumerate the USB key
- for (usbindex = 0; result == ERROR_SUCCESS && regstring == NULL; usbindex++)
- {
- TCHAR keyname[MAX_PATH];
- DWORD namelen;
-
- // get the next enumerated subkey and scan it
- namelen = ARRAY_LENGTH(keyname) - 1;
- result = RegEnumKeyEx(regkey, usbindex, keyname, &namelen, NULL, NULL, NULL, NULL);
- if (result == ERROR_SUCCESS)
- {
- LONG subresult;
- int subindex;
- HKEY subkey;
-
- // open the subkey
- subresult = RegOpenKeyEx(regkey, keyname, 0, KEY_READ, &subkey);
- if (subresult != ERROR_SUCCESS)
- continue;
-
- // enumerate the subkey
- for (subindex = 0; subresult == ERROR_SUCCESS && regstring == NULL; subindex++)
- {
- // get the next enumerated subkey and scan it
- namelen = ARRAY_LENGTH(keyname) - 1;
- subresult = RegEnumKeyEx(subkey, subindex, keyname, &namelen, NULL, NULL, NULL, NULL);
- if (subresult == ERROR_SUCCESS)
- {
- TCHAR *endparentid;
- LONG endresult;
- HKEY endkey;
-
- // open this final key
- endresult = RegOpenKeyEx(subkey, keyname, 0, KEY_READ, &endkey);
- if (endresult != ERROR_SUCCESS)
- continue;
-
- // do we have a match?
- endparentid = reg_query_string(endkey, TEXT("ParentIdPrefix"));
- if (endparentid != NULL && _tcsncmp(parentid, endparentid, _tcslen(endparentid)) == 0)
- regstring = reg_query_string(endkey, TEXT("DeviceDesc"));
-
- // free memory and close the key
- if (endparentid != NULL)
- global_free_array(endparentid);
- RegCloseKey(endkey);
- }
- }
-
- // close the subkey
- RegCloseKey(subkey);
- }
- }
-
- // if we didn't find anything, go to the exit
- if (regstring == NULL)
- goto exit;
-
-convert:
- // replace the name with the nicer one
- global_free_array(name);
-
- // remove anything prior to the final semicolon
- chsrc = _tcsrchr(regstring, ';');
- if (chsrc != NULL)
- chsrc++;
- else
- chsrc = regstring;
- name = global_alloc_array(TCHAR, _tcslen(chsrc) + 1);
- _tcscpy(name, chsrc);
-
-exit:
- if (regstring != NULL)
- global_free_array(regstring);
- if (regpath != NULL)
- global_free_array(regpath);
- if (regkey != NULL)
- RegCloseKey(regkey);
-
- return name;
-}
-
-
-//============================================================
-// rawinput_keyboard_enum
-//============================================================
-
-static void rawinput_keyboard_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
-{
- device_info *devinfo;
- int keynum;
-
- // allocate and link in a new device
- devinfo = rawinput_device_create(machine, &keyboard_list, device);
- if (devinfo == NULL)
- return;
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name, devinfo);
-
- // populate it
- for (keynum = 0; keynum < MAX_KEYS; keynum++)
- {
- input_item_id itemid = keyboard_map_scancode_to_itemid(keynum);
- TCHAR keyname[100];
- char *name;
-
- // generate the name
- if (GetKeyNameText(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, ARRAY_LENGTH(keyname)) == 0)
- _sntprintf(keyname, ARRAY_LENGTH(keyname), TEXT("Scan%03d"), keynum);
- name = utf8_from_tstring(keyname);
-
- // add the item to the device
- devinfo->device->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
- osd_free(name);
- }
-}
-
-
-//============================================================
-// rawinput_keyboard_update
-//============================================================
-
-static void rawinput_keyboard_update(HANDLE device, RAWKEYBOARD *data)
-{
- device_info *devinfo;
-
- // find the keyboard in the list and process
- for (devinfo = keyboard_list; devinfo != NULL; devinfo = devinfo->next)
- if (devinfo->rawinput.device == device)
- {
- // determine the full DIK-compatible scancode
- UINT8 scancode = (data->MakeCode & 0x7f) | ((data->Flags & RI_KEY_E0) ? 0x80 : 0x00);
-
- // scancode 0xaa is a special shift code we need to ignore
- if (scancode == 0xaa)
- break;
-
- // set or clear the key
- if (!(data->Flags & RI_KEY_BREAK))
- devinfo->keyboard.state[scancode] = 0x80;
- else
- devinfo->keyboard.state[scancode] = 0x00;
- break;
- }
-}
-
-
-//============================================================
-// rawinput_mouse_enum
-//============================================================
-
-static void rawinput_mouse_enum(running_machine &machine, PRAWINPUTDEVICELIST device)
-{
- device_info *devinfo, *guninfo = NULL;
- int axisnum, butnum;
-
- // allocate and link in a new mouse device
- devinfo = rawinput_device_create(machine, &mouse_list, device);
- if (devinfo == NULL)
- return;
- devinfo->poll = rawinput_mouse_poll;
-
- // allocate a second device for the gun (unless we are using the shared axis mode)
- if (!lightgun_shared_axis_mode)
- {
- guninfo = rawinput_device_create(machine, &lightgun_list, device);
- assert(guninfo != NULL);
- }
-
- // add the device
- devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name, devinfo);
- if (guninfo != NULL)
- {
- guninfo->device = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).add_device(guninfo->name, guninfo);
- guninfo->poll = NULL;
- }
-
- // populate the axes
- for (axisnum = 0; axisnum < 3; axisnum++)
- {
- char *name = utf8_from_tstring(default_axis_name[axisnum]);
-
- // add to the mouse device and optionally to the gun device as well
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.state.lX + axisnum);
- if (guninfo != NULL && axisnum < 2)
- guninfo->device->add_item(name, (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &guninfo->mouse.state.lX + axisnum);
-
- osd_free(name);
- }
-
- // populate the buttons
- for (butnum = 0; butnum < 5; butnum++)
- {
- char *name = utf8_from_tstring(default_button_name(butnum));
-
- // add to the mouse device and optionally to the gun device as well
- devinfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.state.rgbButtons[butnum]);
- if (guninfo != NULL)
- guninfo->device->add_item(name, (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &guninfo->mouse.state.rgbButtons[butnum]);
-
- osd_free(name);
- }
-}
-
-
-//============================================================
-// rawinput_mouse_update
-//============================================================
-
-static void rawinput_mouse_update(HANDLE device, RAWMOUSE *data)
-{
- device_info *devlist = (data->usFlags & MOUSE_MOVE_ABSOLUTE) ? lightgun_list : mouse_list;
- device_info *devinfo;
-
- // find the mouse in the list and process
- for (devinfo = devlist; devinfo != NULL; devinfo = devinfo->next)
- if (devinfo->rawinput.device == device)
- {
- // if we got relative data, update it as a mouse
- if (!(data->usFlags & MOUSE_MOVE_ABSOLUTE))
- {
- devinfo->mouse.raw_x += data->lLastX * INPUT_RELATIVE_PER_PIXEL;
- devinfo->mouse.raw_y += data->lLastY * INPUT_RELATIVE_PER_PIXEL;
-
- // update zaxis
- if (data->usButtonFlags & RI_MOUSE_WHEEL)
- devinfo->mouse.raw_z += (INT16)data->usButtonData * INPUT_RELATIVE_PER_PIXEL;
- }
-
- // otherwise, update it as a lightgun
- else
- {
- devinfo->mouse.state.lX = normalize_absolute_axis(data->lLastX, 0, 0xffff);
- devinfo->mouse.state.lY = normalize_absolute_axis(data->lLastY, 0, 0xffff);
- }
-
- // update the button states; always update the corresponding mouse buttons
- if (data->usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) devinfo->mouse.state.rgbButtons[0] = 0x80;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_1_UP) devinfo->mouse.state.rgbButtons[0] = 0x00;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) devinfo->mouse.state.rgbButtons[1] = 0x80;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_2_UP) devinfo->mouse.state.rgbButtons[1] = 0x00;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) devinfo->mouse.state.rgbButtons[2] = 0x80;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_3_UP) devinfo->mouse.state.rgbButtons[2] = 0x00;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) devinfo->mouse.state.rgbButtons[3] = 0x80;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_4_UP) devinfo->mouse.state.rgbButtons[3] = 0x00;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) devinfo->mouse.state.rgbButtons[4] = 0x80;
- if (data->usButtonFlags & RI_MOUSE_BUTTON_5_UP) devinfo->mouse.state.rgbButtons[4] = 0x00;
- break;
- }
-}
-
-
-//============================================================
-// rawinput_mouse_poll
-//============================================================
-
-static void rawinput_mouse_poll(device_info *devinfo)
-{
- poll_if_necessary(devinfo->machine());
-
- // copy the accumulated raw state to the actual state
- std::lock_guard<std::mutex> lock(input_lock);
- devinfo->mouse.state.lX = devinfo->mouse.raw_x;
- devinfo->mouse.state.lY = devinfo->mouse.raw_y;
- devinfo->mouse.state.lZ = devinfo->mouse.raw_z;
- devinfo->mouse.raw_x = 0;
- devinfo->mouse.raw_y = 0;
- devinfo->mouse.raw_z = 0;
-}
-
-
-//============================================================
-// reg_query_string
-//============================================================
-
-static TCHAR *reg_query_string(HKEY key, const TCHAR *path)
-{
- TCHAR *buffer;
- DWORD datalen;
- LONG result;
-
- // first query to get the length
- result = RegQueryValueEx(key, path, NULL, NULL, NULL, &datalen);
- if (result != ERROR_SUCCESS)
- return NULL;
-
- // allocate a buffer
- buffer = global_alloc_array(TCHAR, datalen + sizeof(*buffer));
- buffer[datalen / sizeof(*buffer)] = 0;
-
- // now get the actual data
- result = RegQueryValueEx(key, path, NULL, NULL, (LPBYTE)buffer, &datalen);
- if (result == ERROR_SUCCESS)
- return buffer;
-
- // otherwise return a NULL buffer
- global_free_array(buffer);
- return NULL;
-}
-
-
-//============================================================
-// default_button_name
-//============================================================
-
-static const TCHAR *default_button_name(int which)
-{
- static TCHAR buffer[20];
- _sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("B%d"), which);
- return buffer;
-}
-
-
-//============================================================
-// default_pov_name
-//============================================================
-
-static const TCHAR *default_pov_name(int which)
-{
- static TCHAR buffer[20];
- _sntprintf(buffer, ARRAY_LENGTH(buffer), TEXT("POV%d"), which);
- return buffer;
-}