summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Miodrag Milanović <mmicko@gmail.com>2016-02-29 08:38:51 +0100
committer Miodrag Milanović <mmicko@gmail.com>2016-02-29 08:38:51 +0100
commitdc5fa11dcc8177f453d096ecaa4d1ceb35a9a2c0 (patch)
tree787b15e9ede433565ec6029b834aed333ec4539f
parent36413a3656d863739f10568b4c48049e0822fa3f (diff)
parentf68ad66131ab9767f97b77b37111bf1f8a3522c2 (diff)
Merge pull request #661 from bradhugh/topics/input_modules
Rewrite input routines as modules [Brad Hughes]
-rw-r--r--scripts/src/osd/modules.lua13
-rw-r--r--scripts/src/osd/sdl.lua2
-rw-r--r--scripts/src/osd/windows.lua1
-rw-r--r--src/osd/modules/debugger/debugwin.cpp7
-rw-r--r--src/osd/modules/input/input_common.cpp266
-rw-r--r--src/osd/modules/input/input_common.h605
-rw-r--r--src/osd/modules/input/input_dinput.cpp683
-rw-r--r--src/osd/modules/input/input_module.h39
-rw-r--r--src/osd/modules/input/input_none.cpp66
-rw-r--r--src/osd/modules/input/input_rawinput.cpp649
-rw-r--r--src/osd/modules/input/input_sdl.cpp843
-rw-r--r--src/osd/modules/input/input_sdlcommon.cpp283
-rw-r--r--src/osd/modules/input/input_sdlcommon.h204
-rw-r--r--src/osd/modules/input/input_win32.cpp427
-rw-r--r--src/osd/modules/input/input_windows.cpp144
-rw-r--r--src/osd/modules/input/input_windows.h83
-rw-r--r--src/osd/modules/input/input_x11.cpp605
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp87
-rw-r--r--src/osd/modules/lib/osdobj_common.h5
-rw-r--r--src/osd/sdl/input.cpp2128
-rw-r--r--src/osd/sdl/input.h28
-rw-r--r--src/osd/sdl/osdsdl.h10
-rw-r--r--src/osd/sdl/sdlmain.cpp2
-rw-r--r--src/osd/sdl/video.cpp9
-rw-r--r--src/osd/sdl/window.cpp31
-rw-r--r--src/osd/windows/input.cpp2255
-rw-r--r--src/osd/windows/input.h14
-rw-r--r--src/osd/windows/video.cpp2
-rw-r--r--src/osd/windows/window.cpp82
-rw-r--r--src/osd/windows/winmain.h33
30 files changed, 5130 insertions, 4476 deletions
diff --git a/scripts/src/osd/modules.lua b/scripts/src/osd/modules.lua
index ccd997c6a98..6be181c46a8 100644
--- a/scripts/src/osd/modules.lua
+++ b/scripts/src/osd/modules.lua
@@ -69,6 +69,19 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/modules/sound/sdl_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/xaudio2_sound.cpp",
MAME_DIR .. "src/osd/modules/sound/none.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_module.h",
+ MAME_DIR .. "src/osd/modules/input/input_common.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_common.h",
+ MAME_DIR .. "src/osd/modules/input/input_dinput.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_none.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_rawinput.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_win32.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_sdl.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_sdlcommon.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_sdlcommon.h",
+ MAME_DIR .. "src/osd/modules/input/input_x11.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_windows.cpp",
+ MAME_DIR .. "src/osd/modules/input/input_windows.h",
}
if _OPTIONS["targetos"]=="windows" then
diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua
index 9b5ffb195d8..5a64013ffdf 100644
--- a/scripts/src/osd/sdl.lua
+++ b/scripts/src/osd/sdl.lua
@@ -425,8 +425,6 @@ project ("osd_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/sdl/sdlprefix.h",
MAME_DIR .. "src/osd/sdl/sdlmain.cpp",
MAME_DIR .. "src/osd/osdepend.h",
- MAME_DIR .. "src/osd/sdl/input.cpp",
- MAME_DIR .. "src/osd/sdl/input.h",
MAME_DIR .. "src/osd/sdl/video.cpp",
MAME_DIR .. "src/osd/sdl/video.h",
MAME_DIR .. "src/osd/sdl/window.cpp",
diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua
index 154d4732bc1..059c46ccbb4 100644
--- a/scripts/src/osd/windows.lua
+++ b/scripts/src/osd/windows.lua
@@ -163,7 +163,6 @@ project ("osd_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/modules/render/drawgdi.h",
MAME_DIR .. "src/osd/modules/render/drawnone.cpp",
MAME_DIR .. "src/osd/modules/render/drawnone.h",
- MAME_DIR .. "src/osd/windows/input.cpp",
MAME_DIR .. "src/osd/windows/input.h",
MAME_DIR .. "src/osd/windows/output.cpp",
MAME_DIR .. "src/osd/windows/output.h",
diff --git a/src/osd/modules/debugger/debugwin.cpp b/src/osd/modules/debugger/debugwin.cpp
index b31d12ea67a..634332899c3 100644
--- a/src/osd/modules/debugger/debugwin.cpp
+++ b/src/osd/modules/debugger/debugwin.cpp
@@ -25,7 +25,8 @@
#include "debugger.h"
#include "window.h"
-#include "../../windows/input.h"
+#include "../input/input_common.h"
+#include "../input/input_windows.h"
class debugger_windows : public osd_module, public debug_module, protected debugger_windows_interface
@@ -121,7 +122,7 @@ void debugger_windows::wait_for_debugger(device_t &device, bool firststop)
show_all();
// run input polling to ensure that our status is in sync
- wininput_poll(*m_machine);
+ downcast<windows_osd_interface&>(machine().osd()).poll_input(*m_machine);
// get and process messages
MSG message;
@@ -202,7 +203,7 @@ bool debugger_windows::seq_pressed() const
else
{
// handle everything else as a series of ANDs
- int const vkey = wininput_vkey_for_mame_code(code);
+ int const vkey = keyboard_trans_table::instance().vkey_for_mame_code(code);
bool const pressed = (vkey != 0) && ((GetAsyncKeyState(vkey) & 0x8000) != 0);
if (first) // if this is the first in the sequence, result is set equal
diff --git a/src/osd/modules/input/input_common.cpp b/src/osd/modules/input/input_common.cpp
new file mode 100644
index 00000000000..c3d6367da5f
--- /dev/null
+++ b/src/osd/modules/input/input_common.cpp
@@ -0,0 +1,266 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_common.cpp - Common code for all MAME input modules
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+#include "modules/lib/osdobj_common.h"
+
+#include <mutex>
+#include <memory>
+
+// MAME headers
+#include "emu.h"
+
+// winnt.h defines this
+#ifdef DELETE
+#undef DELETE
+#endif
+
+#include "input_common.h"
+
+//============================================================
+// Keyboard translation table
+//============================================================
+
+#if defined(OSD_WINDOWS)
+#include <windows.h>
+#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, ascii, UI) { ITEM_ID_##mame, KEY_ ## disc, virtual, ascii, "ITEM_ID_"#mame, (char *) UI }
+#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, ascii) { ITEM_ID_##mame, KEY_ ## disc, virtual, ascii, "ITEM_ID_"#mame, (char*) #mame }
+#else
+// SDL include
+#include <sdlinc.h>
+#define KEY_TRANS_ENTRY0(mame, sdlsc, sdlkey, disc, virtual, ascii, UI) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, SDLK_ ## sdlkey, ascii, "ITEM_ID_"#mame, (char *) UI }
+#define KEY_TRANS_ENTRY1(mame, sdlsc, sdlkey, disc, virtual, ascii) { ITEM_ID_##mame, SDL_SCANCODE_ ## sdlsc, SDLK_ ## sdlkey, ascii, "ITEM_ID_"#mame, (char*) #mame }
+#endif
+
+key_trans_entry keyboard_trans_table::s_default_table[] =
+{
+ // MAME key sdl scancode sdl key di scancode virtual key ascii ui
+ KEY_TRANS_ENTRY0(ESC, ESCAPE, ESCAPE, ESCAPE, VK_ESCAPE, 27, "ESCAPE"),
+ KEY_TRANS_ENTRY1(1, 1, 1, 1, '1', '1'),
+ KEY_TRANS_ENTRY1(2, 2, 2, 2, '2', '2'),
+ KEY_TRANS_ENTRY1(3, 3, 3, 3, '3', '3'),
+ KEY_TRANS_ENTRY1(4, 4, 4, 4, '4', '4'),
+ KEY_TRANS_ENTRY1(5, 5, 5, 5, '5', '5'),
+ KEY_TRANS_ENTRY1(6, 6, 6, 6, '6', '6'),
+ KEY_TRANS_ENTRY1(7, 7, 7, 7, '7', '7'),
+ KEY_TRANS_ENTRY1(8, 8, 8, 8, '8', '8'),
+ KEY_TRANS_ENTRY1(9, 9, 9, 9, '9', '9'),
+ KEY_TRANS_ENTRY1(0, 0, 0, 0, '0', '0'),
+ KEY_TRANS_ENTRY1(MINUS, MINUS, MINUS, MINUS, VK_OEM_MINUS, '-'),
+ KEY_TRANS_ENTRY1(EQUALS, EQUALS, EQUALS, EQUALS, VK_OEM_PLUS, '='),
+ KEY_TRANS_ENTRY1(BACKSPACE, BACKSPACE, BACKSPACE, BACK, VK_BACK, 8),
+ KEY_TRANS_ENTRY1(TAB, TAB, TAB, TAB, VK_TAB, 9),
+ KEY_TRANS_ENTRY1(Q, Q, q, Q, 'Q', 'Q'),
+ KEY_TRANS_ENTRY1(W, W, w, W, 'W', 'W'),
+ KEY_TRANS_ENTRY1(E, E, e, E, 'E', 'E'),
+ KEY_TRANS_ENTRY1(R, R, r, R, 'R', 'R'),
+ KEY_TRANS_ENTRY1(T, T, t, T, 'T', 'T'),
+ KEY_TRANS_ENTRY1(Y, Y, y, Y, 'Y', 'Y'),
+ KEY_TRANS_ENTRY1(U, U, u, U, 'U', 'U'),
+ KEY_TRANS_ENTRY1(I, I, i, I, 'I', 'I'),
+ KEY_TRANS_ENTRY1(O, O, o, O, 'O', 'O'),
+ KEY_TRANS_ENTRY1(P, P, p, P, 'P', 'P'),
+ KEY_TRANS_ENTRY1(OPENBRACE, LEFTBRACKET, LEFTBRACKET, LBRACKET, VK_OEM_4, '['),
+ KEY_TRANS_ENTRY1(CLOSEBRACE, RIGHTBRACKET, RIGHTBRACKET, RBRACKET, VK_OEM_6, ']'),
+ KEY_TRANS_ENTRY0(ENTER, RETURN, RETURN, RETURN, VK_RETURN, 13, "RETURN"),
+ KEY_TRANS_ENTRY1(LCONTROL, LCTRL, LCTRL, LCONTROL, VK_LCONTROL, 0),
+ KEY_TRANS_ENTRY1(A, A, a, A, 'A', 'A'),
+ KEY_TRANS_ENTRY1(S, S, s, S, 'S', 'S'),
+ KEY_TRANS_ENTRY1(D, D, d, D, 'D', 'D'),
+ KEY_TRANS_ENTRY1(F, F, f, F, 'F', 'F'),
+ KEY_TRANS_ENTRY1(G, G, g, G, 'G', 'G'),
+ KEY_TRANS_ENTRY1(H, H, h, H, 'H', 'H'),
+ KEY_TRANS_ENTRY1(J, J, j, J, 'J', 'J'),
+ KEY_TRANS_ENTRY1(K, K, k, K, 'K', 'K'),
+ KEY_TRANS_ENTRY1(L, L, l, L, 'L', 'L'),
+ KEY_TRANS_ENTRY1(COLON, SEMICOLON, SEMICOLON, SEMICOLON, VK_OEM_1, ';'),
+ KEY_TRANS_ENTRY1(QUOTE, APOSTROPHE, QUOTE, APOSTROPHE, VK_OEM_7, '\''),
+ KEY_TRANS_ENTRY1(TILDE, GRAVE, BACKQUOTE, GRAVE, VK_OEM_3, '`'),
+ KEY_TRANS_ENTRY1(LSHIFT, LSHIFT, LSHIFT, LSHIFT, VK_LSHIFT, 0),
+ KEY_TRANS_ENTRY1(BACKSLASH, BACKSLASH, BACKSLASH, BACKSLASH, VK_OEM_5, '\\'),
+ KEY_TRANS_ENTRY1(BACKSLASH2, 0, 0, OEM_102, VK_OEM_102, '<'),
+ KEY_TRANS_ENTRY1(Z, Z, z, Z, 'Z', 'Z'),
+ KEY_TRANS_ENTRY1(X, X, x, X, 'X', 'X'),
+ KEY_TRANS_ENTRY1(C, C, c, C, 'C', 'C'),
+ KEY_TRANS_ENTRY1(V, V, v, V, 'V', 'V'),
+ KEY_TRANS_ENTRY1(B, B, b, B, 'B', 'B'),
+ KEY_TRANS_ENTRY1(N, N, n, N, 'N', 'N'),
+ KEY_TRANS_ENTRY1(M, M, m, M, 'M', 'M'),
+ KEY_TRANS_ENTRY1(COMMA, COMMA, COMMA, COMMA, VK_OEM_COMMA, ','),
+ KEY_TRANS_ENTRY1(STOP, PERIOD, PERIOD, PERIOD, VK_OEM_PERIOD, '.'),
+ KEY_TRANS_ENTRY1(SLASH, SLASH, SLASH, SLASH, VK_OEM_2, '/'),
+ KEY_TRANS_ENTRY1(RSHIFT, RSHIFT, RSHIFT, RSHIFT, VK_RSHIFT, 0),
+ KEY_TRANS_ENTRY1(ASTERISK, KP_MULTIPLY, KP_MULTIPLY, MULTIPLY, VK_MULTIPLY, '*'),
+ KEY_TRANS_ENTRY1(LALT, LALT, LALT, LMENU, VK_LMENU, 0),
+ KEY_TRANS_ENTRY1(SPACE, SPACE, SPACE, SPACE, VK_SPACE, ' '),
+ KEY_TRANS_ENTRY1(CAPSLOCK, CAPSLOCK, CAPSLOCK, CAPITAL, VK_CAPITAL, 0),
+ KEY_TRANS_ENTRY1(F1, F1, F1, F1, VK_F1, 0),
+ KEY_TRANS_ENTRY1(F2, F2, F2, F2, VK_F2, 0),
+ KEY_TRANS_ENTRY1(F3, F3, F3, F3, VK_F3, 0),
+ KEY_TRANS_ENTRY1(F4, F4, F4, F4, VK_F4, 0),
+ KEY_TRANS_ENTRY1(F5, F5, F5, F5, VK_F5, 0),
+ KEY_TRANS_ENTRY1(F6, F6, F6, F6, VK_F6, 0),
+ KEY_TRANS_ENTRY1(F7, F7, F7, F7, VK_F7, 0),
+ KEY_TRANS_ENTRY1(F8, F8, F8, F8, VK_F8, 0),
+ KEY_TRANS_ENTRY1(F9, F9, F9, F9, VK_F9, 0),
+ KEY_TRANS_ENTRY1(F10, F10, F10, F10, VK_F10, 0),
+ KEY_TRANS_ENTRY1(NUMLOCK, NUMLOCKCLEAR, NUMLOCKCLEAR, NUMLOCK, VK_NUMLOCK, 0),
+ KEY_TRANS_ENTRY1(SCRLOCK, SCROLLLOCK, SCROLLLOCK, SCROLL, VK_SCROLL, 0),
+ KEY_TRANS_ENTRY1(7_PAD, KP_7, KP_7, NUMPAD7, VK_NUMPAD7, 0),
+ KEY_TRANS_ENTRY1(8_PAD, KP_8, KP_8, NUMPAD8, VK_NUMPAD8, 0),
+ KEY_TRANS_ENTRY1(9_PAD, KP_9, KP_9, NUMPAD9, VK_NUMPAD9, 0),
+ KEY_TRANS_ENTRY1(MINUS_PAD, KP_MINUS, KP_MINUS, SUBTRACT, VK_SUBTRACT, 0),
+ KEY_TRANS_ENTRY1(4_PAD, KP_4, KP_4, NUMPAD4, VK_NUMPAD4, 0),
+ KEY_TRANS_ENTRY1(5_PAD, KP_5, KP_5, NUMPAD5, VK_NUMPAD5, 0),
+ KEY_TRANS_ENTRY1(6_PAD, KP_6, KP_6, NUMPAD6, VK_NUMPAD6, 0),
+ KEY_TRANS_ENTRY1(PLUS_PAD, KP_PLUS, KP_PLUS, ADD, VK_ADD, 0),
+ KEY_TRANS_ENTRY1(1_PAD, KP_1, KP_1, NUMPAD1, VK_NUMPAD1, 0),
+ KEY_TRANS_ENTRY1(2_PAD, KP_2, KP_2, NUMPAD2, VK_NUMPAD2, 0),
+ KEY_TRANS_ENTRY1(3_PAD, KP_3, KP_3, NUMPAD3, VK_NUMPAD3, 0),
+ KEY_TRANS_ENTRY1(0_PAD, KP_0, KP_0, NUMPAD0, VK_NUMPAD0, 0),
+ KEY_TRANS_ENTRY1(DEL_PAD, KP_PERIOD, KP_PERIOD, DECIMAL, VK_DECIMAL, 0),
+ KEY_TRANS_ENTRY1(F11, F11, F11, F11, VK_F11, 0),
+ KEY_TRANS_ENTRY1(F12, F12, F12, F12, VK_F12, 0),
+ KEY_TRANS_ENTRY1(F13, F13, F13, F13, VK_F13, 0),
+ KEY_TRANS_ENTRY1(F14, F14, F14, F14, VK_F14, 0),
+ KEY_TRANS_ENTRY1(F15, F15, F15, F15, VK_F15, 0),
+ KEY_TRANS_ENTRY1(ENTER_PAD, KP_ENTER, KP_ENTER, NUMPADENTER, VK_RETURN, 0),
+ KEY_TRANS_ENTRY1(RCONTROL, RCTRL, RCTRL, RCONTROL, VK_RCONTROL, 0),
+ KEY_TRANS_ENTRY1(SLASH_PAD, KP_DIVIDE, KP_DIVIDE, DIVIDE, VK_DIVIDE, 0),
+ KEY_TRANS_ENTRY1(PRTSCR, PRINTSCREEN, PRINTSCREEN, SYSRQ, 0, 0),
+ KEY_TRANS_ENTRY1(RALT, RALT, RALT, RMENU, VK_RMENU, 0),
+ KEY_TRANS_ENTRY1(HOME, HOME, HOME, HOME, VK_HOME, 0),
+ KEY_TRANS_ENTRY1(UP, UP, UP, UP, VK_UP, 0),
+ KEY_TRANS_ENTRY1(PGUP, PAGEUP, PAGEUP, PRIOR, VK_PRIOR, 0),
+ KEY_TRANS_ENTRY1(LEFT, LEFT, LEFT, LEFT, VK_LEFT, 0),
+ KEY_TRANS_ENTRY1(RIGHT, RIGHT, RIGHT, RIGHT, VK_RIGHT, 0),
+ KEY_TRANS_ENTRY1(END, END, END, END, VK_END, 0),
+ KEY_TRANS_ENTRY1(DOWN, DOWN, DOWN, DOWN, VK_DOWN, 0),
+ KEY_TRANS_ENTRY1(PGDN, PAGEDOWN, PAGEDOWN, NEXT, VK_NEXT, 0),
+ KEY_TRANS_ENTRY1(INSERT, INSERT, INSERT, INSERT, VK_INSERT, 0),
+ KEY_TRANS_ENTRY0(DEL, DELETE, DELETE, DELETE, VK_DELETE, 0, "DELETE"),
+ KEY_TRANS_ENTRY1(LWIN, LGUI, LGUI, LWIN, VK_LWIN, 0),
+ KEY_TRANS_ENTRY1(RWIN, RGUI, RGUI, RWIN, VK_RWIN, 0),
+ KEY_TRANS_ENTRY1(MENU, MENU, MENU, APPS, VK_APPS, 0),
+ KEY_TRANS_ENTRY1(PAUSE, PAUSE, PAUSE, PAUSE, VK_PAUSE, 0),
+ KEY_TRANS_ENTRY0(CANCEL, UNKNOWN, UNKNOWN, UNKNOWN, 0, 0, "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_ENTRY1(OTHER_SWITCH, MUTE, MUTE, MUTE, VK_VOLUME_MUTE, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, VOLUMEDOWN, VOLUMEDOWN, VOLUMEDOWN, VK_VOLUME_DOWN, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, VOLUMEUP, VOLUMEUP, VOLUMEUP, VK_VOLUME_UP, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_HOME, AC_HOME, WEBHOME, VK_BROWSER_HOME, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_SEARCH, AC_SEARCH, WEBSEARCH, VK_BROWSER_SEARCH, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_BOOKMARKS, AC_BOOKMARKS, WEBFAVORITES, VK_BROWSER_FAVORITES, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_REFRESH, AC_REFRESH, WEBREFRESH, VK_BROWSER_REFRESH, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_STOP, AC_STOP, WEBSTOP, VK_BROWSER_STOP, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_FORWARD, AC_FORWARD, WEBFORWARD, VK_BROWSER_FORWARD, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, AC_BACK, AC_BACK, WEBBACK, VK_BROWSER_BACK, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, MAIL, MAIL, MAIL, VK_LAUNCH_MAIL, 0),
+ KEY_TRANS_ENTRY1(OTHER_SWITCH, MEDIASELECT, MEDIASELECT, MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0),
+ KEY_TRANS_ENTRY0(INVALID, UNKNOWN, UNKNOWN, ESCAPE, 0, 0, "INVALID")
+};
+
+// The private constructor to create the default instance
+keyboard_trans_table::keyboard_trans_table()
+{
+ m_table = s_default_table;
+ m_table_size = ARRAY_LENGTH(s_default_table);
+}
+
+// public constructor to allow creation of non-default instances
+keyboard_trans_table::keyboard_trans_table(std::unique_ptr<key_trans_entry[]> entries, unsigned int size)
+{
+ m_custom_table = std::move(entries);
+ m_table = m_custom_table.get();
+ m_table_size = size;
+}
+
+int keyboard_trans_table::lookup_mame_index(const char *scode)
+{
+ for (int i = 0; i < m_table_size; i++)
+ {
+ if (!strcmp(scode, m_table[i].mame_key_name))
+ return i;
+ }
+ return -1;
+}
+
+input_item_id keyboard_trans_table::lookup_mame_code(const char *scode)
+{
+ int const index = lookup_mame_index(scode);
+ if (index >= 0)
+ return m_table[index].mame_key;
+ else
+ return ITEM_ID_INVALID;
+}
+
+// Windows specific lookup methods
+#if defined(OSD_WINDOWS)
+
+input_item_id keyboard_trans_table::map_di_scancode_to_itemid(int scancode)
+{
+ int tablenum;
+
+ // scan the table for a match
+ for (tablenum = 0; tablenum < m_table_size; tablenum++)
+ if (m_table[tablenum].scan_code == scancode)
+ return m_table[tablenum].mame_key;
+
+ // default to an "other" switch
+ return ITEM_ID_OTHER_SWITCH;
+}
+
+//============================================================
+// wininput_vkey_for_mame_code
+//============================================================
+
+int keyboard_trans_table::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 < m_table_size; tablenum++)
+ if (m_table[tablenum].mame_key == id)
+ return m_table[tablenum].virtual_key;
+ }
+ return 0;
+}
+
+#endif
+
+
+int input_module_base::init(const osd_options &options)
+{
+ m_options = &options;
+
+ m_mouse_enabled = options.mouse();
+ m_lightgun_enabled = options.lightgun();
+
+ int result = init_internal();
+ if (result != 0)
+ return result;
+
+ m_input_paused = false;
+ m_input_enabled = true;
+
+ return 0;
+} \ No newline at end of file
diff --git a/src/osd/modules/input/input_common.h b/src/osd/modules/input/input_common.h
new file mode 100644
index 00000000000..23d9c958c8c
--- /dev/null
+++ b/src/osd/modules/input/input_common.h
@@ -0,0 +1,605 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_common.h - Common code for all MAME input modules
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#ifndef INPUT_COMMON_H_
+#define INPUT_COMMON_H_
+
+#include <memory>
+#include <chrono>
+#include <string>
+#include <queue>
+
+//============================================================
+// PARAMETERS
+//============================================================
+
+enum
+{
+ POVDIR_LEFT = 0,
+ POVDIR_RIGHT,
+ POVDIR_UP,
+ POVDIR_DOWN
+};
+
+#define MAX_KEYS 256
+#define MAX_AXES 32
+#define MAX_BUTTONS 32
+#define MAX_HATS 8
+#define MAX_POV 4
+
+/****************************************************************************
+* DirectInput compatible keyboard scan codes
+****************************************************************************/
+#define KEY_UNKNOWN 0x00
+#define KEY_ESCAPE 0x01
+#define KEY_1 0x02
+#define KEY_2 0x03
+#define KEY_3 0x04
+#define KEY_4 0x05
+#define KEY_5 0x06
+#define KEY_6 0x07
+#define KEY_7 0x08
+#define KEY_8 0x09
+#define KEY_9 0x0A
+#define KEY_0 0x0B
+#define KEY_MINUS 0x0C /* - on main keyboard */
+#define KEY_EQUALS 0x0D
+#define KEY_BACK 0x0E /* backspace */
+#define KEY_TAB 0x0F
+#define KEY_Q 0x10
+#define KEY_W 0x11
+#define KEY_E 0x12
+#define KEY_R 0x13
+#define KEY_T 0x14
+#define KEY_Y 0x15
+#define KEY_U 0x16
+#define KEY_I 0x17
+#define KEY_O 0x18
+#define KEY_P 0x19
+#define KEY_LBRACKET 0x1A
+#define KEY_RBRACKET 0x1B
+#define KEY_RETURN 0x1C /* Enter on main keyboard */
+#define KEY_LCONTROL 0x1D
+#define KEY_A 0x1E
+#define KEY_S 0x1F
+#define KEY_D 0x20
+#define KEY_F 0x21
+#define KEY_G 0x22
+#define KEY_H 0x23
+#define KEY_J 0x24
+#define KEY_K 0x25
+#define KEY_L 0x26
+#define KEY_SEMICOLON 0x27
+#define KEY_APOSTROPHE 0x28
+#define KEY_GRAVE 0x29 /* accent grave */
+#define KEY_LSHIFT 0x2A
+#define KEY_BACKSLASH 0x2B
+#define KEY_Z 0x2C
+#define KEY_X 0x2D
+#define KEY_C 0x2E
+#define KEY_V 0x2F
+#define KEY_B 0x30
+#define KEY_N 0x31
+#define KEY_M 0x32
+#define KEY_COMMA 0x33
+#define KEY_PERIOD 0x34 /* . on main keyboard */
+#define KEY_SLASH 0x35 /* / on main keyboard */
+#define KEY_RSHIFT 0x36
+#define KEY_MULTIPLY 0x37 /* * on numeric keypad */
+#define KEY_LMENU 0x38 /* left Alt */
+#define KEY_SPACE 0x39
+#define KEY_CAPITAL 0x3A
+#define KEY_F1 0x3B
+#define KEY_F2 0x3C
+#define KEY_F3 0x3D
+#define KEY_F4 0x3E
+#define KEY_F5 0x3F
+#define KEY_F6 0x40
+#define KEY_F7 0x41
+#define KEY_F8 0x42
+#define KEY_F9 0x43
+#define KEY_F10 0x44
+#define KEY_NUMLOCK 0x45
+#define KEY_SCROLL 0x46 /* Scroll Lock */
+#define KEY_NUMPAD7 0x47
+#define KEY_NUMPAD8 0x48
+#define KEY_NUMPAD9 0x49
+#define KEY_SUBTRACT 0x4A /* - on numeric keypad */
+#define KEY_NUMPAD4 0x4B
+#define KEY_NUMPAD5 0x4C
+#define KEY_NUMPAD6 0x4D
+#define KEY_ADD 0x4E /* + on numeric keypad */
+#define KEY_NUMPAD1 0x4F
+#define KEY_NUMPAD2 0x50
+#define KEY_NUMPAD3 0x51
+#define KEY_NUMPAD0 0x52
+#define KEY_DECIMAL 0x53 /* . on numeric keypad */
+#define KEY_OEM_102 0x56 /* <> or \| on RT 102-key keyboard (Non-U.S.) */
+#define KEY_F11 0x57
+#define KEY_F12 0x58
+#define KEY_F13 0x64 /* (NEC PC98) */
+#define KEY_F14 0x65 /* (NEC PC98) */
+#define KEY_F15 0x66 /* (NEC PC98) */
+#define KEY_KANA 0x70 /* (Japanese keyboard) */
+#define KEY_ABNT_C1 0x73 /* /? on Brazilian keyboard */
+#define KEY_CONVERT 0x79 /* (Japanese keyboard) */
+#define KEY_NOCONVERT 0x7B /* (Japanese keyboard) */
+#define KEY_YEN 0x7D /* (Japanese keyboard) */
+#define KEY_ABNT_C2 0x7E /* Numpad . on Brazilian keyboard */
+#define KEY_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */
+#define KEY_PREVTRACK 0x90 /* Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) */
+#define KEY_AT 0x91 /* (NEC PC98) */
+#define KEY_COLON 0x92 /* (NEC PC98) */
+#define KEY_UNDERLINE 0x93 /* (NEC PC98) */
+#define KEY_KANJI 0x94 /* (Japanese keyboard) */
+#define KEY_STOP 0x95 /* (NEC PC98) */
+#define KEY_AX 0x96 /* (Japan AX) */
+#define KEY_UNLABELED 0x97 /* (J3100) */
+#define KEY_NEXTTRACK 0x99 /* Next Track */
+#define KEY_NUMPADENTER 0x9C /* Enter on numeric keypad */
+#define KEY_RCONTROL 0x9D
+#define KEY_MUTE 0xA0 /* Mute */
+#define KEY_CALCULATOR 0xA1 /* Calculator */
+#define KEY_PLAYPAUSE 0xA2 /* Play / Pause */
+#define KEY_MEDIASTOP 0xA4 /* Media Stop */
+#define KEY_VOLUMEDOWN 0xAE /* Volume - */
+#define KEY_VOLUMEUP 0xB0 /* Volume + */
+#define KEY_WEBHOME 0xB2 /* Web home */
+#define KEY_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */
+#define KEY_DIVIDE 0xB5 /* / on numeric keypad */
+#define KEY_SYSRQ 0xB7
+#define KEY_RMENU 0xB8 /* right Alt */
+#define KEY_PAUSE 0xC5 /* Pause */
+#define KEY_HOME 0xC7 /* Home on arrow keypad */
+#define KEY_UP 0xC8 /* UpArrow on arrow keypad */
+#define KEY_PRIOR 0xC9 /* PgUp on arrow keypad */
+#define KEY_LEFT 0xCB /* LeftArrow on arrow keypad */
+#define KEY_RIGHT 0xCD /* RightArrow on arrow keypad */
+#define KEY_END 0xCF /* End on arrow keypad */
+#define KEY_DOWN 0xD0 /* DownArrow on arrow keypad */
+#define KEY_NEXT 0xD1 /* PgDn on arrow keypad */
+#define KEY_INSERT 0xD2 /* Insert on arrow keypad */
+#define KEY_DELETE 0xD3 /* Delete on arrow keypad */
+#define KEY_LWIN 0xDB /* Left Windows key */
+#define KEY_RWIN 0xDC /* Right Windows key */
+#define KEY_APPS 0xDD /* AppMenu key */
+#define KEY_POWER 0xDE /* System Power */
+#define KEY_SLEEP 0xDF /* System Sleep */
+#define KEY_WAKE 0xE3 /* System Wake */
+#define KEY_WEBSEARCH 0xE5 /* Web Search */
+#define KEY_WEBFAVORITES 0xE6 /* Web Favorites */
+#define KEY_WEBREFRESH 0xE7 /* Web Refresh */
+#define KEY_WEBSTOP 0xE8 /* Web Stop */
+#define KEY_WEBFORWARD 0xE9 /* Web Forward */
+#define KEY_WEBBACK 0xEA /* Web Back */
+#define KEY_MYCOMPUTER 0xEB /* My Computer */
+#define KEY_MAIL 0xEC /* Mail */
+#define KEY_MEDIASELECT 0xED /* Media Select */
+
+//============================================================
+// device_info
+//============================================================
+
+class input_device_list;
+
+class device_info
+{
+ friend input_device_list;
+
+private:
+ std::string m_name;
+ input_device * m_device;
+ running_machine & m_machine;
+ input_module & m_module;
+ input_device_class m_deviceclass;
+
+public:
+ // Constructor
+ device_info(running_machine &machine, const char *name, input_device_class deviceclass, input_module &module)
+ : m_name(name),
+ m_device(nullptr),
+ m_machine(machine),
+ m_module(module),
+ m_deviceclass(deviceclass)
+ {
+ }
+
+ // Destructor
+ virtual ~device_info() {}
+
+ // Getters
+ running_machine & machine() const { return m_machine; }
+ const char * name() { return m_name.c_str(); }
+ input_device * device() { return m_device; }
+ input_module & module() const { return m_module; }
+ input_device_class deviceclass() { return m_deviceclass; }
+
+ // Poll and reset methods
+ virtual void poll() {};
+ virtual void reset() = 0;
+};
+
+//============================================================
+// event_based_device
+//============================================================
+
+#define DEFAULT_EVENT_QUEUE_SIZE 20
+
+template <class TEvent>
+class event_based_device : public device_info
+{
+private:
+ std::queue<TEvent> m_event_queue;
+
+protected:
+ std::mutex m_device_lock;
+
+ virtual void process_event(TEvent &ev) = 0;
+
+public:
+ event_based_device(running_machine &machine, const char *name, input_device_class deviceclass, input_module &module)
+ : device_info(machine, name, deviceclass, module)
+ {
+ }
+
+ void queue_events(const TEvent *events, int count)
+ {
+ std::lock_guard<std::mutex> scope_lock(m_device_lock);
+ for (int i = 0; i < count; i++)
+ m_event_queue.push(events[i]);
+
+ // If we've gone over the size, remove old events from the queue
+ while (m_event_queue.size() > DEFAULT_EVENT_QUEUE_SIZE)
+ m_event_queue.pop();
+ }
+
+ void virtual poll() override
+ {
+ std::lock_guard<std::mutex> scope_lock(m_device_lock);
+
+ // Process each event until the queue is empty
+ while (!m_event_queue.empty())
+ {
+ TEvent &next_event = m_event_queue.front();
+ process_event(next_event);
+ m_event_queue.pop();
+ }
+ }
+};
+
+//============================================================
+// input_device_list class
+//============================================================
+
+class input_device_list
+{
+protected:
+ std::vector<std::unique_ptr<device_info>> m_list;
+
+public:
+ input_device_list()
+ {
+ }
+
+ void poll_devices()
+ {
+ for (auto iter = m_list.begin(); iter != m_list.end(); iter++)
+ iter->get()->poll();
+ }
+
+ void reset_devices()
+ {
+ for (auto iter = m_list.begin(); iter != m_list.end(); iter++)
+ iter->get()->reset();
+ }
+
+ void free_device(device_info * devinfo)
+ {
+ // remove us from the list
+ for (auto iter = m_list.begin(); iter != m_list.end(); iter++)
+ {
+ if (iter->get() == devinfo)
+ {
+ m_list.erase(iter);
+ break;
+ }
+ }
+ }
+
+ int find_index(device_info* devinfo)
+ {
+ // remove us from the list
+ int i = 0;
+ for (auto iter = m_list.begin(); iter != m_list.end(); iter++)
+ {
+ if (iter->get() == devinfo)
+ {
+ break;
+ }
+
+ i++;
+ }
+
+ // return the index or -1 if we couldn't find it
+ return i == m_list.size() ? -1 : i;
+ }
+
+ void free_all_devices()
+ {
+ while (!m_list.empty())
+ m_list.pop_back();
+ }
+
+ int size()
+ {
+ return m_list.size();
+ }
+
+ device_info* at(int index)
+ {
+ return m_list.at(index).get();
+ }
+
+ template <typename TActual>
+ TActual* create_device(running_machine &machine, const char *name, input_module &module)
+ {
+ // allocate the device object
+ auto devinfo = std::make_unique<TActual>(machine, name, module);
+
+ // Add the device to the machine
+ devinfo->m_device = machine.input().device_class(devinfo->deviceclass()).add_device(devinfo->name(), devinfo.get());
+
+ // append us to the list
+ m_list.push_back(std::move(devinfo));
+
+ return (TActual*)m_list.back().get();
+ }
+
+ template <class TActual>
+ TActual* at(int index)
+ {
+ return (TActual*)m_list.at(index).get();
+ }
+};
+
+// keyboard translation table
+
+struct key_trans_entry {
+ input_item_id mame_key;
+
+#if !defined(OSD_WINDOWS)
+ int sdl_scancode;
+ int sdl_key;
+#else
+ int scan_code;
+ unsigned char virtual_key;
+#endif
+
+ char ascii_key;
+ char const * mame_key_name;
+ char * ui_name;
+};
+
+class keyboard_trans_table
+{
+private:
+ // default constructor is private
+ keyboard_trans_table();
+
+ static key_trans_entry s_default_table[];
+ std::unique_ptr<key_trans_entry[]> m_custom_table;
+
+ key_trans_entry * m_table;
+ UINT32 m_table_size;
+
+public:
+ // constructor
+ keyboard_trans_table(std::unique_ptr<key_trans_entry[]> table, unsigned int size);
+
+ // getters/setters
+ UINT32 size() { return m_table_size; }
+
+ // public methods
+ input_item_id lookup_mame_code(const char * scode);
+ int lookup_mame_index(const char * scode);
+
+#if defined(OSD_WINDOWS)
+ input_item_id map_di_scancode_to_itemid(int di_scancode);
+ int vkey_for_mame_code(input_code code);
+#endif
+
+ static keyboard_trans_table& instance()
+ {
+ static keyboard_trans_table s_instance;
+ return s_instance;
+ }
+
+ key_trans_entry & operator [](int i) { return m_table[i]; }
+};
+
+//============================================================
+// input_module_base - base class for input modules
+//============================================================
+
+class osd_options;
+
+typedef std::chrono::high_resolution_clock clock_type;
+typedef std::chrono::time_point<std::chrono::high_resolution_clock> timepoint_type;
+
+// 10 milliseconds polling interval
+#define MIN_POLLING_INTERVAL 10
+
+class input_module_base : public input_module
+{
+public:
+ input_module_base(const char *type, const char* name)
+ : input_module(type, name),
+ m_input_enabled(FALSE),
+ m_mouse_enabled(FALSE),
+ m_lightgun_enabled(FALSE),
+ m_input_paused(FALSE)
+ {
+ }
+
+private:
+ bool m_input_enabled;
+ bool m_mouse_enabled;
+ bool m_lightgun_enabled;
+ bool m_input_paused;
+ const osd_options * m_options;
+ input_device_list m_devicelist;
+ clock_type m_clock;
+ timepoint_type m_last_poll;
+
+protected:
+ void set_mouse_enabled(bool value) { m_mouse_enabled = value; }
+
+public:
+
+ const osd_options * options() { return m_options; }
+ input_device_list * devicelist() { return &m_devicelist; }
+ bool input_enabled() { return m_input_enabled; }
+ bool input_paused() { return m_input_paused; }
+ bool mouse_enabled() { return m_mouse_enabled; }
+ bool lightgun_enabled() { return m_lightgun_enabled; }
+
+ int init(const osd_options &options) override;
+
+ void poll_if_necessary(running_machine &machine) override
+ {
+ auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(m_clock.now() - m_last_poll);
+ if (elapsed.count() >= MIN_POLLING_INTERVAL)
+ {
+ poll(machine);
+ }
+ }
+
+ virtual void poll(running_machine &machine)
+ {
+ // ignore if not enabled
+ if (m_input_enabled)
+ {
+ // grab the current time
+ m_last_poll = m_clock.now();
+
+ before_poll(machine);
+
+ // track if mouse/lightgun is enabled, for mouse hiding purposes
+ m_mouse_enabled = machine.input().device_class(DEVICE_CLASS_MOUSE).enabled();
+ m_lightgun_enabled = machine.input().device_class(DEVICE_CLASS_LIGHTGUN).enabled();
+ }
+
+ // poll all of the devices
+ if (should_poll_devices(machine))
+ {
+ m_devicelist.poll_devices();
+ }
+ else
+ {
+ m_devicelist.reset_devices();
+ }
+ }
+
+ virtual void pause() override
+ {
+ // keep track of the paused state
+ m_input_paused = true;
+ }
+
+ virtual void resume() override
+ {
+ // keep track of the paused state
+ m_input_paused = false;
+ }
+
+ virtual void exit() override
+ {
+ devicelist()->free_all_devices();
+ }
+
+protected:
+ virtual int init_internal() { return 0; }
+ virtual bool should_poll_devices(running_machine &machine) = 0;
+ virtual void before_poll(running_machine &machine) {}
+};
+
+inline static int generic_button_get_state(void *device_internal, void *item_internal)
+{
+ device_info *devinfo = (device_info *)device_internal;
+ unsigned char *itemdata = (unsigned char*)item_internal;
+
+ // return the current state
+ devinfo->module().poll_if_necessary(devinfo->machine());
+ return *itemdata >> 7;
+}
+
+inline static int generic_axis_get_state(void *device_internal, void *item_internal)
+{
+ device_info *devinfo = (device_info *)device_internal;
+ int *axisdata = (int*)item_internal;
+
+ // return the current state
+ devinfo->module().poll_if_necessary(devinfo->machine());
+ return *axisdata;
+}
+
+//============================================================
+// default_button_name
+//============================================================
+
+inline static const char *default_button_name(int which)
+{
+ static char buffer[20];
+ snprintf(buffer, ARRAY_LENGTH(buffer), "B%d", which);
+ return buffer;
+}
+
+//============================================================
+// default_pov_name
+//============================================================
+
+inline static const char *default_pov_name(int which)
+{
+ static char buffer[20];
+ snprintf(buffer, ARRAY_LENGTH(buffer), "POV%d", which);
+ return buffer;
+}
+
+// default axis names
+const char *const default_axis_name[] =
+{
+ "X", "Y", "Z", "RX",
+ "RY", "RZ", "SL1", "SL2"
+};
+
+inline static 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);
+ }
+}
+
+#endif
diff --git a/src/osd/modules/input/input_dinput.cpp b/src/osd/modules/input/input_dinput.cpp
new file mode 100644
index 00000000000..a08a62af636
--- /dev/null
+++ b/src/osd/modules/input/input_dinput.cpp
@@ -0,0 +1,683 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Brad Hughes
+//============================================================
+//
+// input_dinput.cpp - Windows DirectInput support
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS)
+
+// 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
+
+#include <mutex>
+#include <thread>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "strconv.h"
+
+// MAMEOS headers
+#include "winmain.h"
+#include "window.h"
+#include "winutil.h"
+#include "../../windows/input.h"
+
+#include "input_common.h"
+#include "input_windows.h"
+
+#define STRUCTSIZE(x) (m_dinput_version == 0x0300) ? sizeof(x##_DX3) : sizeof(x)
+
+static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal);
+
+//============================================================
+// 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 - base directinput device
+//============================================================
+
+// DirectInput-specific information about a device
+struct dinput_api_state
+{
+ LPDIRECTINPUTDEVICE device;
+ LPDIRECTINPUTDEVICE2 device2;
+ DIDEVCAPS caps;
+ LPCDIDATAFORMAT format;
+};
+
+class dinput_device : public device_info
+{
+public:
+ dinput_api_state dinput;
+
+ dinput_device(running_machine &machine, const char *name, input_device_class deviceclass, input_module &module)
+ : device_info(machine, name, deviceclass, module),
+ dinput({0})
+ {
+ }
+
+protected:
+ HRESULT poll_dinput(LPVOID pState)
+ {
+ HRESULT result;
+
+ // first poll the device, then get the state
+ if (dinput.device2 != NULL)
+ IDirectInputDevice2_Poll(dinput.device2);
+
+ // GetDeviceState returns the immediate state
+ result = IDirectInputDevice_GetDeviceState(dinput.device, dinput.format->dwDataSize, pState);
+
+ // handle lost inputs here
+ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED)
+ {
+ result = IDirectInputDevice_Acquire(dinput.device);
+ if (result == DI_OK)
+ result = IDirectInputDevice_GetDeviceState(dinput.device, dinput.format->dwDataSize, pState);
+ }
+
+ return result;
+ }
+};
+
+//============================================================
+// dinput_keyboard_device - directinput keyboard device
+//============================================================
+
+class dinput_keyboard_device : public dinput_device
+{
+private:
+ HANDLE m_dataEvent;
+ HANDLE m_exitEvent;
+ std::mutex m_device_lock;
+
+public:
+ keyboard_state keyboard;
+
+ dinput_keyboard_device(running_machine &machine, const char *name, input_module &module)
+ : dinput_device(machine, name, DEVICE_CLASS_KEYBOARD, module),
+ keyboard({0})
+ {
+ }
+
+ // Polls the direct input immediate state
+ void poll() override
+ {
+ std::lock_guard<std::mutex> scope_lock(m_device_lock);
+
+ // Poll the state
+ dinput_device::poll_dinput(&keyboard.state);
+ }
+
+ void reset() override
+ {
+ memset(&keyboard, 0, sizeof(keyboard));
+ }
+};
+
+//============================================================
+// dinput_module - base directinput module
+//============================================================
+
+class dinput_module : public wininput_module
+{
+private:
+ LPDIRECTINPUT m_dinput;
+ int m_dinput_version;
+ int didevtype_keyboard;
+ int didevtype_mouse;
+
+public:
+ dinput_module(const char* type, const char* name)
+ : wininput_module(type, name)
+ {
+ }
+
+ int init_internal() override
+ {
+ HRESULT result = S_OK;
+
+#if DIRECTINPUT_VERSION >= 0x800
+ m_dinput_version = DIRECTINPUT_VERSION;
+ result = DirectInput8Create(GetModuleHandleUni(), m_dinput_version, IID_IDirectInput8, (void **)&m_dinput, NULL);
+ if (result != DI_OK)
+ {
+ m_dinput_version = 0;
+ return result;
+ }
+#else
+ // first attempt to initialize DirectInput at the current version
+ m_dinput_version = DIRECTINPUT_VERSION;
+ result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, &m_dinput, NULL);
+ if (result != DI_OK)
+ {
+ // if that fails, try version 5
+ m_dinput_version = 0x0500;
+ result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, &m_dinput, NULL);
+ if (result != DI_OK)
+ {
+ // if that fails, try version 3
+ m_dinput_version = 0x0300;
+ result = DirectInputCreate(GetModuleHandleUni(), m_dinput_version, &m_dinput, NULL);
+ if (result != DI_OK)
+ {
+ m_dinput_version = 0;
+ return result;
+ }
+ }
+ }
+#endif
+
+ osd_printf_verbose("DirectInput: Using DirectInput %d\n", m_dinput_version >> 8);
+ return 0;
+ }
+
+ void exit() override
+ {
+ wininput_module::exit();
+ }
+
+ virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) = 0;
+
+ void input_init(running_machine &machine) override
+ {
+ struct dinput_callback_context
+ {
+ dinput_module * self;
+ running_machine * machine;
+ } context = { this, &machine };
+
+ // enumerate the ones we have
+ auto enum_callback = [](LPCDIDEVICEINSTANCE instance, LPVOID ref) {
+ return ((dinput_callback_context*)ref)->self->device_enum_callback(instance, ((dinput_callback_context*)ref)->machine);
+ };
+
+ HRESULT result = IDirectInput_EnumDevices(m_dinput, dinput_devclass(), enum_callback, &context, DIEDFL_ATTACHEDONLY);
+ if (result != DI_OK)
+ fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", (UINT32)result);
+ }
+
+protected:
+ virtual int dinput_devclass() = 0;
+
+ template <class TDevice>
+ TDevice* create_dinput_device(
+ running_machine &machine,
+ LPCDIDEVICEINSTANCE instance,
+ LPCDIDATAFORMAT format1,
+ LPCDIDATAFORMAT format2,
+ DWORD cooperative_level)
+ {
+ HRESULT result;
+
+ // convert instance name to utf8
+ auto osd_deleter = [](void *ptr) { osd_free(ptr); };
+ auto utf8_instance_name = std::unique_ptr<char, decltype(osd_deleter)>(utf8_from_tstring(instance->tszInstanceName), osd_deleter);
+
+ // allocate memory for the device object
+ TDevice* devinfo = devicelist()->create_device<TDevice>(machine, utf8_instance_name.get(), *this);
+
+ // attempt to create a device
+ result = IDirectInput_CreateDevice(m_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:
+ devicelist()->free_device(devinfo);
+ return NULL;
+ }
+
+ std::string device_item_name(dinput_device * devinfo, int offset, const char * defstring, const TCHAR * suffix)
+ {
+ DIDEVICEOBJECTINSTANCE instance = { 0 };
+ HRESULT result;
+
+ // 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 == nullptr)
+ return nullptr;
+
+ // Return the default value
+ return std::string(defstring);
+ }
+
+ auto osd_free_deleter = [](char *p) { osd_free(p); };
+
+ // convert the name to utf8
+ auto namestring = std::unique_ptr<char, decltype(osd_free_deleter)>(utf8_from_tstring(instance.tszName), osd_free_deleter);
+
+ // if no suffix, return as-is
+ if (suffix == nullptr)
+ {
+ return std::string(namestring.get());
+ }
+
+ // otherwise, allocate space to add the suffix
+ auto combined = std::make_unique<char[]>(strlen(namestring.get()) + 1 + _tcslen(suffix) + 1);
+
+ // convert the suffix to utf8
+ auto suffix_utf8 = std::unique_ptr<char, decltype(osd_free_deleter)>(utf8_from_tstring(suffix), osd_free_deleter);
+
+ // Concat the name and suffix
+ strcpy(combined.get(), namestring.get());
+ strcat(combined.get(), " ");
+ strcat(combined.get(), suffix_utf8.get());
+
+ return std::string(combined.get());
+ }
+};
+
+class keyboard_input_dinput : public dinput_module
+{
+public:
+ keyboard_input_dinput() :
+ dinput_module(OSD_KEYBOARDINPUT_PROVIDER, "dinput")
+ {
+ }
+
+ int dinput_devclass() override
+ {
+#if DIRECTINPUT_VERSION >= 0x800
+ return DI8DEVCLASS_KEYBOARD;
+#else
+ return DIDEVTYPE_KEYBOARD;
+#endif
+ }
+
+ BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ {
+ running_machine &machine = *(running_machine *)ref;
+ dinput_keyboard_device *devinfo;
+ int keynum;
+
+ // allocate and link in a new device
+ devinfo = create_dinput_device<dinput_keyboard_device>(machine, instance, &c_dfDIKeyboard, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
+ if (devinfo == NULL)
+ goto exit;
+
+ // populate it
+ for (keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = keyboard_trans_table::instance().map_di_scancode_to_itemid(keynum);
+ char defname[20];
+ std::string name;
+
+ // generate/fetch the name
+ snprintf(defname, ARRAY_LENGTH(defname), "Scan%03d", keynum);
+ name = device_item_name(devinfo, keynum, defname, NULL);
+
+ // add the item to the device
+ devinfo->device()->add_item(name.c_str(), itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
+ }
+
+ exit:
+ return DIENUM_CONTINUE;
+ }
+};
+
+class dinput_mouse_device : public dinput_device
+{
+public:
+ mouse_state mouse;
+
+ dinput_mouse_device(running_machine &machine, const char *name, input_module &module)
+ : dinput_device(machine, name, DEVICE_CLASS_MOUSE, module),
+ mouse({0})
+ {
+ }
+
+ void poll() override
+ {
+ // poll
+ dinput_device::poll_dinput(&mouse);
+
+ // scale the axis data
+ mouse.lX *= INPUT_RELATIVE_PER_PIXEL;
+ mouse.lY *= INPUT_RELATIVE_PER_PIXEL;
+ mouse.lZ *= INPUT_RELATIVE_PER_PIXEL;
+ }
+
+ void reset() override
+ {
+ memset(&mouse, 0, sizeof(mouse));
+ }
+};
+
+class mouse_input_dinput : public dinput_module
+{
+public:
+ mouse_input_dinput() :
+ dinput_module(OSD_MOUSEINPUT_PROVIDER, "dinput")
+ {
+ }
+
+ int dinput_devclass() override
+ {
+#if DIRECTINPUT_VERSION >= 0x800
+ return DI8DEVCLASS_POINTER;
+#else
+ return DI8DEVTYPE_MOUSE;
+#endif
+ }
+
+ BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ {
+ dinput_mouse_device *devinfo = NULL;
+ running_machine &machine = *(running_machine *)ref;
+ int axisnum, butnum;
+ HRESULT result;
+
+ // allocate and link in a new device
+ devinfo = create_dinput_device<dinput_mouse_device>(machine, instance, &c_dfDIMouse2, &c_dfDIMouse, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
+ if (devinfo == 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", devicelist()->size(), devinfo->name());
+ goto error;
+ }
+
+ // 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++)
+ {
+ // add to the mouse device and optionally to the gun device as well
+ std::string name = device_item_name(devinfo, offsetof(DIMOUSESTATE, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
+ devinfo->device()->add_item(name.c_str(), (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
+ {
+ FPTR offset = (FPTR)(&((DIMOUSESTATE *)NULL)->rgbButtons[butnum]);
+
+ // add to the mouse device
+ std::string name = device_item_name(devinfo, offset, default_button_name(butnum), NULL);
+ devinfo->device()->add_item(name.c_str(), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
+ }
+
+ exit:
+ return DIENUM_CONTINUE;
+
+ error:
+ if (devinfo != NULL)
+ devicelist()->free_device(devinfo);
+ goto exit;
+ }
+};
+
+// state information for a joystick; DirectInput state must be first element
+struct dinput_joystick_state
+{
+ DIJOYSTATE state;
+ LONG rangemin[8];
+ LONG rangemax[8];
+};
+
+class dinput_joystick_device : public dinput_device
+{
+public:
+ dinput_joystick_state joystick;
+
+ dinput_joystick_device(running_machine &machine, const char *name, input_module &module)
+ : dinput_device(machine, name, DEVICE_CLASS_JOYSTICK, module),
+ joystick({0})
+ {
+ }
+
+ void reset() override
+ {
+ memset(&joystick, 0, sizeof(joystick));
+ }
+
+ void poll() override
+ {
+ int axisnum;
+
+ // poll the device first
+ dinput_device::poll_dinput(&joystick.state);
+
+ // normalize axis values
+ for (axisnum = 0; axisnum < 8; axisnum++)
+ {
+ LONG *axis = (&joystick.state.lX) + axisnum;
+ *axis = normalize_absolute_axis(*axis, joystick.rangemin[axisnum], joystick.rangemax[axisnum]);
+ }
+ }
+};
+
+class joystick_input_dinput : public dinput_module
+{
+public:
+ joystick_input_dinput() :
+ dinput_module(OSD_JOYSTICKINPUT_PROVIDER, "dinput")
+ {
+ }
+
+ int dinput_devclass() override
+ {
+#if DIRECTINPUT_VERSION >= 0x800
+ return DI8DEVCLASS_GAMECTRL;
+#else
+ return DI8DEVTYPE_JOYSTICK;
+#endif
+ }
+
+ BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ {
+ DWORD cooperative_level = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
+ int axisnum, axiscount, povnum, butnum;
+ running_machine &machine = *(running_machine *)ref;
+ dinput_joystick_device *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 = create_dinput_device<dinput_joystick_device>(machine, 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", devicelist()->size(), 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", devicelist()->size(), 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", devicelist()->size(), 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);
+
+ // populate the axes
+ for (axisnum = axiscount = 0; axiscount < devinfo->dinput.caps.dwAxes && axisnum < 8; axisnum++)
+ {
+ DIPROPRANGE dipr;
+ std::string 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 = device_item_name(devinfo, offsetof(DIJOYSTATE2, lX) + axisnum * sizeof(LONG), default_axis_name[axisnum], NULL);
+ devinfo->device()->add_item(name.c_str(), (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->joystick.state.lX + axisnum);
+
+ axiscount++;
+ }
+
+ // populate the POVs
+ for (povnum = 0; povnum < devinfo->dinput.caps.dwPOVs; povnum++)
+ {
+ std::string name;
+
+ // left
+ name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("L"));
+ devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_LEFT));
+
+ // right
+ name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("R"));
+ devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_RIGHT));
+
+ // up
+ name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("U"));
+ devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_UP));
+
+ // down
+ name = device_item_name(devinfo, offsetof(DIJOYSTATE2, rgdwPOV) + povnum * sizeof(DWORD), default_pov_name(povnum), TEXT("D"));
+ devinfo->device()->add_item(name.c_str(), ITEM_ID_OTHER_SWITCH, dinput_joystick_pov_get_state, (void *)(FPTR)(povnum * 4 + POVDIR_DOWN));
+ }
+
+ // populate the buttons
+ for (butnum = 0; butnum < devinfo->dinput.caps.dwButtons; butnum++)
+ {
+ FPTR offset = (FPTR)(&((DIJOYSTATE2 *)NULL)->rgbButtons[butnum]);
+ std::string name = 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.c_str(), itemid, generic_button_get_state, &devinfo->joystick.state.rgbButtons[butnum]);
+ }
+
+ exit:
+ return DIENUM_CONTINUE;
+ }
+};
+
+//============================================================
+// dinput_joystick_pov_get_state
+//============================================================
+
+static INT32 dinput_joystick_pov_get_state(void *device_internal, void *item_internal)
+{
+ dinput_joystick_device *devinfo = (dinput_joystick_device *)device_internal;
+ int povnum = (FPTR)item_internal / 4;
+ int povdir = (FPTR)item_internal % 4;
+ INT32 result = 0;
+ DWORD pov;
+
+ // get the current state
+ devinfo->module().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;
+}
+
+#else
+MODULE_NOT_SUPPORTED(keyboard_input_dinput, OSD_KEYBOARDINPUT_PROVIDER, "dinput")
+MODULE_NOT_SUPPORTED(mouse_input_dinput, OSD_MOUSEINPUT_PROVIDER, "dinput")
+MODULE_NOT_SUPPORTED(joystick_input_dinput, OSD_JOYSTICKINPUT_PROVIDER, "dinput")
+#endif
+
+MODULE_DEFINITION(KEYBOARDINPUT_DINPUT, keyboard_input_dinput)
+MODULE_DEFINITION(MOUSEINPUT_DINPUT, mouse_input_dinput)
+MODULE_DEFINITION(JOYSTICKINPUT_DINPUT, joystick_input_dinput) \ No newline at end of file
diff --git a/src/osd/modules/input/input_module.h b/src/osd/modules/input/input_module.h
new file mode 100644
index 00000000000..f031bbb6fad
--- /dev/null
+++ b/src/osd/modules/input/input_module.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes
+//============================================================
+//
+// input_module.h - OSD input module contracts
+//
+//============================================================
+
+#ifndef INPUT_MODULE_H_
+#define INPUT_MODULE_H_
+
+#include "osdepend.h"
+#include "modules/osdmodule.h"
+
+class input_module : public osd_module
+{
+public:
+ input_module(const char *type, const char *name)
+ : osd_module(type, name)
+ {
+ }
+
+ virtual void input_init(running_machine &machine) = 0;
+ virtual void poll_if_necessary(running_machine &machine) = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+ virtual void exit() override {};
+};
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+#define OSD_KEYBOARDINPUT_PROVIDER "keyboardprovider"
+#define OSD_MOUSEINPUT_PROVIDER "mouseprovider"
+#define OSD_LIGHTGUNINPUT_PROVIDER "lightgunprovider"
+#define OSD_JOYSTICKINPUT_PROVIDER "joystickprovider"
+
+#endif /* INPUT_MODULE_H_ */
diff --git a/src/osd/modules/input/input_none.cpp b/src/osd/modules/input/input_none.cpp
new file mode 100644
index 00000000000..e485faca4f6
--- /dev/null
+++ b/src/osd/modules/input/input_none.cpp
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Brad Hughes
+//============================================================
+//
+// input_none.cpp - Default unimplemented input modules
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+class keyboard_input_none : public input_module
+{
+public:
+ keyboard_input_none()
+ : input_module(OSD_KEYBOARDINPUT_PROVIDER, "none") {}
+ int init(const osd_options &options) override { return 0; }
+ void poll_if_necessary(running_machine &machine) override {};
+ void input_init(running_machine &machine) override {};
+ void pause() override {};
+ void resume() override {};
+};
+
+MODULE_DEFINITION(KEYBOARD_NONE, keyboard_input_none)
+
+class mouse_input_none : public input_module
+{
+public:
+ mouse_input_none()
+ : input_module(OSD_MOUSEINPUT_PROVIDER, "none") {}
+ int init(const osd_options &options) override { return 0; }
+ void input_init(running_machine &machine) override {};
+ void poll_if_necessary(running_machine &machine) override {};
+ void pause() override {};
+ void resume() override {};
+};
+
+MODULE_DEFINITION(MOUSE_NONE, mouse_input_none)
+
+class lightgun_input_none : public input_module
+{
+public:
+ lightgun_input_none()
+ : input_module(OSD_LIGHTGUNINPUT_PROVIDER, "none") {}
+ int init(const osd_options &options) override { return 0; }
+ void input_init(running_machine &machine) override {};
+ void poll_if_necessary(running_machine &machine) override {};
+ void pause() override {};
+ void resume() override {};
+};
+
+MODULE_DEFINITION(LIGHTGUN_NONE, lightgun_input_none)
+
+class joystick_input_none : public input_module
+{
+public:
+ joystick_input_none()
+ : input_module(OSD_JOYSTICKINPUT_PROVIDER, "none") {}
+ int init(const osd_options &options) override { return 0; }
+ void input_init(running_machine &machine) override {};
+ void poll_if_necessary(running_machine &machine) override {};
+ void pause() override {};
+ void resume() override {};
+};
+
+MODULE_DEFINITION(JOYSTICK_NONE, joystick_input_none) \ No newline at end of file
diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp
new file mode 100644
index 00000000000..3b9c621b015
--- /dev/null
+++ b/src/osd/modules/input/input_rawinput.cpp
@@ -0,0 +1,649 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Brad Hughes
+//============================================================
+//
+// input_rawinput.cpp - Windows RawInput input implementation
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#undef interface
+
+#include <mutex>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "strconv.h"
+
+// MAMEOS headers
+#include "winmain.h"
+#include "window.h"
+#include "../../windows/input.h"
+
+#include "input_common.h"
+#include "input_windows.h"
+
+//============================================================
+// MACROS
+//============================================================
+
+#ifdef UNICODE
+#define UNICODE_SUFFIX "W"
+#else
+#define UNICODE_SUFFIX "A"
+#endif
+
+// 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);
+
+//============================================================
+// 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;
+}
+
+//============================================================
+// 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_device class
+//============================================================
+
+class rawinput_device : public event_based_device<RAWINPUT>
+{
+private:
+ HANDLE m_handle;
+
+public:
+ rawinput_device(running_machine& machine, const char* name, input_device_class deviceclass, input_module& module)
+ : event_based_device(machine, name, deviceclass, module)
+ {
+ }
+
+ HANDLE device_handle() { return m_handle; }
+ void set_handle(HANDLE handle) { m_handle = handle; }
+};
+
+//============================================================
+// rawinput_keyboard_device
+//============================================================
+
+class rawinput_keyboard_device : public rawinput_device
+{
+public:
+ keyboard_state keyboard;
+
+ rawinput_keyboard_device(running_machine& machine, const char* name, input_module& module)
+ : rawinput_device(machine, name, DEVICE_CLASS_KEYBOARD, module),
+ keyboard({0})
+ {
+ }
+
+ void reset() override
+ {
+ memset(&keyboard, 0, sizeof(keyboard));
+ }
+
+ void process_event(RAWINPUT &rawinput) override
+ {
+ // determine the full DIK-compatible scancode
+ UINT8 scancode = (rawinput.data.keyboard.MakeCode & 0x7f) | ((rawinput.data.keyboard.Flags & RI_KEY_E0) ? 0x80 : 0x00);
+
+ // scancode 0xaa is a special shift code we need to ignore
+ if (scancode == 0xaa)
+ return;
+
+ // set or clear the key
+ keyboard.state[scancode] = (rawinput.data.keyboard.Flags & RI_KEY_BREAK) ? 0x00 : 0x80;
+ }
+};
+
+//============================================================
+// rawinput_mouse_device
+//============================================================
+
+struct rawinput_mouse_state
+{
+ int raw_x;
+ int raw_y;
+ int raw_z;
+};
+
+class rawinput_mouse_device : public rawinput_device
+{
+private:
+ std::mutex m_device_lock;
+public:
+ //rawinput_mouse_state raw_mouse;
+ mouse_state mouse;
+
+ rawinput_mouse_device(running_machine& machine, const char* name, input_module& module)
+ : rawinput_device(machine, name, DEVICE_CLASS_MOUSE, module),
+ mouse({0})
+ {
+ }
+
+ void poll() override
+ {
+ mouse.lX = 0;
+ mouse.lY = 0;
+ mouse.lZ = 0;
+
+ rawinput_device::poll();
+
+ //std::lock_guard<std::mutex> scope_lock(m_device_lock);
+
+ //// copy the accumulated raw state to the actual state
+ //mouse.lX = raw_mouse.raw_x;
+ //mouse.lY = raw_mouse.raw_y;
+ //mouse.lZ = raw_mouse.raw_z;
+ //raw_mouse.raw_x = 0;
+ //raw_mouse.raw_y = 0;
+ //raw_mouse.raw_z = 0;
+
+ //osd_printf_verbose("At poll: lX=%d, lY=%d, lZ=%d\n", (int)mouse.lX, (int)mouse.lY, (int)mouse.lZ);
+ }
+
+ void reset() override
+ {
+ memset(&mouse, 0, sizeof(mouse));
+ }
+
+ void process_event(RAWINPUT &rawinput) override
+ {
+ // If this data was intended for a rawinput lightgun, ignore it.
+ if (rawinput.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+ return;
+
+ mouse.lX += rawinput.data.mouse.lLastX * INPUT_RELATIVE_PER_PIXEL;
+ mouse.lY += rawinput.data.mouse.lLastY * INPUT_RELATIVE_PER_PIXEL;
+
+ /*osd_printf_verbose(
+ "Mouse Abs : lastX = %d, lastY = %d, rawx = %d, rawy = %d\n",
+ (int)rawinput.data.mouse.lLastX,
+ (int)rawinput.data.mouse.lLastY,
+ (int)raw_mouse.raw_x,
+ (int)raw_mouse.raw_y);*/
+
+ // update zaxis
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_WHEEL)
+ mouse.lZ += (INT16)rawinput.data.mouse.usButtonData * INPUT_RELATIVE_PER_PIXEL;
+
+ // update the button states; always update the corresponding mouse buttons
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) mouse.rgbButtons[0] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) mouse.rgbButtons[0] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) mouse.rgbButtons[1] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) mouse.rgbButtons[1] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) mouse.rgbButtons[2] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) mouse.rgbButtons[2] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) mouse.rgbButtons[3] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) mouse.rgbButtons[3] = 0x00;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) mouse.rgbButtons[4] = 0x80;
+ if (rawinput.data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) mouse.rgbButtons[4] = 0x00;
+ }
+};
+
+//============================================================
+// rawinput_module - base class for rawinput modules
+//============================================================
+
+class rawinput_module : public wininput_module
+{
+private:
+ // RawInput variables
+ get_rawinput_device_list_ptr get_rawinput_device_list;
+ get_rawinput_data_ptr get_rawinput_data;
+ get_rawinput_device_info_ptr get_rawinput_device_info;
+ register_rawinput_devices_ptr register_rawinput_devices;
+ std::mutex m_module_lock;
+
+public:
+ rawinput_module(const char *type, const char* name)
+ : wininput_module(type, name),
+ get_rawinput_device_list(nullptr),
+ get_rawinput_data(nullptr),
+ get_rawinput_device_info(nullptr),
+ register_rawinput_devices(nullptr)
+ {
+ }
+
+ void input_init(running_machine &machine) override
+ {
+ // get the number of devices, allocate a device list, and fetch it
+ int device_count = 0;
+ if ((*get_rawinput_device_list)(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) != 0)
+ return;
+
+ if (device_count == 0)
+ return;
+
+ auto rawinput_devices = std::make_unique<RAWINPUTDEVICELIST[]>(device_count);
+ if ((*get_rawinput_device_list)(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)) == -1)
+ return;
+
+ // iterate backwards through devices; new devices are added at the head
+ for (int devnum = device_count - 1; devnum >= 0; devnum--)
+ {
+ RAWINPUTDEVICELIST *device = &rawinput_devices[devnum];
+ add_rawinput_device(machine, device);
+ }
+
+ // don't enable global inputs when debugging
+ if (!machine.options().debug())
+ {
+ m_global_inputs_enabled = downcast<windows_options &>(machine.options()).global_inputs();
+ }
+
+ // If we added no devices, no need to register for notifications
+ if (devicelist()->size() == 0)
+ return;
+
+ // finally, register to receive raw input WM_INPUT messages if we found devices
+ RAWINPUTDEVICE registration;
+ registration.usUsagePage = usagepage();
+ registration.usUsage = usage();
+ registration.dwFlags = m_global_inputs_enabled ? 0x00000100 : 0;
+ registration.hwndTarget = win_window_list->m_hwnd;
+
+ // register the device
+ (*register_rawinput_devices)(&registration, 1, sizeof(registration));
+ }
+
+protected:
+ virtual void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) = 0;
+ virtual USHORT usagepage() = 0;
+ virtual USHORT usage() = 0;
+
+ int init_internal() override
+ {
+ HMODULE user32;
+
+ // look in user32 for the raw input APIs
+ user32 = LoadLibrary(TEXT("user32.dll"));
+ if (user32 == NULL)
+ return 1;
+
+ // 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)
+ return 1;
+
+ osd_printf_verbose("RawInput: APIs detected\n");
+
+ return 0;
+ }
+
+ template<class TDevice>
+ TDevice* create_rawinput_device(running_machine &machine, PRAWINPUTDEVICELIST rawinputdevice)
+ {
+ TDevice* devinfo = nullptr;
+ INT name_length = 0;
+ // determine the length of the device name, allocate it, and fetch it if not nameless
+ if ((*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, NULL, &name_length) != 0)
+ return nullptr;
+
+ std::unique_ptr<TCHAR[]> tname = std::make_unique<TCHAR[]>(name_length + 1);
+ if (name_length > 1 && (*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == -1)
+ return nullptr;
+
+ // if this is an RDP name, skip it
+ if (_tcsstr(tname.get(), TEXT("Root#RDP_")) != NULL)
+ return nullptr;
+
+ // improve the name and then allocate a device
+ tname = std::unique_ptr<TCHAR[]>(rawinput_device_improve_name(tname.release()));
+
+ // convert name to utf8
+ auto osd_deleter = [](void *ptr) { osd_free(ptr); };
+ auto utf8_name = std::unique_ptr<char, decltype(osd_deleter)>(utf8_from_tstring(tname.get()), osd_deleter);
+
+ devinfo = devicelist()->create_device<TDevice>(machine, utf8_name.get(), *this);
+
+ // Add the handle
+ devinfo->set_handle(rawinputdevice->hDevice);
+
+ return devinfo;
+ }
+
+ bool handle_input_event(input_event eventid, void* eventdata) override
+ {
+ // Only handle raw input data
+ if (!input_enabled() || eventid != INPUT_EVENT_RAWINPUT)
+ return FALSE;
+
+ HRAWINPUT rawinputdevice = *(HRAWINPUT*)eventdata;
+
+ BYTE small_buffer[4096];
+ std::unique_ptr<BYTE[]> larger_buffer;
+ LPBYTE data = small_buffer;
+ BOOL result = FALSE;
+ int size;
+
+ // ignore if not enabled
+ if (!input_enabled())
+ return FALSE;
+
+ // determine the size of databuffer we need
+ if ((*get_rawinput_data)(rawinputdevice, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)) != 0)
+ return FALSE;
+
+ // if necessary, allocate a temporary buffer and fetch the data
+ if (size > sizeof(small_buffer))
+ {
+ larger_buffer = std::make_unique<BYTE[]>(size);
+ data = larger_buffer.get();
+ if (data == NULL)
+ return FALSE;
+ }
+
+ // fetch the data and process the appropriate message types
+ result = (*get_rawinput_data)((HRAWINPUT)rawinputdevice, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
+ if (result)
+ {
+ std::lock_guard<std::mutex> scope_lock(m_module_lock);
+
+ rawinput_device *devinfo;
+ // find the device in the list and update
+ for (int i = 0; i < devicelist()->size(); i++)
+ {
+ devinfo = dynamic_cast<rawinput_device*>(devicelist()->at(i));
+ RAWINPUT *input = reinterpret_cast<RAWINPUT*>(data);
+ if (input->header.hDevice == devinfo->device_handle())
+ {
+ devinfo->queue_events(input, 1);
+ result = TRUE;
+ }
+ }
+ }
+
+ return result;
+ }
+};
+
+//============================================================
+// keyboard_input_rawinput - rawinput keyboard module
+//============================================================
+
+class keyboard_input_rawinput : public rawinput_module
+{
+public:
+ keyboard_input_rawinput()
+ : rawinput_module(OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
+ {
+ }
+
+protected:
+ USHORT usagepage() { return 1; }
+ USHORT usage() { return 6; }
+ void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) override
+ {
+ // make sure this is a keyboard
+ if (device->dwType != RIM_TYPEKEYBOARD)
+ return;
+
+ // allocate and link in a new device
+ rawinput_keyboard_device *devinfo = create_rawinput_device<rawinput_keyboard_device>(machine, device);
+ if (devinfo == NULL)
+ return;
+
+ keyboard_trans_table &table = keyboard_trans_table::instance();
+
+ // populate it
+ for (int keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = table.map_di_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);
+ }
+ }
+};
+
+//============================================================
+// mouse_input_rawinput - rawinput mouse module
+//============================================================
+
+class mouse_input_rawinput : public rawinput_module
+{
+public:
+ mouse_input_rawinput()
+ : rawinput_module(OSD_MOUSEINPUT_PROVIDER, "rawinput")
+ {
+ }
+
+protected:
+ USHORT usagepage() { return 1; }
+ USHORT usage() { return 2; }
+ void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) override
+ {
+ // make sure this is a mouse
+ if (device->dwType != RIM_TYPEMOUSE)
+ return;
+
+ // allocate and link in a new device
+ rawinput_mouse_device *devinfo = create_rawinput_device<rawinput_mouse_device>(machine, device);
+ if (devinfo == NULL)
+ return;
+
+ // populate the axes
+ for (int axisnum = 0; axisnum < 3; axisnum++)
+ {
+ devinfo->device()->add_item(default_axis_name[axisnum], (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (int butnum = 0; butnum < 5; butnum++)
+ {
+ devinfo->device()->add_item(default_button_name(butnum), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
+ }
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(keyboard_input_rawinput, OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
+MODULE_NOT_SUPPORTED(mouse_input_rawinput, OSD_MOUSEINPUT_PROVIDER, "rawinput")
+//MODULE_NOT_SUPPORTED(lightgun_input_rawinput, OSD_LIGHTGUNINPUT_PROVIDER, "rawinput")
+#endif
+
+MODULE_DEFINITION(KEYBOARDINPUT_RAWINPUT, keyboard_input_rawinput)
+MODULE_DEFINITION(MOUSEINPUT_RAWINPUT, mouse_input_rawinput)
+//MODULE_DEFINITION(LIGHTGUNINPUT_RAWINPUT, lightgun_input_rawinput) \ No newline at end of file
diff --git a/src/osd/modules/input/input_sdl.cpp b/src/osd/modules/input/input_sdl.cpp
new file mode 100644
index 00000000000..3894f25e1b4
--- /dev/null
+++ b/src/osd/modules/input/input_sdl.cpp
@@ -0,0 +1,843 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_sdl.cpp - SDL 2.0 implementation of MAME input routines
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+// SixAxis info: left analog is axes 0 & 1, right analog is axes 2 & 3,
+// analog L2 is axis 12 and analog L3 is axis 13
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(SDLMAME_SDL2)
+
+// standard sdl header
+#include "sdlinc.h"
+#include <ctype.h>
+#include <stddef.h>
+#include <mutex>
+#include <memory>
+#include <queue>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "uiinput.h"
+#include "strconv.h"
+
+// MAMEOS headers
+#include "input_common.h"
+#include "../lib/osdobj_common.h"
+#include "input_sdlcommon.h"
+#include "../../sdl/osdsdl.h"
+#include "../../sdl/window.h"
+
+// winnt.h defines this
+#ifdef DELETE
+#undef DELETE
+#endif
+
+
+// FIXME: sdl does not properly report the window for certain OS.
+#define GET_FOCUS_WINDOW(ev) focus_window()
+//#define GET_FOCUS_WINDOW(ev) window_from_id((ev)->windowID)
+
+struct key_lookup_table
+{
+ int code;
+ const char *name;
+};
+
+#define KE(x) { SDL_SCANCODE_ ## x, "SDL_SCANCODE_" #x },
+#define KE8(A, B, C, D, E, F, G, H) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G) KE(H)
+#define KE7(A, B, C, D, E, F, G) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G)
+#define KE5(A, B, C, D, E) KE(A) KE(B) KE(C) KE(D) KE(E)
+#define KE3(A, B, C) KE(A) KE(B) KE(C)
+
+static key_lookup_table sdl_lookup_table[] =
+{
+ KE7(UNKNOWN, BACKSPACE, TAB, CLEAR, RETURN, PAUSE, ESCAPE)
+ KE(SPACE)
+ KE5(COMMA, MINUS, PERIOD, SLASH, 0)
+ KE8(1, 2, 3, 4, 5, 6, 7, 8)
+ KE3(9, SEMICOLON, EQUALS)
+ KE5(LEFTBRACKET,BACKSLASH, RIGHTBRACKET, A, B)
+ KE8(C, D, E, F, G, H, I, J)
+ KE8(K, L, M, N, O, P, Q, R)
+ KE8(S, T, U, V, W, X, Y, Z)
+ KE8(DELETE, KP_0, KP_1, KP_2, KP_3, KP_4, KP_5, KP_6)
+ KE8(KP_7, KP_8, KP_9, KP_PERIOD, KP_DIVIDE, KP_MULTIPLY,KP_MINUS, KP_PLUS)
+ KE8(KP_ENTER, KP_EQUALS, UP, DOWN, RIGHT, LEFT, INSERT, HOME)
+ KE8(END, PAGEUP, PAGEDOWN, F1, F2, F3, F4, F5)
+ KE8(F6, F7, F8, F9, F10, F11, F12, F13)
+ KE8(F14, F15, NUMLOCKCLEAR, CAPSLOCK, SCROLLLOCK, RSHIFT, LSHIFT, RCTRL)
+ KE5(LCTRL, RALT, LALT, LGUI, RGUI)
+ KE8(GRAVE, LEFTBRACKET,RIGHTBRACKET, SEMICOLON, APOSTROPHE, BACKSLASH, PRINTSCREEN,MENU)
+ KE(UNDO)
+{
+ -1, ""
+}
+};
+
+//============================================================
+// lookup_sdl_code
+//============================================================
+
+static int lookup_sdl_code(const char *scode)
+{
+ int i = 0;
+
+ while (sdl_lookup_table[i].code >= 0)
+ {
+ if (!strcmp(scode, sdl_lookup_table[i].name))
+ return sdl_lookup_table[i].code;
+ i++;
+ }
+ return -1;
+}
+
+//============================================================
+// sdl_device
+//============================================================
+
+class sdl_device : public event_based_device<SDL_Event>
+{
+public:
+ sdl_device(running_machine &machine, const char* name, input_device_class devclass, input_module &module)
+ : event_based_device(machine, name, devclass, module)
+ {
+ }
+
+protected:
+ sdl_window_info * focus_window()
+ {
+ return sdl_event_manager::instance().focus_window();
+ }
+};
+
+//============================================================
+// sdl_keyboard_device
+//============================================================
+
+#define OSD_SDL_INDEX_KEYSYM(keysym) ((keysym)->scancode)
+class sdl_keyboard_device : public sdl_device
+{
+public:
+ keyboard_state keyboard;
+
+ sdl_keyboard_device(running_machine &machine, const char* name, input_module &module)
+ : sdl_device(machine, name, DEVICE_CLASS_KEYBOARD, module),
+ keyboard({{0}})
+ {
+ }
+
+ void process_event(SDL_Event &sdlevent) override
+ {
+ switch (sdlevent.type)
+ {
+ case SDL_KEYDOWN:
+ keyboard.state[OSD_SDL_INDEX_KEYSYM(&sdlevent.key.keysym)] = 0x80;
+ if (sdlevent.key.keysym.sym < 0x20)
+ machine().ui_input().push_char_event(sdl_window_list->target(), sdlevent.key.keysym.sym);
+ break;
+
+ case SDL_KEYUP:
+ keyboard.state[OSD_SDL_INDEX_KEYSYM(&sdlevent.key.keysym)] = 0x00;
+ break;
+
+ case SDL_TEXTINPUT:
+ if (*sdlevent.text.text)
+ {
+ sdl_window_info *window = GET_FOCUS_WINDOW(&event.text);
+ //printf("Focus window is %p - wl %p\n", window, sdl_window_list);
+ unicode_char result;
+ if (window != NULL)
+ {
+ osd_uchar_from_osdchar(&result, sdlevent.text.text, 1);
+ machine().ui_input().push_char_event(window->target(), result);
+ }
+ }
+ break;
+ }
+ }
+
+ void reset() override
+ {
+ memset(&keyboard.state, 0, sizeof(keyboard.state));
+ }
+};
+
+//============================================================
+// sdl_mouse_device
+//============================================================
+
+class sdl_mouse_device : public sdl_device
+{
+public:
+ mouse_state mouse;
+
+ sdl_mouse_device(running_machine &machine, const char* name, input_module &module)
+ : sdl_device(machine, name, DEVICE_CLASS_MOUSE, module),
+ mouse({0})
+ {
+ }
+
+ void reset() override
+ {
+ memset(&mouse, 0, sizeof(mouse));
+ }
+
+ void poll() override
+ {
+ mouse.lX = 0;
+ mouse.lY = 0;
+ sdl_device::poll();
+ }
+
+ virtual void process_event(SDL_Event &sdlevent) override
+ {
+ switch (sdlevent.type)
+ {
+ case SDL_MOUSEMOTION:
+ mouse.lX += sdlevent.motion.xrel * INPUT_RELATIVE_PER_PIXEL;
+ mouse.lY += sdlevent.motion.yrel * INPUT_RELATIVE_PER_PIXEL;
+
+ {
+ int cx = -1, cy = -1;
+ sdl_window_info *window = GET_FOCUS_WINDOW(&sdlevent.motion);
+
+ if (window != NULL && window->xy_to_render_target(sdlevent.motion.x, sdlevent.motion.y, &cx, &cy))
+ machine().ui_input().push_mouse_move_event(window->target(), cx, cy);
+ }
+ break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ mouse.buttons[sdlevent.button.button - 1] = 0x80;
+ //printf("But down %d %d %d %d %s\n", event.button.which, event.button.button, event.button.x, event.button.y, devinfo->name.c_str());
+ if (sdlevent.button.button == 1)
+ {
+ // FIXME Move static declaration
+ static osd_ticks_t last_click = 0;
+ static int last_x = 0;
+ static int last_y = 0;
+ int cx, cy;
+ osd_ticks_t click = osd_ticks() * 1000 / osd_ticks_per_second();
+ sdl_window_info *window = GET_FOCUS_WINDOW(&sdlevent.button);
+ if (window != NULL && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
+ {
+ machine().ui_input().push_mouse_down_event(window->target(), cx, cy);
+ // FIXME Parameter ?
+ if ((click - last_click < 250)
+ && (cx >= last_x - 4 && cx <= last_x + 4)
+ && (cy >= last_y - 4 && cy <= last_y + 4))
+ {
+ last_click = 0;
+ machine().ui_input().push_mouse_double_click_event(window->target(), cx, cy);
+ }
+ else
+ {
+ last_click = click;
+ last_x = cx;
+ last_y = cy;
+ }
+ }
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ mouse.buttons[sdlevent.button.button - 1] = 0;
+ //printf("But up %d %d %d %d\n", event.button.which, event.button.button, event.button.x, event.button.y);
+
+ if (sdlevent.button.button == 1)
+ {
+ int cx, cy;
+ sdl_window_info *window = GET_FOCUS_WINDOW(&sdlevent.button);
+
+ if (window != NULL && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
+ {
+ machine().ui_input().push_mouse_up_event(window->target(), cx, cy);
+ }
+ }
+ break;
+
+ case SDL_MOUSEWHEEL:
+ sdl_window_info *window = GET_FOCUS_WINDOW(&sdlevent.wheel);
+ if (window != NULL)
+ machine().ui_input().push_mouse_wheel_event(window->target(), 0, 0, sdlevent.wheel.y, 3);
+ break;
+ }
+ }
+};
+
+//============================================================
+// sdl_joystick_device
+//============================================================
+
+// state information for a joystick
+struct sdl_joystick_state
+{
+ INT32 axes[MAX_AXES];
+ INT32 buttons[MAX_BUTTONS];
+ INT32 hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS];
+ INT32 balls[MAX_AXES];
+};
+
+struct sdl_api_state
+{
+ SDL_Joystick *device;
+ SDL_JoystickID joystick_id;
+};
+
+class sdl_joystick_device : public sdl_device
+{
+public:
+ sdl_joystick_state joystick;
+ sdl_api_state sdl_state;
+
+ sdl_joystick_device(running_machine &machine, const char *name, input_module &module)
+ : sdl_device(machine, name, DEVICE_CLASS_JOYSTICK, module),
+ joystick({{0}}),
+ sdl_state({0})
+ {
+ }
+
+ ~sdl_joystick_device()
+ {
+ if (sdl_state.device != nullptr)
+ {
+ SDL_JoystickClose(sdl_state.device);
+ sdl_state.device = nullptr;
+ }
+ }
+
+ void reset() override
+ {
+ memset(&joystick, 0, sizeof(joystick));
+ }
+
+ void process_event(SDL_Event &sdlevent) override
+ {
+ switch (sdlevent.type)
+ {
+ case SDL_JOYAXISMOTION:
+ joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2);
+ break;
+
+ case SDL_JOYBALLMOTION:
+ //printf("Ball %d %d\n", sdlevent.jball.xrel, sdlevent.jball.yrel);
+ joystick.balls[sdlevent.jball.ball * 2] = sdlevent.jball.xrel * INPUT_RELATIVE_PER_PIXEL;
+ joystick.balls[sdlevent.jball.ball * 2 + 1] = sdlevent.jball.yrel * INPUT_RELATIVE_PER_PIXEL;
+ break;
+
+ case SDL_JOYHATMOTION:
+ if (sdlevent.jhat.value & SDL_HAT_UP)
+ {
+ joystick.hatsU[sdlevent.jhat.hat] = 0x80;
+ }
+ else
+ {
+ joystick.hatsU[sdlevent.jhat.hat] = 0;
+ }
+ if (sdlevent.jhat.value & SDL_HAT_DOWN)
+ {
+ joystick.hatsD[sdlevent.jhat.hat] = 0x80;
+ }
+ else
+ {
+ joystick.hatsD[sdlevent.jhat.hat] = 0;
+ }
+ if (sdlevent.jhat.value & SDL_HAT_LEFT)
+ {
+ joystick.hatsL[sdlevent.jhat.hat] = 0x80;
+ }
+ else
+ {
+ joystick.hatsL[sdlevent.jhat.hat] = 0;
+ }
+ if (sdlevent.jhat.value & SDL_HAT_RIGHT)
+ {
+ joystick.hatsR[sdlevent.jhat.hat] = 0x80;
+ }
+ else
+ {
+ joystick.hatsR[sdlevent.jhat.hat] = 0;
+ }
+ break;
+
+ case SDL_JOYBUTTONDOWN:
+ case SDL_JOYBUTTONUP:
+ joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0;
+ break;
+ }
+ }
+};
+
+class sdl_sixaxis_joystick_device : public sdl_joystick_device
+{
+public:
+ sdl_sixaxis_joystick_device(running_machine &machine, const char *name, input_module &module)
+ : sdl_joystick_device(machine, name, module)
+ {
+ }
+
+ void process_event(SDL_Event &sdlevent) override
+ {
+ switch (sdlevent.type)
+ {
+ case SDL_JOYAXISMOTION:
+ {
+ int axis = sdlevent.jaxis.axis;
+
+ if (axis <= 3)
+ {
+ joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2);
+ }
+ else
+ {
+ int magic = (sdlevent.jaxis.value / 2) + 16384;
+ joystick.axes[sdlevent.jaxis.axis] = magic;
+ }
+ }
+ break;
+
+ default:
+ // Call the base for other events
+ sdl_joystick_device::process_event(sdlevent);
+ break;
+ }
+ }
+};
+
+//============================================================
+// sdl_input_module
+//============================================================
+
+class sdl_input_module : public input_module_base, public sdl_event_subscriber
+{
+public:
+ sdl_input_module(const char *type)
+ : input_module_base(type, "sdl")
+ {
+ }
+
+ void input_init(running_machine &machine) override
+ {
+ if (machine.debug_flags & DEBUG_FLAG_OSD_ENABLED)
+ {
+ osd_printf_warning("Debug Build: Disabling input grab for -debug\n");
+ set_mouse_enabled(false);
+ }
+ }
+
+ void before_poll(running_machine& machine) override
+ {
+ // Tell the event manager to process events and push them to the devices
+ sdl_event_manager::instance().process_events(machine);
+ }
+
+ bool should_poll_devices(running_machine& machine) override
+ {
+ return sdl_event_manager::instance().app_has_mouse_focus() && input_enabled();
+ }
+
+ virtual void handle_event(SDL_Event &sdlevent) override
+ {
+ // By default dispatch event to every device
+ for (int i = 0; i < devicelist()->size(); i++)
+ downcast<sdl_device*>(devicelist()->at(i))->queue_events(&sdlevent, 1);
+ }
+};
+
+//============================================================
+// sdl_keyboard_module
+//============================================================
+
+class sdl_keyboard_module : public sdl_input_module
+{
+ keyboard_trans_table * m_key_trans_table;
+public:
+ sdl_keyboard_module()
+ : sdl_input_module(OSD_KEYBOARDINPUT_PROVIDER)
+ {
+ }
+
+ void input_init(running_machine &machine) override
+ {
+ sdl_input_module::input_init(machine);
+
+ SDL_EventType event_types[] = { SDL_KEYDOWN, SDL_KEYUP, SDL_TEXTINPUT };
+ sdl_event_manager::instance().subscribe(reinterpret_cast<int*>(event_types), ARRAY_LENGTH(event_types), this);
+
+ sdl_keyboard_device *devinfo;
+
+ // Read our keymap and store a pointer to our table
+ m_key_trans_table = sdlinput_read_keymap(machine);
+
+ keyboard_trans_table& local_table = *m_key_trans_table;
+
+ osd_printf_verbose("Keyboard: Start initialization\n");
+
+ // SDL only has 1 keyboard add it now
+ devinfo = devicelist()->create_device<sdl_keyboard_device>(machine, "System keyboard", *this);
+
+ // populate it
+ for (int keynum = 0; local_table[keynum].mame_key != ITEM_ID_INVALID; keynum++)
+ {
+ input_item_id itemid = local_table[keynum].mame_key;
+
+ // generate the default / modified name
+ char defname[20];
+ snprintf(defname, sizeof(defname) - 1, "%s", local_table[keynum].ui_name);
+
+ devinfo->device()->add_item(defname, itemid, generic_button_get_state, &devinfo->keyboard.state[local_table[keynum].sdl_scancode]);
+ }
+
+ osd_printf_verbose("Keyboard: Registered %s\n", devinfo->name());
+ osd_printf_verbose("Keyboard: End initialization\n");
+ }
+
+private:
+ static keyboard_trans_table* sdlinput_read_keymap(running_machine &machine)
+ {
+ char *keymap_filename;
+ FILE *keymap_file;
+ int line = 1;
+ int index, i, sk, vk, ak;
+ char buf[256];
+ char mks[41];
+ char sks[41];
+ char kns[41];
+ int sdl2section = 0;
+
+ keyboard_trans_table &default_table = keyboard_trans_table::instance();
+
+ if (!machine.options().bool_value(SDLOPTION_KEYMAP))
+ return &default_table;
+
+ keymap_filename = (char *)downcast<sdl_options &>(machine.options()).keymap_file();
+ osd_printf_verbose("Keymap: Start reading keymap_file %s\n", keymap_filename);
+
+ keymap_file = fopen(keymap_filename, "r");
+ if (keymap_file == NULL)
+ {
+ osd_printf_warning("Keymap: Unable to open keymap %s, using default\n", keymap_filename);
+ return &default_table;
+ }
+
+ // Allocate a block of translation entries big enough to hold what's in the default table
+ auto key_trans_entries = std::make_unique<key_trans_entry[]>(default_table.size());
+
+ // copy the elements from the default table
+ for (int i = 0; i < default_table.size(); i++)
+ key_trans_entries[i] = default_table[i];
+
+ // Allocate the trans table to be associated with the machine so we don't have to free it
+ keyboard_trans_table *custom_table = auto_alloc(machine, keyboard_trans_table(std::move(key_trans_entries), default_table.size()));
+
+ while (!feof(keymap_file))
+ {
+ char *ret = fgets(buf, 255, keymap_file);
+ if (ret && buf[0] != '\n' && buf[0] != '#')
+ {
+ buf[255] = 0;
+ i = strlen(buf);
+ if (i && buf[i - 1] == '\n')
+ buf[i - 1] = 0;
+ if (strncmp(buf, "[SDL2]", 6) == 0)
+ {
+ sdl2section = 1;
+ }
+ else if (((SDLMAME_SDL2) ^ sdl2section) == 0)
+ {
+ mks[0] = 0;
+ sks[0] = 0;
+ memset(kns, 0, ARRAY_LENGTH(kns));
+ sscanf(buf, "%40s %40s %x %x %40c\n",
+ mks, sks, &vk, &ak, kns);
+
+ index = default_table.lookup_mame_index(mks);
+ sk = lookup_sdl_code(sks);
+
+ if (sk >= 0 && index >= 0)
+ {
+ key_trans_entry &entry = (*custom_table)[index];
+ entry.sdl_key = sk;
+ // vk and ak are not really needed
+ //key_trans_table[index][VIRTUAL_KEY] = vk;
+ //key_trans_table[index][ASCII_KEY] = ak;
+ entry.ui_name = auto_alloc_array(machine, char, strlen(kns) + 1);
+ strcpy(entry.ui_name, kns);
+ osd_printf_verbose("Keymap: Mapped <%s> to <%s> with ui-text <%s>\n", sks, mks, kns);
+ }
+ else
+ osd_printf_warning("Keymap: Error on line %d - %s key not found: %s\n", line, (sk<0) ? "sdl" : "mame", buf);
+ }
+ }
+ line++;
+ }
+ fclose(keymap_file);
+ osd_printf_verbose("Keymap: Processed %d lines\n", line);
+
+ return custom_table;
+ }
+};
+
+//============================================================
+// sdl_mouse_module
+//============================================================
+
+class sdl_mouse_module : public sdl_input_module
+{
+public:
+ sdl_mouse_module()
+ : sdl_input_module(OSD_MOUSEINPUT_PROVIDER)
+ {
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ sdl_input_module::input_init(machine);
+
+ SDL_EventType event_types[] = { SDL_MOUSEMOTION, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP, SDL_MOUSEWHEEL };
+ sdl_event_manager::instance().subscribe(reinterpret_cast<int*>(event_types), ARRAY_LENGTH(event_types), this);
+
+ sdl_mouse_device *devinfo;
+ char defname[20];
+ int button;
+
+ osd_printf_verbose("Mouse: Start initialization\n");
+
+ // SDL currently only supports one mouse
+ devinfo = devicelist()->create_device<sdl_mouse_device>(machine, "System mouse", *this);
+
+ // add the axes
+ devinfo->device()->add_item("X", ITEM_ID_XAXIS, generic_axis_get_state, &devinfo->mouse.lX);
+ devinfo->device()->add_item("Y", ITEM_ID_YAXIS, generic_axis_get_state, &devinfo->mouse.lY);
+
+ for (button = 0; button < 4; button++)
+ {
+ input_item_id itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
+ snprintf(defname, sizeof(defname), "B%d", button + 1);
+
+ devinfo->device()->add_item(defname, itemid, generic_button_get_state, &devinfo->mouse.buttons[button]);
+ }
+
+ osd_printf_verbose("Mouse: Registered %s\n", devinfo->name());
+ osd_printf_verbose("Mouse: End initialization\n");
+ }
+};
+
+
+static void devmap_register(device_map_t *devmap, int physical_idx, const std::string &name)
+{
+ int found = 0;
+ int stick, i;
+
+ for (i = 0; i < MAX_DEVMAP_ENTRIES; i++)
+ {
+ if (strcmp(name.c_str(), devmap->map[i].name.c_str()) == 0 && devmap->map[i].physical < 0)
+ {
+ devmap->map[i].physical = physical_idx;
+ found = 1;
+ devmap->logical[physical_idx] = i;
+ }
+ }
+
+ if (found == 0)
+ {
+ stick = devmap_leastfree(devmap);
+ devmap->map[stick].physical = physical_idx;
+ devmap->map[stick].name = name;
+ devmap->logical[physical_idx] = stick;
+ }
+
+}
+
+//============================================================
+// sdl_joystick_module
+//============================================================
+
+class sdl_joystick_module : public sdl_input_module
+{
+private:
+ device_map_t m_joy_map;
+ bool m_sixaxis_mode;
+public:
+ sdl_joystick_module()
+ : sdl_input_module(OSD_JOYSTICKINPUT_PROVIDER)
+ {
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ sdl_input_module::input_init(machine);
+
+ char tempname[512];
+
+ m_sixaxis_mode = downcast<const sdl_options*>(options())->sixaxis();
+
+ devmap_init(machine, &m_joy_map, SDLOPTION_JOYINDEX, 8, "Joystick mapping");
+
+ osd_printf_verbose("Joystick: Start initialization\n");
+ int physical_stick;
+ for (physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++)
+ {
+ SDL_Joystick *joy = SDL_JoystickOpen(physical_stick);
+ std::string joy_name = remove_spaces(SDL_JoystickName(joy));
+ SDL_JoystickClose(joy);
+
+ devmap_register(&m_joy_map, physical_stick, joy_name.c_str());
+ }
+
+ for (int stick = 0; stick < MAX_DEVMAP_ENTRIES; stick++)
+ {
+ sdl_joystick_device *devinfo = create_joystick_device(machine, &m_joy_map, stick, DEVICE_CLASS_JOYSTICK);
+
+ if (devinfo == NULL)
+ continue;
+
+ physical_stick = m_joy_map.map[stick].physical;
+
+ SDL_Joystick *joy = SDL_JoystickOpen(physical_stick);
+
+ devinfo->sdl_state.device = joy;
+ devinfo->sdl_state.joystick_id = SDL_JoystickInstanceID(joy);
+
+ osd_printf_verbose("Joystick: %s\n", devinfo->name());
+ osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy));
+ osd_printf_verbose("Joystick: ... Physical id %d mapped to logical id %d\n", physical_stick, stick + 1);
+
+ // loop over all axes
+ for (int axis = 0; axis < SDL_JoystickNumAxes(joy); axis++)
+ {
+ input_item_id itemid;
+
+ if (axis < INPUT_MAX_AXIS)
+ itemid = (input_item_id)(ITEM_ID_XAXIS + axis);
+ else if (axis < INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE)
+ itemid = (input_item_id)(ITEM_ID_ADD_ABSOLUTE1 - INPUT_MAX_AXIS + axis);
+ else
+ itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE;
+
+ snprintf(tempname, sizeof(tempname), "A%d %s", axis, devinfo->name());
+ devinfo->device()->add_item(tempname, itemid, generic_axis_get_state, &devinfo->joystick.axes[axis]);
+ }
+
+ // loop over all buttons
+ for (int button = 0; button < SDL_JoystickNumButtons(joy); button++)
+ {
+ input_item_id itemid;
+
+ devinfo->joystick.buttons[button] = 0;
+
+ if (button < INPUT_MAX_BUTTONS)
+ itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
+ else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
+ itemid = (input_item_id)(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + button);
+ else
+ itemid = ITEM_ID_OTHER_SWITCH;
+
+ snprintf(tempname, sizeof(tempname), "button %d", button);
+ devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.buttons[button]);
+ }
+
+ // loop over all hats
+ for (int hat = 0; hat < SDL_JoystickNumHats(joy); hat++)
+ {
+ input_item_id itemid;
+
+ snprintf(tempname, sizeof(tempname), "hat %d Up", hat);
+ itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH);
+ devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsU[hat]);
+ snprintf(tempname, sizeof(tempname), "hat %d Down", hat);
+ itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH);
+ devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsD[hat]);
+ snprintf(tempname, sizeof(tempname), "hat %d Left", hat);
+ itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH);
+ devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsL[hat]);
+ snprintf(tempname, sizeof(tempname), "hat %d Right", hat);
+ itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH);
+ devinfo->device()->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsR[hat]);
+ }
+
+ // loop over all (track)balls
+ for (int ball = 0; ball < SDL_JoystickNumBalls(joy); ball++)
+ {
+ int itemid;
+
+ if (ball * 2 < INPUT_MAX_ADD_RELATIVE)
+ itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2;
+ else
+ itemid = ITEM_ID_OTHER_AXIS_RELATIVE;
+
+ snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2, devinfo->name());
+ devinfo->device()->add_item(tempname, (input_item_id)itemid, generic_axis_get_state, &devinfo->joystick.balls[ball * 2]);
+ snprintf(tempname, sizeof(tempname), "R%d %s", ball * 2 + 1, devinfo->name());
+ devinfo->device()->add_item(tempname, (input_item_id)(itemid + 1), generic_axis_get_state, &devinfo->joystick.balls[ball * 2 + 1]);
+ }
+ }
+
+ SDL_EventType event_types[] = { SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP };
+ sdl_event_manager::instance().subscribe(reinterpret_cast<int*>(event_types), ARRAY_LENGTH(event_types), this);
+
+ osd_printf_verbose("Joystick: End initialization\n");
+ }
+
+ virtual void handle_event(SDL_Event &sdlevent) override
+ {
+ // Figure out which joystick this event id destined for
+ for (int i = 0; i < devicelist()->size(); i++)
+ {
+ auto joy = downcast<sdl_joystick_device*>(devicelist()->at(i));
+
+ // If we find a matching joystick, dispatch the event to the joystick
+ if (joy->sdl_state.joystick_id == sdlevent.jdevice.which)
+ joy->queue_events(&sdlevent, 1);
+ }
+ }
+
+private:
+ sdl_joystick_device* create_joystick_device(running_machine &machine, device_map_t *devmap, int index, input_device_class devclass)
+ {
+ sdl_joystick_device *devinfo = NULL;
+ char tempname[20];
+
+ if (devmap->map[index].name.length() == 0)
+ {
+ /* only map place holders if there were mappings specified is enabled */
+ if (devmap->initialized)
+ {
+ snprintf(tempname, ARRAY_LENGTH(tempname), "NC%d", index);
+ devinfo = m_sixaxis_mode
+ ? devicelist()->create_device<sdl_sixaxis_joystick_device>(machine, tempname, *this)
+ : devicelist()->create_device<sdl_joystick_device>(machine, tempname, *this);
+ }
+
+ return NULL;
+ }
+ else
+ {
+ devinfo = m_sixaxis_mode
+ ? devicelist()->create_device<sdl_sixaxis_joystick_device>(machine, devmap->map[index].name.c_str(), *this)
+ : devicelist()->create_device<sdl_joystick_device>(machine, devmap->map[index].name.c_str(), *this);
+ }
+
+ return devinfo;
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(sdl_keyboard_module, OSD_KEYBOARDINPUT_PROVIDER, "sdl")
+MODULE_NOT_SUPPORTED(sdl_mouse_module, OSD_MOUSEINPUT_PROVIDER, "sdl")
+MODULE_NOT_SUPPORTED(sdl_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "sdl")
+#endif
+
+MODULE_DEFINITION(KEYBOARDINPUT_SDL, sdl_keyboard_module)
+MODULE_DEFINITION(MOUSEINPUT_SDL, sdl_mouse_module)
+MODULE_DEFINITION(JOYSTICKINPUT_SDL, sdl_joystick_module) \ No newline at end of file
diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp
new file mode 100644
index 00000000000..e22606f9fb3
--- /dev/null
+++ b/src/osd/modules/input/input_sdlcommon.cpp
@@ -0,0 +1,283 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_sdlcommon.cpp - SDL Common code shared by SDL modules
+//
+// Note: this code is also used by the X11 input modules
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(OSD_SDL)
+
+// standard sdl header
+#include "sdlinc.h"
+#include <ctype.h>
+#include <stddef.h>
+#include <mutex>
+#include <memory>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "uiinput.h"
+#include "window.h"
+#include "strconv.h"
+
+#include "../../sdl/osdsdl.h"
+#include "input_common.h"
+#include "input_sdlcommon.h"
+
+#define GET_WINDOW(ev) window_from_id((ev)->windowID)
+//#define GET_WINDOW(ev) ((ev)->windowID)
+
+static inline sdl_window_info * window_from_id(Uint32 windowID)
+{
+ sdl_window_info *w;
+ SDL_Window *window = SDL_GetWindowFromID(windowID);
+
+ for (w = sdl_window_list; w != NULL; w = w->m_next)
+ {
+ //printf("w->window_id: %d\n", w->window_id);
+ if (w->sdl_window() == window)
+ {
+ return w;
+ }
+ }
+ return NULL;
+}
+
+void sdl_event_manager::process_events(running_machine &machine)
+{
+ std::lock_guard<std::mutex> scope_lock(m_lock);
+ SDL_Event sdlevent;
+ while (SDL_PollEvent(&sdlevent))
+ {
+ // process window events if they come in
+ if (sdlevent.type == SDL_WINDOWEVENT)
+ process_window_event(machine, sdlevent);
+
+ // Find all subscribers for the event type
+ auto subscribers = m_subscription_index.equal_range(sdlevent.type);
+
+ // Dispatch the events
+ for (auto iter = subscribers.first; iter != subscribers.second; iter++)
+ iter->second->handle_event(sdlevent);
+ }
+}
+
+void sdl_event_manager::process_window_event(running_machine &machine, SDL_Event &sdlevent)
+{
+ sdl_window_info *window = GET_WINDOW(&sdlevent.window);
+
+ if (window == NULL)
+ return;
+
+ switch (sdlevent.window.event)
+ {
+ case SDL_WINDOWEVENT_CLOSE:
+ machine.schedule_exit();
+ break;
+
+ case SDL_WINDOWEVENT_LEAVE:
+ machine.ui_input().push_mouse_leave_event(window->target());
+ m_app_has_mouse_focus = 0;
+ break;
+
+ case SDL_WINDOWEVENT_MOVED:
+ window->notify_changed();
+ m_focus_window = window;
+ break;
+
+ case SDL_WINDOWEVENT_RESIZED:
+#ifndef SDLMAME_WIN32
+ /* FIXME: SDL2 sends some spurious resize events on Ubuntu
+ * while in fullscreen mode. Ignore them for now.
+ */
+ if (!window->fullscreen())
+#endif
+ {
+ //printf("event data1,data2 %d x %d %ld\n", event.window.data1, event.window.data2, sizeof(SDL_Event));
+ window->resize(sdlevent.window.data1, sdlevent.window.data2);
+ }
+ m_focus_window = window;
+ break;
+
+ case SDL_WINDOWEVENT_ENTER:
+ m_app_has_mouse_focus = 1;
+ /* fall through */
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ case SDL_WINDOWEVENT_EXPOSED:
+ case SDL_WINDOWEVENT_MAXIMIZED:
+ case SDL_WINDOWEVENT_RESTORED:
+ m_focus_window = window;
+ break;
+ }
+}
+
+//============================================================
+// customize_input_type_list
+//============================================================
+
+void sdl_osd_interface::customize_input_type_list(simple_list<input_type_entry> &typelist)
+{
+ input_item_id mameid_code;
+ input_code ui_code;
+ input_type_entry *entry;
+ const char* uimode;
+ char fullmode[64];
+
+ // loop over the defaults
+ for (entry = typelist.first(); entry != NULL; entry = entry->next())
+ {
+ switch (entry->type())
+ {
+ // configurable UI mode switch
+ case IPT_UI_TOGGLE_UI:
+ uimode = options().ui_mode_key();
+ if (!strcmp(uimode, "auto"))
+ {
+#if defined(__APPLE__) && defined(__MACH__)
+ mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_INSERT");
+#else
+ mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_SCRLOCK");
+#endif
+ }
+ else
+ {
+ snprintf(fullmode, 63, "ITEM_ID_%s", uimode);
+ mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode);
+ }
+ 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);
+ break;
+
+ // disable UI_SELECT when LALT is down, this stops selecting
+ // things in the menu when toggling fullscreen with LALT+ENTER
+ /* case IPT_UI_SELECT:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT);
+ break;*/
+
+ // page down for fastforward (must be OSD_3 as per src/emu/ui.c)
+ case IPT_UI_FAST_FORWARD:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_PGDN);
+ break;
+
+ // OSD hotkeys use LCTRL and start at F3, they start at
+ // F3 because F1-F2 are hardcoded into many drivers to
+ // various dipswitches, and pressing them together with
+ // LCTRL will still press/toggle these dipswitches.
+
+ // LCTRL-F3 to toggle fullstretch
+ case IPT_OSD_2:
+ entry->configure_osd("TOGGLE_FULLSTRETCH", "Toggle Uneven stretch");
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F3, KEYCODE_LCONTROL);
+ break;
+ // add a Not lcrtl condition to the reset key
+ case IPT_UI_SOFT_RESET:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F3, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
+ break;
+
+ // LCTRL-F4 to toggle keep aspect
+ case IPT_OSD_4:
+ entry->configure_osd("TOGGLE_KEEP_ASPECT", "Toggle Keepaspect");
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F4, KEYCODE_LCONTROL);
+ break;
+ // add a Not lcrtl condition to the show gfx key
+ case IPT_UI_SHOW_GFX:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F4, input_seq::not_code, KEYCODE_LCONTROL);
+ break;
+
+ // LCTRL-F5 to toggle OpenGL filtering
+ case IPT_OSD_5:
+ entry->configure_osd("TOGGLE_FILTER", "Toggle Filter");
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LCONTROL);
+ break;
+ // add a Not lcrtl condition to the toggle debug key
+ case IPT_UI_TOGGLE_DEBUG:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, input_seq::not_code, KEYCODE_LCONTROL);
+ break;
+
+ // LCTRL-F6 to decrease OpenGL prescaling
+ case IPT_OSD_6:
+ entry->configure_osd("DECREASE_PRESCALE", "Decrease Prescaling");
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, KEYCODE_LCONTROL);
+ break;
+ // add a Not lcrtl condition to the toggle cheat key
+ case IPT_UI_TOGGLE_CHEAT:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, input_seq::not_code, KEYCODE_LCONTROL);
+ break;
+
+ // LCTRL-F7 to increase OpenGL prescaling
+ case IPT_OSD_7:
+ entry->configure_osd("INCREASE_PRESCALE", "Increase Prescaling");
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, KEYCODE_LCONTROL);
+ break;
+ // add a Not lcrtl condition to the load state key
+ case IPT_UI_LOAD_STATE:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
+ break;
+
+ // add a Not lcrtl condition to the throttle key
+ case IPT_UI_THROTTLE:
+ entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, input_seq::not_code, KEYCODE_LCONTROL);
+ break;
+
+ // disable the config menu if the ALT key is down
+ // (allows ALT-TAB to switch between 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;
+
+ // leave everything else alone
+ default:
+ break;
+ }
+ }
+}
+
+void sdl_osd_interface::poll_inputs(running_machine &machine)
+{
+ m_keyboard_input->poll_if_necessary(machine);
+ m_mouse_input->poll_if_necessary(machine);
+ m_lightgun_input->poll_if_necessary(machine);
+ m_joystick_input->poll_if_necessary(machine);
+}
+
+void sdl_osd_interface::release_keys()
+{
+ downcast<input_module_base*>(m_keyboard_input)->devicelist()->reset_devices();
+}
+
+bool sdl_osd_interface::should_hide_mouse()
+{
+ // if we are paused, no
+ if (machine().paused())
+ return false;
+
+ // if neither mice nor lightguns enabled in the core, then no
+ if (!options().mouse() && !options().lightgun())
+ return false;
+
+ if (!sdl_event_manager::instance().app_has_mouse_focus())
+ return false;
+
+ // otherwise, yes
+ return true;
+}
+
+void sdl_osd_interface::process_events_buf()
+{
+ SDL_PumpEvents();
+}
+
+#endif \ No newline at end of file
diff --git a/src/osd/modules/input/input_sdlcommon.h b/src/osd/modules/input/input_sdlcommon.h
new file mode 100644
index 00000000000..a4bde246967
--- /dev/null
+++ b/src/osd/modules/input/input_sdlcommon.h
@@ -0,0 +1,204 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_sdlcommon.h - SDL Common code shared by SDL modules
+//
+// Note: this code is also used by the X11 input modules
+//
+//============================================================
+
+#ifndef INPUT_SDLCOMMON_H_
+#define INPUT_SDLCOMMON_H_
+
+#include <vector>
+#include <unordered_map>
+#include <algorithm>
+#include <queue>
+
+#define MAX_DEVMAP_ENTRIES 16
+#define SDL_MODULE_EVENT_BUFFER_SIZE 5
+
+// state information for a keyboard
+struct keyboard_state
+{
+ INT32 state[0x3ff]; // must be INT32!
+ INT8 oldkey[MAX_KEYS];
+ INT8 currkey[MAX_KEYS];
+};
+
+// state information for a mouse
+struct mouse_state
+{
+ INT32 lX, lY;
+ INT32 buttons[MAX_BUTTONS];
+};
+
+
+// state information for a joystick; DirectInput state must be first element
+struct joystick_state
+{
+ SDL_Joystick *device;
+ INT32 axes[MAX_AXES];
+ INT32 buttons[MAX_BUTTONS];
+ INT32 hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS];
+ INT32 balls[MAX_AXES];
+};
+
+struct device_map_t
+{
+ struct {
+ std::string name;
+ int physical;
+ } map[MAX_DEVMAP_ENTRIES];
+ int logical[MAX_DEVMAP_ENTRIES];
+ int initialized;
+};
+
+//============================================================
+// event_manager_t
+//============================================================
+
+class sdl_event_subscriber
+{
+public:
+ virtual void handle_event(SDL_Event &sdlevent) = 0;
+};
+
+template <class TSubscriber>
+class event_manager_t
+{
+protected:
+ std::mutex m_lock;
+ std::unordered_multimap<int, TSubscriber*> m_subscription_index;
+ event_manager_t()
+ {
+ }
+
+public:
+ void subscribe(int* event_types, int num_event_types, TSubscriber *subscriber)
+ {
+ std::lock_guard<std::mutex> scope_lock(m_lock);
+
+ // Add the subscription
+ for (int i = 0; i < num_event_types; i++)
+ {
+ m_subscription_index.emplace(event_types[i], subscriber);
+ }
+ }
+
+ void unsubscribe(TSubscriber *subscriber)
+ {
+ std::lock_guard<std::mutex> scope_lock(m_lock);
+
+ // Loop over the entries and find ones that match our subscriber
+ // remove those that match
+ for (auto iter = m_subscription_index.begin(); iter != m_subscription_index.end(); iter++)
+ {
+ if (iter->second == subscriber)
+ m_subscription_index.erase(iter);
+ }
+ }
+
+ virtual void process_events(running_machine &machine) = 0;
+};
+
+class sdl_window_info;
+
+// REVIEW: Do we need to handle SDLMAME_EVENTS_IN_WORKER_THREAD eventually?
+class sdl_event_manager : public event_manager_t<sdl_event_subscriber>
+{
+private:
+ bool m_app_has_mouse_focus;
+ sdl_window_info * m_focus_window;
+
+ sdl_event_manager()
+ : m_app_has_mouse_focus(true),
+ m_focus_window(nullptr)
+ {
+ }
+
+public:
+ bool app_has_mouse_focus() { return m_app_has_mouse_focus; }
+ sdl_window_info * focus_window() { return m_focus_window; }
+
+ static sdl_event_manager& instance()
+ {
+ static sdl_event_manager s_instance;
+ return s_instance;
+ }
+
+ void process_events(running_machine &machine) override;
+
+private:
+ void process_window_event(running_machine &machine, SDL_Event &sdlevent);
+};
+
+//============================================================
+// INLINE FUNCTIONS
+//============================================================
+
+static inline int devmap_leastfree(device_map_t *devmap)
+{
+ int i;
+ for (i = 0; i < MAX_DEVMAP_ENTRIES; i++)
+ {
+ if (devmap->map[i].name.length() == 0)
+ return i;
+ }
+ return -1;
+}
+
+static inline std::string remove_spaces(const char *s)
+{
+ // Remove the spaces
+ auto output = std::string(s);
+ output.erase(std::remove_if(output.begin(), output.end(), isspace), output.end());
+
+ return output;
+}
+
+//============================================================
+// devmap_init - initializes a device_map based on
+// an input option prefix and max number of devices
+//============================================================
+
+static inline void devmap_init(running_machine &machine, device_map_t *devmap, const char *opt, int max_devices, const char *label)
+{
+ int dev;
+ char defname[20];
+
+ // The max devices the user specified, better not be bigger than the max the arrays can old
+ assert(max_devices <= MAX_DEVMAP_ENTRIES);
+
+ // Initialize the map to default uninitialized values
+ for (dev = 0; dev < MAX_DEVMAP_ENTRIES; dev++)
+ {
+ devmap->map[dev].physical = -1;
+ devmap->logical[dev] = -1;
+ }
+ devmap->initialized = 0;
+
+ // populate the device map up to the max number of devices
+ for (dev = 0; dev < max_devices; dev++)
+ {
+ const char *dev_name;
+
+ // derive the parameter name from the option name and index. For instance: lightgun_index1 to lightgun_index8
+ sprintf(defname, "%s%d", opt, dev + 1);
+
+ // Get the user-specified name that matches the parameter
+ dev_name = machine.options().value(defname);
+
+ // If they've specified a name and it's not "auto", treat it as a custom mapping
+ if (dev_name && *dev_name && strcmp(dev_name, OSDOPTVAL_AUTO))
+ {
+ // remove the spaces from the name store it in the index
+ devmap->map[dev].name = remove_spaces(dev_name);
+ osd_printf_verbose("%s: Logical id %d: %s\n", label, dev + 1, devmap->map[dev].name.c_str());
+ devmap->initialized = 1;
+ }
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/osd/modules/input/input_win32.cpp b/src/osd/modules/input/input_win32.cpp
new file mode 100644
index 00000000000..f0477a414fc
--- /dev/null
+++ b/src/osd/modules/input/input_win32.cpp
@@ -0,0 +1,427 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Brad Hughes
+//============================================================
+//
+// input_win32.cpp - Win32 input implementation
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#undef interface
+
+#include <mutex>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+#include "strconv.h"
+
+// MAMEOS headers
+#include "winmain.h"
+#include "window.h"
+#include "../../windows/input.h"
+
+#include "input_common.h"
+#include "input_windows.h"
+
+//============================================================
+// win32_keyboard_device
+//============================================================
+
+// This device is purely event driven so the implementation is in the module
+class win32_keyboard_device : public event_based_device<KeyPressEventArgs>
+{
+public:
+ keyboard_state keyboard;
+
+ win32_keyboard_device(running_machine& machine, const char *name, input_module &module)
+ : event_based_device(machine, name, DEVICE_CLASS_KEYBOARD, module),
+ keyboard({0})
+ {
+ }
+
+ void reset() override
+ {
+ memset(&keyboard, 0, sizeof(keyboard));
+ }
+
+protected:
+ void process_event(KeyPressEventArgs &args) override
+ {
+ keyboard.state[args.scancode] = args.event_id == INPUT_EVENT_KEYDOWN ? 0x80 : 0x00;
+ }
+};
+
+//============================================================
+// keyboard_input_win32 - win32 keyboard input module
+//============================================================
+
+class keyboard_input_win32 : public wininput_module
+{
+private:
+ const osd_options * m_options;
+
+public:
+ keyboard_input_win32()
+ : wininput_module(OSD_KEYBOARDINPUT_PROVIDER, "win32")
+ {
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ // Add a single win32 keyboard device that we'll monitor using Win32
+ win32_keyboard_device *devinfo = devicelist()->create_device<win32_keyboard_device>(machine, "Win32 Keyboard 1", *this);
+
+ keyboard_trans_table &table = keyboard_trans_table::instance();
+
+ // populate it
+ for (int keynum = 0; keynum < MAX_KEYS; keynum++)
+ {
+ input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
+ char name[20];
+
+ // generate/fetch the name
+ _snprintf(name, ARRAY_LENGTH(name), "Scan%03d", keynum);
+
+ // add the item to the device
+ devinfo->device()->add_item(name, itemid, generic_button_get_state, &devinfo->keyboard.state[keynum]);
+ }
+ }
+
+ bool handle_input_event(input_event eventid, void *eventdata) override
+ {
+ if (!input_enabled())
+ return FALSE;
+
+ KeyPressEventArgs *args = nullptr;
+
+ switch (eventid)
+ {
+ case INPUT_EVENT_KEYDOWN:
+ case INPUT_EVENT_KEYUP:
+ args = (KeyPressEventArgs*)eventdata;
+ for (int i = 0; i < devicelist()->size(); i++)
+ downcast<win32_keyboard_device*>(devicelist()->at(i))->queue_events(args, 1);
+
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+};
+
+//============================================================
+// win32_mouse_device
+//============================================================
+
+struct win32_mouse_state
+{
+ POINT last_point;
+};
+
+class win32_mouse_device : public event_based_device<MouseButtonEventArgs>
+{
+public:
+ mouse_state mouse;
+ win32_mouse_state win32_mouse;
+
+ win32_mouse_device(running_machine& machine, const char *name, input_module &module)
+ : event_based_device(machine, name, DEVICE_CLASS_MOUSE, module),
+ mouse({0}),
+ win32_mouse({0})
+ {
+ }
+
+ void poll() override
+ {
+ event_based_device::poll();
+
+ CURSORINFO cursor_info = {0};
+ cursor_info.cbSize = sizeof(CURSORINFO);
+ GetCursorInfo(&cursor_info);
+
+ // We only take over the mouse if the cursor isn't showing
+ // This should happen anyway in mouse mode
+ if (!(cursor_info.flags & CURSOR_SHOWING))
+ {
+ // We measure the position change from the previously set center position
+ mouse.lX = (cursor_info.ptScreenPos.x - win32_mouse.last_point.x) * INPUT_RELATIVE_PER_PIXEL;
+ mouse.lY = (cursor_info.ptScreenPos.y - win32_mouse.last_point.y) * INPUT_RELATIVE_PER_PIXEL;
+
+ RECT window_pos = {0};
+ GetWindowRect(win_window_list->m_hwnd, &window_pos);
+
+ // We reset the cursor position to the middle of the window each frame
+ win32_mouse.last_point.x = window_pos.left + (window_pos.right - window_pos.left) / 2;
+ win32_mouse.last_point.y = window_pos.top + (window_pos.bottom - window_pos.top) / 2;
+
+ SetCursorPos(win32_mouse.last_point.x, win32_mouse.last_point.y);
+ }
+ }
+
+ void reset() override
+ {
+ memset(&mouse, 0, sizeof(mouse));
+ }
+
+protected:
+ void process_event(MouseButtonEventArgs &args)
+ {
+ // set the button state
+ mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
+
+ // Make sure we have a fresh mouse position on button down
+ if (args.keydown)
+ module().poll_if_necessary(machine());
+ }
+};
+
+//============================================================
+// mouse_input_win32 - win32 mouse input module
+//============================================================
+
+class mouse_input_win32 : public wininput_module
+{
+private:
+ const osd_options * m_options;
+
+public:
+ mouse_input_win32()
+ : wininput_module(OSD_MOUSEINPUT_PROVIDER, "win32")
+ {
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ win32_mouse_device *devinfo;
+ int axisnum, butnum;
+
+ if (!input_enabled() || !mouse_enabled())
+ return;
+
+ // allocate a device
+ devinfo = devicelist()->create_device<win32_mouse_device>(machine, "Win32 Mouse 1", *this);
+ if (devinfo == NULL)
+ return;
+
+ // populate the axes
+ for (axisnum = 0; axisnum < 2; axisnum++)
+ {
+ devinfo->device()->add_item(default_axis_name[axisnum], (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (butnum = 0; butnum < 2; butnum++)
+ {
+ devinfo->device()->add_item(default_button_name(butnum), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
+ }
+ }
+
+ bool handle_input_event(input_event eventid, void *eventdata) override
+ {
+ if (!input_enabled() || !mouse_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
+ return FALSE;
+
+ auto args = static_cast<MouseButtonEventArgs*>(eventdata);
+ for (int i = 0; i < devicelist()->size(); i++)
+ downcast<win32_mouse_device*>(devicelist()->at(i))->queue_events(args, 1);
+
+ return TRUE;
+ }
+};
+
+//============================================================
+// win32_lightgun_device
+//============================================================
+
+class win32_lightgun_device : public event_based_device<MouseButtonEventArgs>
+{
+private:
+ BOOL m_lightgun_shared_axis_mode;
+ int m_gun_index;
+
+public:
+ mouse_state mouse;
+
+ win32_lightgun_device(running_machine& machine, const char *name, input_module &module)
+ : event_based_device(machine, name, DEVICE_CLASS_LIGHTGUN, module),
+ m_lightgun_shared_axis_mode(FALSE),
+ m_gun_index(0)
+ {
+ m_lightgun_shared_axis_mode = downcast<windows_options &>(machine.options()).dual_lightgun();
+
+ // Since we are about to be added to the list, the current size is the zero-based index of where we will be
+ m_gun_index = downcast<wininput_module&>(module).devicelist()->size();
+ }
+
+ void poll() override
+ {
+ event_based_device::poll();
+
+ INT32 xpos = 0, ypos = 0;
+ POINT mousepos;
+
+ // if we are using the shared axis hack, the data is updated via Windows messages only
+ if (m_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
+ mouse.lX = xpos;
+ mouse.lY = ypos;
+ }
+
+ void reset() override
+ {
+ memset(&mouse, 0, sizeof(mouse));
+ }
+
+protected:
+ void process_event(MouseButtonEventArgs &args)
+ {
+ // Are we in shared axis mode?
+ if (m_lightgun_shared_axis_mode)
+ {
+ handle_shared_axis_mode(args);
+ }
+ else
+ {
+ // In non-shared axis mode, just update the button state
+ mouse.rgbButtons[args.button] = args.keydown ? 0x80 : 0x00;
+ }
+ }
+
+private:
+ void handle_shared_axis_mode(MouseButtonEventArgs &args)
+ {
+ int button = args.button;
+
+ // We only handle the first four buttons in shared axis mode
+ if (button > 3)
+ return;
+
+ // First gun doesn't handle buttons 2 & 3
+ if (button >= 2 && m_gun_index == 0)
+ return;
+
+ // Second gun doesn't handle buttons 0 & 1
+ if (button < 2 && m_gun_index == 1)
+ return;
+
+ // Adjust the button if we're the second lightgun
+ int logical_button = m_gun_index == 1 ? button - 2 : button;
+
+ // set the button state
+ mouse.rgbButtons[logical_button] = args.keydown ? 0x80 : 0x00;
+ if (args.keydown)
+ {
+ RECT client_rect;
+ POINT mousepos;
+
+ // get the position relative to the window
+ GetClientRect(win_window_list->m_hwnd, &client_rect);
+ mousepos.x = args.xpos;
+ mousepos.y = args.ypos;
+ ScreenToClient(win_window_list->m_hwnd, &mousepos);
+
+ // convert to absolute coordinates
+ mouse.lX = normalize_absolute_axis(mousepos.x, client_rect.left, client_rect.right);
+ mouse.lY = normalize_absolute_axis(mousepos.y, client_rect.top, client_rect.bottom);
+ }
+ }
+};
+
+//============================================================
+// lightgun_input_win32 - win32 lightgun input module
+//============================================================
+
+class lightgun_input_win32 : public wininput_module
+{
+public:
+ lightgun_input_win32()
+ : wininput_module(OSD_LIGHTGUNINPUT_PROVIDER, "win32")
+ {
+ }
+
+ int init_internal() override
+ {
+ return 0;
+ }
+
+ virtual void input_init(running_machine &machine) override
+ {
+ int max_guns = downcast<windows_options&>(machine.options()).dual_lightgun() ? 2 : 1;
+
+ // allocate the lightgun devices
+ for (int gunnum = 0; gunnum < max_guns; gunnum++)
+ {
+ static const char *const gun_names[] = { "Win32 Gun 1", "Win32 Gun 2" };
+ win32_lightgun_device *devinfo;
+ int axisnum, butnum;
+
+ // allocate a device
+ devinfo = devicelist()->create_device<win32_lightgun_device>(machine, gun_names[gunnum], *this);
+ if (devinfo == NULL)
+ break;
+
+ // populate the axes
+ for (axisnum = 0; axisnum < 2; axisnum++)
+ {
+ devinfo->device()->add_item(default_axis_name[axisnum], (input_item_id)(ITEM_ID_XAXIS + axisnum), generic_axis_get_state, &devinfo->mouse.lX + axisnum);
+ }
+
+ // populate the buttons
+ for (butnum = 0; butnum < 2; butnum++)
+ {
+ devinfo->device()->add_item(default_button_name(butnum), (input_item_id)(ITEM_ID_BUTTON1 + butnum), generic_button_get_state, &devinfo->mouse.rgbButtons[butnum]);
+ }
+ }
+ }
+
+ bool handle_input_event(input_event eventid, void* eventdata) override
+ {
+ if (!input_enabled() || !lightgun_enabled() || eventid != INPUT_EVENT_MOUSE_BUTTON)
+ return false;
+
+ for (int i = 0; i < devicelist()->size(); i++)
+ downcast<win32_lightgun_device*>(devicelist()->at(i))->queue_events(static_cast<MouseButtonEventArgs*>(eventdata), 1);
+
+ return true;
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(keyboard_input_win32, OSD_KEYBOARDINPUT_PROVIDER, "win32")
+MODULE_NOT_SUPPORTED(mouse_input_win32, OSD_MOUSEINPUT_PROVIDER, "win32")
+MODULE_NOT_SUPPORTED(lightgun_input_win32, OSD_LIGHTGUNINPUT_PROVIDER, "win32")
+#endif
+
+MODULE_DEFINITION(KEYBOARDINPUT_WIN32, keyboard_input_win32)
+MODULE_DEFINITION(MOUSEINPUT_WIN32, mouse_input_win32)
+MODULE_DEFINITION(LIGHTGUNINPUT_WIN32, lightgun_input_win32)
+
diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp
new file mode 100644
index 00000000000..d5761d37708
--- /dev/null
+++ b/src/osd/modules/input/input_windows.cpp
@@ -0,0 +1,144 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Brad Hughes
+//============================================================
+//
+// input_windows.cpp - Common code used by Windows input modules
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#undef interface
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+#include "ui/ui.h"
+
+// MAMEOS headers
+#include "winmain.h"
+#include "window.h"
+#include "../../windows/input.h"
+
+#include "input_common.h"
+#include "input_windows.h"
+
+bool windows_osd_interface::should_hide_mouse()
+{
+ bool hidemouse = false;
+ hidemouse |= downcast<wininput_module*>(m_keyboard_input)->should_hide_mouse();
+ hidemouse |= downcast<wininput_module*>(m_mouse_input)->should_hide_mouse();
+ hidemouse |= downcast<wininput_module*>(m_lightgun_input)->should_hide_mouse();
+ hidemouse |= downcast<wininput_module*>(m_joystick_input)->should_hide_mouse();
+ return hidemouse;
+}
+
+bool windows_osd_interface::handle_input_event(input_event eventid, void* eventdata)
+{
+ bool handled = false;
+ handled |= downcast<wininput_module*>(m_keyboard_input)->handle_input_event(eventid, eventdata);
+ handled |= downcast<wininput_module*>(m_mouse_input)->handle_input_event(eventid, eventdata);
+ handled |= downcast<wininput_module*>(m_lightgun_input)->handle_input_event(eventid, eventdata);
+ handled |= downcast<wininput_module*>(m_joystick_input)->handle_input_event(eventid, eventdata);
+ return handled;
+}
+
+void windows_osd_interface::poll_input(running_machine &machine)
+{
+ m_keyboard_input->poll_if_necessary(machine);
+ m_mouse_input->poll_if_necessary(machine);
+ m_lightgun_input->poll_if_necessary(machine);
+ m_joystick_input->poll_if_necessary(machine);
+}
+
+//============================================================
+// 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 = keyboard_trans_table::instance().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;
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/src/osd/modules/input/input_windows.h b/src/osd/modules/input/input_windows.h
new file mode 100644
index 00000000000..b79560c97a7
--- /dev/null
+++ b/src/osd/modules/input/input_windows.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Brad Hughes
+//============================================================
+//
+// input_windows.h - Common code used by Windows input modules
+//
+//============================================================
+
+#ifndef INPUT_WIN_H_
+#define INPUT_WIN_H_
+
+//============================================================
+// TYPEDEFS
+//============================================================
+
+// state information for a keyboard
+struct keyboard_state
+{
+ UINT8 state[MAX_KEYS];
+ INT8 oldkey[MAX_KEYS];
+ INT8 currkey[MAX_KEYS];
+};
+
+// state information for a mouse (matches DIMOUSESTATE exactly)
+struct mouse_state
+{
+ LONG lX;
+ LONG lY;
+ LONG lZ;
+ BYTE rgbButtons[8];
+};
+
+class wininput_module : public input_module_base
+{
+protected:
+ bool m_global_inputs_enabled;
+
+public:
+ wininput_module(const char * type, const char * name)
+ : input_module_base(type, name)
+ {
+ }
+
+ virtual bool should_hide_mouse()
+ {
+ if (winwindow_has_focus() // has focus
+ && (!video_config.windowed || !win_window_list->win_has_menu()) // not windowed or doesn't have a menu
+ && (input_enabled() && !input_paused()) // input enabled and not paused
+ && (mouse_enabled() || lightgun_enabled())) // either mouse or lightgun enabled in the core
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual bool handle_input_event(input_event eventid, void* data)
+ {
+ return false;
+ }
+
+protected:
+
+ void before_poll(running_machine& machine) override
+ {
+ // 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);
+ }
+
+ bool should_poll_devices(running_machine &machine) override
+ {
+ return input_enabled() && (m_global_inputs_enabled || winwindow_has_focus());
+ }
+};
+
+//============================================================
+// INLINE FUNCTIONS
+//============================================================
+
+INT32 generic_button_get_state(void *device_internal, void *item_internal);
+INT32 generic_axis_get_state(void *device_internal, void *item_internal);
+#endif \ No newline at end of file
diff --git a/src/osd/modules/input/input_x11.cpp b/src/osd/modules/input/input_x11.cpp
new file mode 100644
index 00000000000..3a4073ef8c7
--- /dev/null
+++ b/src/osd/modules/input/input_x11.cpp
@@ -0,0 +1,605 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Brad Hughes
+//============================================================
+//
+// input_x11.cpp - X11 XLib/XInput routines
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#include "input_module.h"
+#include "modules/osdmodule.h"
+
+#if defined(SDLMAME_SDL2) && !defined(SDLMAME_WIN32) && defined(USE_XINPUT) && USE_XINPUT
+
+// for X11 xinput
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#include <X11/Xutil.h>
+
+// standard sdl header
+#include "sdlinc.h"
+#include <ctype.h>
+#include <stddef.h>
+#include <mutex>
+#include <memory>
+#include <queue>
+#include <string>
+
+// MAME headers
+#include "emu.h"
+#include "osdepend.h"
+
+// MAMEOS headers
+#include "../lib/osdobj_common.h"
+#include "input_common.h"
+#include "../../sdl/osdsdl.h"
+#include "input_sdlcommon.h"
+
+#define MAX_DEVMAP_ENTRIES 16
+
+#define INVALID_EVENT_TYPE -1
+static int motion_type = INVALID_EVENT_TYPE;
+static int button_press_type = INVALID_EVENT_TYPE;
+static int button_release_type = INVALID_EVENT_TYPE;
+static int key_press_type = INVALID_EVENT_TYPE;
+static int key_release_type = INVALID_EVENT_TYPE;
+static int proximity_in_type = INVALID_EVENT_TYPE;
+static int proximity_out_type = INVALID_EVENT_TYPE;
+
+// state information for a lightgun
+struct lightgun_state
+{
+ INT32 lX, lY;
+ INT32 buttons[MAX_BUTTONS];
+};
+
+struct x11_api_state
+{
+ XID deviceid; // X11 device id
+ INT32 maxx, maxy;
+ INT32 minx, miny;
+};
+
+//============================================================
+// DEBUG MACROS
+//============================================================
+
+#if defined(XINPUT_DEBUG) && XINPUT_DEBUG
+#define XI_DBG(format, ...) osd_printf_verbose(format, __VA_ARGS__)
+
+#define print_motion_event(motion) print_motion_event_impl(motion)
+static inline void print_motion_event_impl(XDeviceMotionEvent *motion)
+{
+ /*
+ * print a lot of debug informations of the motion event(s).
+ */
+ osd_printf_verbose(
+ "XDeviceMotionEvent:\n"
+ " type: %d\n"
+ " serial: %lu\n"
+ " send_event: %d\n"
+ " display: %p\n"
+ " window: --\n"
+ " deviceid: %lu\n"
+ " root: --\n"
+ " subwindow: --\n"
+ " time: --\n"
+ " x: %d, y: %d\n"
+ " x_root: %d, y_root: %d\n"
+ " state: %u\n"
+ " is_hint: %2.2X\n"
+ " same_screen: %d\n"
+ " device_state: %u\n"
+ " axes_count: %2.2X\n"
+ " first_axis: %2.2X\n"
+ " axis_data[6]: {%d,%d,%d,%d,%d,%d}\n",
+ motion->type,
+ motion->serial,
+ motion->send_event,
+ motion->display,
+ /* motion->window, */
+ motion->deviceid,
+ /* motion->root */
+ /* motion->subwindow */
+ /* motion->time, */
+ motion->x, motion->y,
+ motion->x_root, motion->y_root,
+ motion->state,
+ motion->is_hint,
+ motion->same_screen,
+ motion->device_state,
+ motion->axes_count,
+ motion->first_axis,
+ motion->axis_data[0], motion->axis_data[1], motion->axis_data[2], motion->axis_data[3], motion->axis_data[4], motion->axis_data[5]
+ );
+}
+#else
+#define XI_DBG(format, ...) while(0) {}
+#define print_motion_event(motion) while(0) {}
+#endif
+
+//============================================================
+// lightgun helpers: copy-past from xinfo
+//============================================================
+
+XDeviceInfo*
+find_device_info(Display *display,
+ const char *name,
+ bool only_extended)
+{
+ XDeviceInfo *devices;
+ XDeviceInfo *found = NULL;
+ int loop;
+ int num_devices;
+ int len = strlen(name);
+ bool is_id = true;
+ XID id = (XID)-1;
+
+ for(loop = 0; loop < len; loop++)
+ {
+ if (!isdigit(name[loop]))
+ {
+ is_id = false;
+ break;
+ }
+ }
+
+ if (is_id)
+ {
+ id = atoi(name);
+ }
+
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop = 0; loop < num_devices; loop++)
+ {
+ osd_printf_verbose("Evaluating device with name: %s\n", devices[loop].name);
+
+ // if only extended devices and our device isn't extended, skip
+ if (only_extended && devices[loop].use < IsXExtensionDevice)
+ continue;
+
+ // Adjust name to remove spaces for accurate comparison
+ std::string name_no_space = remove_spaces(devices[loop].name);
+ if ((!is_id && strcmp(name_no_space.c_str(), name) == 0)
+ || (is_id && devices[loop].id == id))
+ {
+ if (found)
+ {
+ osd_printf_verbose(
+ "Warning: There are multiple devices named \"%s\".\n"
+ "To ensure the correct one is selected, please use "
+ "the device ID instead.\n\n", name);
+ }
+ else
+ {
+ found = &devices[loop];
+ }
+ }
+ }
+
+ return found;
+}
+
+//Copypasted from xinfo
+static int
+register_events(
+ Display *dpy,
+ XDeviceInfo *info,
+ const char *dev_name,
+ bool handle_proximity)
+{
+ int number = 0; /* number of events registered */
+ XEventClass event_list[7];
+ int i;
+ XDevice * device;
+ Window root_win;
+ unsigned long screen;
+ XInputClassInfo * ip;
+
+ screen = DefaultScreen(dpy);
+ root_win = RootWindow(dpy, screen);
+
+ device = XOpenDevice(dpy, info->id);
+ if (device == nullptr)
+ {
+ osd_printf_verbose("unable to open device %s\n", dev_name);
+ return 0;
+ }
+
+ if (device->num_classes > 0)
+ {
+ for (ip = device->classes, i = 0; i < info->num_classes; ip++, i++)
+ {
+ switch (ip->input_class)
+ {
+ case KeyClass:
+ DeviceKeyPress(device, key_press_type, event_list[number]); number++;
+ DeviceKeyRelease(device, key_release_type, event_list[number]); number++;
+ break;
+
+ case ButtonClass:
+ DeviceButtonPress(device, button_press_type, event_list[number]); number++;
+ DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
+ break;
+
+ case ValuatorClass:
+ DeviceMotionNotify(device, motion_type, event_list[number]); number++;
+ osd_printf_verbose("Motion = %i\n",motion_type);
+ if (handle_proximity)
+ {
+ ProximityIn(device, proximity_in_type, event_list[number]); number++;
+ ProximityOut(device, proximity_out_type, event_list[number]); number++;
+ }
+ break;
+
+ default:
+ osd_printf_verbose("unknown class\n");
+ break;
+ }
+ }
+
+ if (XSelectExtensionEvent(dpy, root_win, event_list, number))
+ {
+ osd_printf_verbose("error selecting extended events\n");
+ return 0;
+ }
+ }
+
+ return number;
+}
+
+//============================================================
+// x11_event_manager
+//============================================================
+
+class x11_event_handler
+{
+public:
+ virtual void handle_event(XEvent &xevent) = 0;
+};
+
+class x11_event_manager : public event_manager_t<x11_event_handler>
+{
+private:
+ Display * m_display;
+
+ x11_event_manager()
+ : event_manager_t(),
+ m_display(nullptr)
+ {
+ }
+public:
+ Display * display() { return m_display; }
+
+ static x11_event_manager& instance()
+ {
+ static x11_event_manager s_instance;
+ return s_instance;
+ }
+
+ int initialize()
+ {
+ std::lock_guard<std::mutex> scope_lock(m_lock);
+
+ if (m_display != nullptr)
+ return 0;
+
+ m_display = XOpenDisplay(NULL);
+ if (m_display == nullptr)
+ {
+ osd_printf_verbose("Unable to connect to X server\n");
+ return -1;
+ }
+
+ XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
+ if (!version || (version == (XExtensionVersion*)NoSuchExtension))
+ {
+ osd_printf_verbose("xinput extension not available!\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ void process_events(running_machine &machine) override
+ {
+ std::lock_guard<std::mutex> scope_lock(m_lock);
+ XEvent xevent;
+
+ //Get XInput events
+ while (XPending(m_display) != 0)
+ {
+ XNextEvent(m_display, &xevent);
+
+ // Find all subscribers for the event type
+ auto subscribers = m_subscription_index.equal_range(xevent.type);
+
+ // Dispatch the events
+ for (auto iter = subscribers.first; iter != subscribers.second; iter++)
+ iter->second->handle_event(xevent);
+ }
+ }
+};
+
+//============================================================
+// x11_input_device
+//============================================================
+
+class x11_input_device : public event_based_device<XEvent>
+{
+public:
+ x11_api_state x11_state;
+
+ x11_input_device(running_machine &machine, const char* name, input_device_class devclass, input_module &module)
+ : event_based_device(machine, name, devclass, module),
+ x11_state({0})
+ {
+ }
+};
+
+//============================================================
+// x11_lightgun_device
+//============================================================
+
+class x11_lightgun_device : public x11_input_device
+{
+public:
+ lightgun_state lightgun;
+
+ x11_lightgun_device(running_machine &machine, const char* name, input_module &module)
+ : x11_input_device(machine, name, DEVICE_CLASS_LIGHTGUN, module),
+ lightgun({0})
+ {
+ }
+
+ void process_event(XEvent &xevent) override
+ {
+ if (xevent.type == motion_type)
+ {
+ XDeviceMotionEvent *motion = (XDeviceMotionEvent *)&xevent;
+ print_motion_event(motion);
+
+ /*
+ * We have to check with axis will start on array index 0.
+ * We have also to check the number of axes that are stored in the array.
+ */
+ switch (motion->first_axis)
+ {
+ /*
+ * Starting with x, check number of axis, if there is also the y axis stored.
+ */
+ case 0:
+ if (motion->axes_count >= 1)
+ {
+ lightgun.lX = normalize_absolute_axis(motion->axis_data[0], x11_state.minx, x11_state.maxx);
+ if (motion->axes_count >= 2)
+ {
+ lightgun.lY = normalize_absolute_axis(motion->axis_data[1], x11_state.miny, x11_state.maxy);
+ }
+ }
+ break;
+
+ /*
+ * Starting with y, ...
+ */
+ case 1:
+ if (motion->axes_count >= 1)
+ {
+ lightgun.lY = normalize_absolute_axis(motion->axis_data[0], x11_state.miny, x11_state.maxy);
+ }
+ break;
+ }
+ }
+ else if (xevent.type == button_press_type || xevent.type == button_release_type)
+ {
+ XDeviceButtonEvent *button = (XDeviceButtonEvent *)&xevent;
+ lightgun.buttons[button->button] = (xevent.type == button_press_type) ? 0x80 : 0;
+ }
+ }
+
+ void reset() override
+ {
+ memset(&lightgun, 0, sizeof(lightgun));
+ }
+};
+
+//============================================================
+// x11_lightgun_module
+//============================================================
+
+class x11_lightgun_module : public input_module_base, public x11_event_handler
+{
+private:
+ device_map_t m_lightgun_map;
+ Display * m_display;
+public:
+ x11_lightgun_module()
+ : input_module_base(OSD_LIGHTGUNINPUT_PROVIDER, "x11")
+ {
+ }
+
+ void input_init(running_machine &machine) override
+ {
+ int index;
+
+ osd_printf_verbose("Lightgun: Begin initialization\n");
+
+ devmap_init(machine, &m_lightgun_map, SDLOPTION_LIGHTGUNINDEX, 8, "Lightgun mapping");
+
+ x11_event_manager::instance().initialize();
+ m_display = x11_event_manager::instance().display();
+
+ // Loop through all 8 possible devices
+ for (index = 0; index < 8; index++)
+ {
+ XDeviceInfo *info;
+
+ // Skip if the name is empty
+ if (m_lightgun_map.map[index].name.length() == 0)
+ continue;
+
+ x11_lightgun_device *devinfo;
+ std::string const &name = m_lightgun_map.map[index].name;
+ char defname[512];
+
+ // Register and add the device
+ devinfo = create_lightgun_device(machine, index);
+ osd_printf_verbose("%i: %s\n", index, name.c_str());
+
+ // Find the device info associated with the name
+ info = find_device_info(m_display, name.c_str(), 0);
+
+ // If we couldn't find the device, skip
+ if (info == nullptr)
+ {
+ osd_printf_verbose("Can't find device %s!\n", name.c_str());
+ continue;
+ }
+
+ //Grab device info and translate to stuff mame can use
+ if (info->num_classes > 0)
+ {
+ // Add the lightgun buttons based on what we read
+ add_lightgun_buttons((XAnyClassPtr)info->inputclassinfo, info->num_classes, devinfo);
+
+ // Also, set the axix min/max ranges if we got them
+ set_lightgun_axis_props((XAnyClassPtr)info->inputclassinfo, info->num_classes, devinfo);
+ }
+
+ // Add X and Y axis
+ sprintf(defname, "X %s", devinfo->name());
+ devinfo->device()->add_item(defname, ITEM_ID_XAXIS, generic_axis_get_state, &devinfo->lightgun.lX);
+
+ sprintf(defname, "Y %s", devinfo->name());
+ devinfo->device()->add_item(defname, ITEM_ID_YAXIS, generic_axis_get_state, &devinfo->lightgun.lY);
+
+ // Save the device id
+ devinfo->x11_state.deviceid = info->id;
+
+ // Register this device to receive event notifications
+ int events_registered = register_events(m_display, info, m_lightgun_map.map[index].name.c_str(), 0);
+ osd_printf_verbose("Device %i: Registered %i events.\n", (int)info->id, events_registered);
+
+ // register ourself to handle events from event manager
+ int event_types[] = { motion_type, button_press_type, button_release_type };
+ osd_printf_verbose("Events types to register: motion:%d, press:%d, release:%d\n", motion_type, button_press_type, button_release_type);
+ x11_event_manager::instance().subscribe(event_types, ARRAY_LENGTH(event_types), this);
+ }
+
+ osd_printf_verbose("Lightgun: End initialization\n");
+ }
+
+ bool should_poll_devices(running_machine &machine) override
+ {
+ return sdl_event_manager::instance().app_has_mouse_focus();
+ }
+
+ void before_poll(running_machine &machine) override
+ {
+ if (!should_poll_devices(machine))
+ return;
+
+ // Tell the event manager to process events and push them to the devices
+ x11_event_manager::instance().process_events(machine);
+
+ // Also trigger the SDL event manager so it can process window events
+ sdl_event_manager::instance().process_events(machine);
+ }
+
+ void handle_event(XEvent &xevent) override
+ {
+ for (int i = 0; i < devicelist()->size(); i++)
+ {
+ downcast<x11_input_device*>(devicelist()->at(i))->queue_events(&xevent, 1);
+ }
+ }
+
+private:
+ x11_lightgun_device* create_lightgun_device(running_machine &machine, int index)
+ {
+ x11_lightgun_device *devinfo = nullptr;
+ char tempname[20];
+
+ if (m_lightgun_map.map[index].name.length() == 0)
+ {
+ if (m_lightgun_map.initialized)
+ {
+ snprintf(tempname, ARRAY_LENGTH(tempname), "NC%d", index);
+ devinfo = devicelist()->create_device<x11_lightgun_device>(machine, tempname, *this);
+ }
+
+ return nullptr;
+ }
+ else
+ {
+ devinfo = devicelist()->create_device<x11_lightgun_device>(machine, m_lightgun_map.map[index].name.c_str(), *this);
+ }
+
+ return devinfo;
+ }
+
+ void add_lightgun_buttons(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device *devinfo)
+ {
+ XAnyClassPtr any = first_info_class;
+
+ for (int i = 0; i < num_classes; i++)
+ {
+ switch (any->c_class)
+ {
+ case ButtonClass:
+ XButtonInfoPtr b = (XButtonInfoPtr)any;
+ for (int button = 0; button < b->num_buttons; button++)
+ {
+ input_item_id itemid = (input_item_id)(ITEM_ID_BUTTON1 + button);
+ devinfo->device()->add_item(default_button_name(button), itemid, generic_button_get_state, &devinfo->lightgun.buttons[button]);
+ }
+ break;
+ }
+
+ any = (XAnyClassPtr)((char *)any + any->length);
+ }
+ }
+
+ void set_lightgun_axis_props(XAnyClassPtr first_info_class, int num_classes, x11_lightgun_device *devinfo)
+ {
+ XAnyClassPtr any = first_info_class;
+
+ for (int i = 0; i < num_classes; i++)
+ {
+ switch (any->c_class)
+ {
+ case ValuatorClass:
+ XValuatorInfoPtr valuator_info = (XValuatorInfoPtr)any;
+ XAxisInfoPtr axis_info = (XAxisInfoPtr)((char *)valuator_info + sizeof(XValuatorInfo));
+ for (int j = 0; j < valuator_info->num_axes; j++, axis_info++)
+ {
+ if (j == 0)
+ {
+ XI_DBG("Set minx=%d, maxx=%d\n", axis_info->min_value, axis_info->max_value);
+ devinfo->x11_state.maxx = axis_info->max_value;
+ devinfo->x11_state.minx = axis_info->min_value;
+ }
+
+ if (j == 1)
+ {
+ XI_DBG("Set miny=%d, maxy=%d\n", axis_info->min_value, axis_info->max_value);
+ devinfo->x11_state.maxy = axis_info->max_value;
+ devinfo->x11_state.miny = axis_info->min_value;
+ }
+ }
+ break;
+ }
+
+ any = (XAnyClassPtr)((char *)any + any->length);
+ }
+ }
+};
+
+#else
+MODULE_NOT_SUPPORTED(x11_lightgun_module, OSD_LIGHTGUNINPUT_PROVIDER, "x11")
+#endif
+
+MODULE_DEFINITION(LIGHTGUN_X11, x11_lightgun_module) \ No newline at end of file
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index 7317876eaca..277dc4ef692 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -25,6 +25,12 @@ const options_entry osd_options::s_option_entries[] =
{ nullptr, nullptr, OPTION_HEADER, "OSD FONT OPTIONS" },
{ OSD_FONT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for ui font: " },
+ { nullptr, nullptr, OPTION_HEADER, "OSD INPUT OPTIONS" },
+ { OSD_KEYBOARDINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for keyboard input: " },
+ { OSD_MOUSEINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for mouse input: " },
+ { OSD_LIGHTGUNINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for lightgun input: " },
+ { OSD_JOYSTICKINPUT_PROVIDER, OSDOPTVAL_AUTO, OPTION_STRING, "provider for joystick input: " },
+
{ nullptr, nullptr, OPTION_HEADER, "OSD CLI OPTIONS" },
{ OSDCOMMAND_LIST_MIDI_DEVICES ";mlist", "0", OPTION_COMMAND, "list available MIDI I/O devices" },
{ OSDCOMMAND_LIST_NETWORK_ADAPTERS ";nlist", "0", OPTION_COMMAND, "list available network adapters" },
@@ -155,7 +161,11 @@ osd_common_t::osd_common_t(osd_options &options)
m_options(options),
m_print_verbose(false),
m_sound(nullptr),
- m_debugger(nullptr)
+ m_debugger(nullptr),
+ m_keyboard_input(nullptr),
+ m_mouse_input(nullptr),
+ m_lightgun_input(nullptr),
+ m_joystick_input(nullptr)
{
osd_output::push(this);
}
@@ -207,6 +217,26 @@ void osd_common_t::register_options()
#endif
REGISTER_MODULE(m_mod_man, MIDI_NONE);
+ REGISTER_MODULE(m_mod_man, KEYBOARDINPUT_SDL);
+ REGISTER_MODULE(m_mod_man, KEYBOARDINPUT_RAWINPUT);
+ REGISTER_MODULE(m_mod_man, KEYBOARDINPUT_DINPUT);
+ REGISTER_MODULE(m_mod_man, KEYBOARDINPUT_WIN32);
+ REGISTER_MODULE(m_mod_man, KEYBOARD_NONE);
+
+ REGISTER_MODULE(m_mod_man, MOUSEINPUT_SDL);
+ REGISTER_MODULE(m_mod_man, MOUSEINPUT_RAWINPUT);
+ REGISTER_MODULE(m_mod_man, MOUSEINPUT_DINPUT);
+ REGISTER_MODULE(m_mod_man, MOUSEINPUT_WIN32);
+ REGISTER_MODULE(m_mod_man, MOUSE_NONE);
+
+ REGISTER_MODULE(m_mod_man, LIGHTGUN_X11);
+ REGISTER_MODULE(m_mod_man, LIGHTGUNINPUT_WIN32);
+ REGISTER_MODULE(m_mod_man, LIGHTGUN_NONE);
+
+ REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDL);
+ REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_DINPUT);
+ REGISTER_MODULE(m_mod_man, JOYSTICK_NONE);
+
// after initialization we know which modules are supported
const char *names[20];
@@ -217,6 +247,30 @@ void osd_common_t::register_options()
dnames.push_back(names[i]);
update_option(OSD_FONT_PROVIDER, dnames);
+ m_mod_man.get_module_names(OSD_KEYBOARDINPUT_PROVIDER, 20, &num, names);
+ dnames.clear();
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_KEYBOARDINPUT_PROVIDER, dnames);
+
+ m_mod_man.get_module_names(OSD_MOUSEINPUT_PROVIDER, 20, &num, names);
+ dnames.clear();
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_MOUSEINPUT_PROVIDER, dnames);
+
+ m_mod_man.get_module_names(OSD_LIGHTGUNINPUT_PROVIDER, 20, &num, names);
+ dnames.clear();
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_LIGHTGUNINPUT_PROVIDER, dnames);
+
+ m_mod_man.get_module_names(OSD_JOYSTICKINPUT_PROVIDER, 20, &num, names);
+ dnames.clear();
+ for (int i = 0; i < num; i++)
+ dnames.push_back(names[i]);
+ update_option(OSD_JOYSTICKINPUT_PROVIDER, dnames);
+
m_mod_man.get_module_names(OSD_SOUND_PROVIDER, 20, &num, names);
dnames.clear();
for (int i = 0; i < num; i++)
@@ -545,15 +599,14 @@ void osd_common_t::init_subsystems()
exit(-1);
}
- input_init();
- // we need pause callbacks
- machine().add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(osd_common_t::input_pause), this));
- machine().add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(osd_common_t::input_resume), this));
-
output_init();
- m_font_module = select_module_options<font_module *>(options(), OSD_FONT_PROVIDER);
+ m_keyboard_input = select_module_options<input_module *>(options(), OSD_KEYBOARDINPUT_PROVIDER);
+ m_mouse_input = select_module_options<input_module *>(options(), OSD_MOUSEINPUT_PROVIDER);
+ m_lightgun_input = select_module_options<input_module *>(options(), OSD_LIGHTGUNINPUT_PROVIDER);
+ m_joystick_input = select_module_options<input_module *>(options(), OSD_JOYSTICKINPUT_PROVIDER);
+ m_font_module = select_module_options<font_module *>(options(), OSD_FONT_PROVIDER);
m_sound = select_module_options<sound_module *>(options(), OSD_SOUND_PROVIDER);
m_sound->m_sample_rate = options().sample_rate();
m_sound->m_audio_latency = options().audio_latency();
@@ -566,6 +619,10 @@ void osd_common_t::init_subsystems()
m_mod_man.init(options());
+ input_init();
+ // we need pause callbacks
+ machine().add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(FUNC(osd_common_t::input_pause), this));
+ machine().add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(FUNC(osd_common_t::input_resume), this));
}
bool osd_common_t::video_init()
@@ -589,15 +646,27 @@ void osd_common_t::video_register()
bool osd_common_t::input_init()
{
+ m_keyboard_input->input_init(machine());
+ m_mouse_input->input_init(machine());
+ m_lightgun_input->input_init(machine());
+ m_joystick_input->input_init(machine());
return true;
}
void osd_common_t::input_pause()
{
+ m_keyboard_input->pause();
+ m_mouse_input->pause();
+ m_lightgun_input->pause();
+ m_joystick_input->pause();
}
void osd_common_t::input_resume()
{
+ m_keyboard_input->resume();
+ m_mouse_input->resume();
+ m_lightgun_input->resume();
+ m_joystick_input->resume();
}
bool osd_common_t::output_init()
@@ -622,6 +691,10 @@ void osd_common_t::window_exit()
void osd_common_t::input_exit()
{
+ m_keyboard_input->exit();
+ m_mouse_input->exit();
+ m_lightgun_input->exit();
+ m_joystick_input->exit();
}
void osd_common_t::output_exit()
diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h
index 8152c7bfea9..592391b5161 100644
--- a/src/osd/modules/lib/osdobj_common.h
+++ b/src/osd/modules/lib/osdobj_common.h
@@ -16,6 +16,7 @@
#include "osdepend.h"
#include "modules/osdmodule.h"
#include "modules/font/font_module.h"
+#include "modules/input/input_module.h"
#include "modules/sound/sound_module.h"
#include "modules/debugger/debug_module.h"
#include "modules/netdev/netdev_module.h"
@@ -269,6 +270,10 @@ protected:
sound_module* m_sound;
debug_module* m_debugger;
midi_module* m_midi;
+ input_module* m_keyboard_input;
+ input_module* m_mouse_input;
+ input_module* m_lightgun_input;
+ input_module* m_joystick_input;
private:
std::vector<const char *> m_video_names;
};
diff --git a/src/osd/sdl/input.cpp b/src/osd/sdl/input.cpp
deleted file mode 100644
index 9cfcdb1cf16..00000000000
--- a/src/osd/sdl/input.cpp
+++ /dev/null
@@ -1,2128 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// input.c - SDL implementation of MAME input routines
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-// SixAxis info: left analog is axes 0 & 1, right analog is axes 2 & 3,
-// analog L2 is axis 12 and analog L3 is axis 13
-//
-//============================================================
-
-// standard sdl header
-#include "sdlinc.h"
-#include <ctype.h>
-#include <stddef.h>
-#include <mutex>
-
-#if USE_XINPUT
-// for xinput
-#include <X11/Xlib.h>
-#include <X11/extensions/XInput.h>
-#include <X11/Xutil.h>
-#endif
-
-// MAME headers
-#include "emu.h"
-#include "ui/ui.h"
-#include "uiinput.h"
-#include "emuopts.h"
-
-
-// MAMEOS headers
-#include "input.h"
-#include "osdsdl.h"
-#include "window.h"
-
-// winnt.h defines this
-#ifdef DELETE
-#undef DELETE
-#endif
-
-//============================================================
-// PARAMETERS
-//============================================================
-
-enum
-{
- POVDIR_LEFT = 0,
- POVDIR_RIGHT,
- POVDIR_UP,
- POVDIR_DOWN
-};
-
-#define MAX_KEYS 256
-#define MAX_AXES 32
-#define MAX_BUTTONS 32
-#define MAX_HATS 8
-#define MAX_POV 4
-#define MAX_DEVMAP_ENTRIES 16
-
-#if (USE_XINPUT)
-//For xinput
-#define INVALID_EVENT_TYPE -1
-static int motion_type = INVALID_EVENT_TYPE;
-static int button_press_type = INVALID_EVENT_TYPE;
-static int button_release_type = INVALID_EVENT_TYPE;
-static int key_press_type = INVALID_EVENT_TYPE;
-static int key_release_type = INVALID_EVENT_TYPE;
-static int proximity_in_type = INVALID_EVENT_TYPE;
-static int proximity_out_type = INVALID_EVENT_TYPE;
-#endif
-
-//============================================================
-// MACROS
-//============================================================
-
-// introduced in 1.3
-
-#ifndef SDLK_INDEX
-#define SDLK_INDEX(x) (x)
-#endif
-
-
-//============================================================
-// TYPEDEFS
-//============================================================
-
-// state information for a keyboard
-struct keyboard_state
-{
- INT32 state[0x3ff]; // must be INT32!
- INT8 oldkey[MAX_KEYS];
- INT8 currkey[MAX_KEYS];
-};
-
-
-// state information for a mouse
-struct mouse_state
-{
- INT32 lX, lY;
- INT32 buttons[MAX_BUTTONS];
-};
-
-
-// state information for a joystick; DirectInput state must be first element
-struct joystick_state
-{
- SDL_Joystick *device;
- INT32 axes[MAX_AXES];
- INT32 buttons[MAX_BUTTONS];
- INT32 hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS];
- INT32 balls[MAX_AXES];
-};
-
-#if (USE_XINPUT)
-// state information for a lightgun
-struct lightgun_state
-{
- INT32 lX, lY;
- INT32 buttons[MAX_BUTTONS];
- XID deviceid; //Xinput device id
- INT32 maxx,maxy;
- INT32 minx,miny;
-};
-#endif
-
-// generic device information
-struct device_info
-{
- // device information
- device_info ** head;
- device_info * next;
- std::string name;
-
- // MAME information
- input_device * device;
-
- // device state
- union
- {
- keyboard_state keyboard;
- mouse_state mouse;
- joystick_state joystick;
-#if (USE_XINPUT)
- lightgun_state lightgun;
-#endif
- };
-};
-
-
-//============================================================
-// LOCAL VARIABLES
-//============================================================
-
-// global states
-static std::mutex input_lock;
-static UINT8 input_paused;
-
-static sdl_window_info * focus_window = NULL;
-
-// input buffer - only for SDLMAME_EVENTS_IN_WORKER_THREAD
-#define MAX_BUF_EVENTS (1000) /* 100 not enough for SDL 1.3 */
-static SDL_Event event_buf[MAX_BUF_EVENTS];
-static int event_buf_count;
-
-// keyboard states
-static device_info * keyboard_list;
-
-// mouse states
-static UINT8 app_has_mouse_focus;
-static UINT8 mouse_enabled;
-static device_info * mouse_list;
-
-// lightgun states
-static UINT8 lightgun_enabled;
-static device_info * lightgun_list;
-
-// joystick states
-static device_info * joystick_list;
-
-// joystick mapper
-
-struct device_map_t
-{
- struct {
- char *name;
- int physical;
- } map[MAX_DEVMAP_ENTRIES];
- int logical[MAX_DEVMAP_ENTRIES];
- int initialized;
-};
-
-static device_map_t joy_map;
-static device_map_t mouse_map;
-static device_map_t keyboard_map;
-#if (USE_XINPUT)
-static device_map_t lightgun_map;
-Display *XDisplay;
-#endif
-
-static int sixaxis_mode;
-
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-// deivce list management
-static void device_list_reset_devices(device_info *devlist_head);
-static void device_list_free_devices(device_info **devlist_head);
-
-// generic device management
-static device_info *generic_device_alloc(device_info **devlist_head_ptr, const char *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);
-static device_info *generic_device_find_index(device_info *devlist_head, int index);
-
-
-//============================================================
-// KEYBOARD/JOYSTICK LIST
-//============================================================
-
-// master keyboard translation table
-struct kt_table {
- input_item_id mame_key;
- INT32 sdl_key;
- //const char * vkey;
- //const char * ascii;
- const char * mame_key_name;
- char * ui_name;
-};
-
-
-#define OSD_SDL_INDEX(x) (x)
-#define OSD_SDL_INDEX_KEYSYM(keysym) ((keysym)->scancode)
-
-#define GET_WINDOW(ev) window_from_id((ev)->windowID)
-//#define GET_WINDOW(ev) ((ev)->windowID)
-// FIXME: sdl does not properly report the window for certain OS.
-#define GET_FOCUS_WINDOW(ev) focus_window
-//#define GET_FOCUS_WINDOW(ev) window_from_id((ev)->windowID)
-
-
-#define KTT_ENTRY0(MAME, SDL, VK, AS, UI) { ITEM_ID_ ## MAME, SDL_SCANCODE_ ## SDL, "ITEM_ID_" #MAME, (char *) UI }
-#define KTT_ENTRY1(MAME, SDL) KTT_ENTRY0(MAME, SDL, MAME, MAME, #MAME)
-// only for reference ...
-#define KTT_ENTRY2(MAME, SDL) KTT_ENTRY0(MAME, SDL, 0, 0, #MAME)
-
-
-static kt_table sdl_key_trans_table[] =
-{
- // MAME key SDL key vkey ascii
- KTT_ENTRY0( ESC, ESCAPE, 0x1b, 0x1b, "ESC" ), // 0
- KTT_ENTRY1( 1, 1 ), // 1
- KTT_ENTRY1( 2, 2 ), // 2
- KTT_ENTRY1( 3, 3 ), // 3
- KTT_ENTRY1( 4, 4 ), // 4
- KTT_ENTRY1( 5, 5 ), // 5
- KTT_ENTRY1( 6, 6 ), // 6
- KTT_ENTRY1( 7, 7 ), // 7
- KTT_ENTRY1( 8, 8 ), // 8
- KTT_ENTRY1( 9, 9 ), // 9
- KTT_ENTRY1( 0, 0 ), // 10
- KTT_ENTRY0( MINUS, MINUS, 0xbd, '-', "MINUS" ), // 11
- KTT_ENTRY0( EQUALS, EQUALS, 0xbb, '=', "EQUALS" ), // 12
- KTT_ENTRY0( BACKSPACE, BACKSPACE, 0x08, 0x08, "BACKSPACE" ), // 13
- KTT_ENTRY0( TAB, TAB, 0x09, 0x09, "TAB" ), // 14
- KTT_ENTRY1( Q, Q ), // 15
- KTT_ENTRY1( W, W ), // 16
- KTT_ENTRY1( E, E ), // 17
- KTT_ENTRY1( R, R ), // 18
- KTT_ENTRY1( T, T ), // 19
- KTT_ENTRY1( Y, Y ), // 20
- KTT_ENTRY1( U, U ), // 21
- KTT_ENTRY1( I, I ), // 22
- KTT_ENTRY1( O, O ), // 23
- KTT_ENTRY1( P, P ), // 24
- KTT_ENTRY0( OPENBRACE, LEFTBRACKET, 0xdb, '[', "OPENBRACE" ), // 25
- KTT_ENTRY0( CLOSEBRACE,RIGHTBRACKET, 0xdd, ']', "CLOSEBRACE" ), // 26
- KTT_ENTRY0( ENTER, RETURN, 0x0d, 0x0d, "RETURN" ), // 27
- KTT_ENTRY2( LCONTROL, LCTRL ), // 28
- KTT_ENTRY1( A, A ), // 29
- KTT_ENTRY1( S, S ), // 30
- KTT_ENTRY1( D, D ), // 31
- KTT_ENTRY1( F, F ), // 32
- KTT_ENTRY1( G, G ), // 33
- KTT_ENTRY1( H, H ), // 34
- KTT_ENTRY1( J, J ), // 35
- KTT_ENTRY1( K, K ), // 36
- KTT_ENTRY1( L, L ), // 37
- KTT_ENTRY0( COLON, SEMICOLON, 0xba, ';', "COLON" ), // 38
- KTT_ENTRY0( QUOTE, APOSTROPHE, 0xde, '\'', "QUOTE" ), // 39
- KTT_ENTRY2( LSHIFT, LSHIFT ), // 40
- KTT_ENTRY0( BACKSLASH, BACKSLASH, 0xdc, '\\', "BACKSLASH" ), // 41
- KTT_ENTRY1( Z, Z ), // 42
- KTT_ENTRY1( X, X ), // 43
- KTT_ENTRY1( C, C ), // 44
- KTT_ENTRY1( V, V ), // 45
- KTT_ENTRY1( B, B ), // 46
- KTT_ENTRY1( N, N ), // 47
- KTT_ENTRY1( M, M ), // 48
- KTT_ENTRY0( COMMA, COMMA, 0xbc, ',', "COMMA" ), // 49
- KTT_ENTRY0( STOP, PERIOD, 0xbe, '.', "STOP" ), // 50
- KTT_ENTRY0( SLASH, SLASH, 0xbf, '/', "SLASH" ), // 51
- KTT_ENTRY2( RSHIFT, RSHIFT ), // 52
- KTT_ENTRY0( ASTERISK, KP_MULTIPLY, '*', '*', "ASTERIX" ), // 53
- KTT_ENTRY2( LALT, LALT ), // 54
- KTT_ENTRY0( SPACE, SPACE, ' ', ' ', "SPACE" ), // 55
- KTT_ENTRY2( CAPSLOCK, CAPSLOCK ), // 56
- KTT_ENTRY2( F1, F1 ), // 57
- KTT_ENTRY2( F2, F2 ), // 58
- KTT_ENTRY2( F3, F3 ), // 59
- KTT_ENTRY2( F4, F4 ), // 60
- KTT_ENTRY2( F5, F5 ), // 61
- KTT_ENTRY2( F6, F6 ), // 62
- KTT_ENTRY2( F7, F7 ), // 63
- KTT_ENTRY2( F8, F8 ), // 64
- KTT_ENTRY2( F9, F9 ), // 65
- KTT_ENTRY2( F10, F10 ), // 66
- KTT_ENTRY2( NUMLOCK, NUMLOCKCLEAR ), // 67
- KTT_ENTRY2( SCRLOCK, SCROLLLOCK ), // 68
- KTT_ENTRY2( 7_PAD, KP_7 ), // 69
- KTT_ENTRY2( 8_PAD, KP_8 ),
- KTT_ENTRY2( 9_PAD, KP_9 ),
- KTT_ENTRY2( MINUS_PAD, KP_MINUS ),
- KTT_ENTRY2( 4_PAD, KP_4 ),
- KTT_ENTRY2( 5_PAD, KP_5 ),
- KTT_ENTRY2( 6_PAD, KP_6 ),
- KTT_ENTRY2( PLUS_PAD, KP_PLUS ),
- KTT_ENTRY2( 1_PAD, KP_1 ),
- KTT_ENTRY2( 2_PAD, KP_2 ),
- KTT_ENTRY2( 3_PAD, KP_3 ),
- KTT_ENTRY2( 0_PAD, KP_0 ),
- KTT_ENTRY2( DEL_PAD, KP_PERIOD ),
- KTT_ENTRY2( F11, F11 ),
- KTT_ENTRY2( F12, F12 ),
- KTT_ENTRY2( F13, F13 ),
- KTT_ENTRY2( F14, F14 ),
- KTT_ENTRY2( F15, F15 ),
- KTT_ENTRY2( ENTER_PAD, KP_ENTER ),
- KTT_ENTRY2( RCONTROL, RCTRL ),
- KTT_ENTRY2( SLASH_PAD, KP_DIVIDE ),
- KTT_ENTRY2( PRTSCR, PRINTSCREEN ),
- KTT_ENTRY2( RALT, RALT ),
- KTT_ENTRY2( HOME, HOME ),
- KTT_ENTRY2( UP, UP ),
- KTT_ENTRY2( PGUP, PAGEUP ),
- KTT_ENTRY2( LEFT, LEFT ),
- KTT_ENTRY2( RIGHT, RIGHT ),
- KTT_ENTRY2( END, END ),
- KTT_ENTRY2( DOWN, DOWN ),
- KTT_ENTRY2( PGDN, PAGEDOWN ),
- KTT_ENTRY2( INSERT, INSERT ),
- { ITEM_ID_DEL, SDL_SCANCODE_DELETE, "ITEM_ID_DEL", (char *)"DELETE" },
- KTT_ENTRY2( LWIN, LGUI ),
- KTT_ENTRY2( RWIN, RGUI ),
- KTT_ENTRY2( MENU, MENU ),
- KTT_ENTRY0( TILDE, GRAVE, 0xc0, '`', "TILDE" ),
- KTT_ENTRY0( BACKSLASH2, NONUSBACKSLASH, 0xdc, '\\', "BACKSLASH2" ),
- { ITEM_ID_INVALID }
-};
-
-struct key_lookup_table
-{
- int code;
- const char *name;
-};
-
-#define KE(x) { SDL_SCANCODE_ ## x, "SDL_SCANCODE_" #x },
-#define KE8(A, B, C, D, E, F, G, H) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G) KE(H)
-#define KE7(A, B, C, D, E, F, G) KE(A) KE(B) KE(C) KE(D) KE(E) KE(F) KE(G)
-#define KE5(A, B, C, D, E) KE(A) KE(B) KE(C) KE(D) KE(E)
-#define KE3(A, B, C) KE(A) KE(B) KE(C)
-
-static key_lookup_table sdl_lookup_table[] =
-{
- KE7(UNKNOWN, BACKSPACE, TAB, CLEAR, RETURN, PAUSE, ESCAPE )
- KE(SPACE)
- KE5(COMMA, MINUS, PERIOD, SLASH, 0 )
- KE8(1, 2, 3, 4, 5, 6, 7, 8 )
- KE3(9, SEMICOLON, EQUALS)
- KE5(LEFTBRACKET,BACKSLASH, RIGHTBRACKET, A, B )
- KE8(C, D, E, F, G, H, I, J )
- KE8(K, L, M, N, O, P, Q, R )
- KE8(S, T, U, V, W, X, Y, Z )
- KE8(DELETE, KP_0, KP_1, KP_2, KP_3, KP_4, KP_5, KP_6 )
- KE8(KP_7, KP_8, KP_9, KP_PERIOD, KP_DIVIDE, KP_MULTIPLY,KP_MINUS, KP_PLUS )
- KE8(KP_ENTER, KP_EQUALS, UP, DOWN, RIGHT, LEFT, INSERT, HOME )
- KE8(END, PAGEUP, PAGEDOWN, F1, F2, F3, F4, F5 )
- KE8(F6, F7, F8, F9, F10, F11, F12, F13 )
- KE8(F14, F15, NUMLOCKCLEAR, CAPSLOCK, SCROLLLOCK, RSHIFT, LSHIFT, RCTRL )
- KE5(LCTRL, RALT, LALT, LGUI, RGUI)
- KE8(GRAVE, LEFTBRACKET,RIGHTBRACKET, SEMICOLON, APOSTROPHE, BACKSLASH, PRINTSCREEN,MENU )
- KE(UNDO)
- {-1, ""}
-};
-
-//============================================================
-// INLINE FUNCTIONS
-//============================================================
-
-static int devmap_leastfree(device_map_t *devmap)
-{
- int i;
- for (i=0;i<MAX_DEVMAP_ENTRIES;i++)
- {
- if (*devmap->map[i].name == 0)
- return i;
- }
- return -1;
-}
-
-static char *remove_spaces(running_machine &machine, const char *s)
-{
- char *r, *p;
- static const char *def_name[] = { "Unknown" };
-
- while (*s && *s == ' ')
- s++;
-
- if (strlen(s) == 0)
- {
- r = auto_alloc_array(machine, char, strlen((char *)def_name) + 1);
- strcpy(r, (char *)def_name);
- return r;
- }
-
- r = auto_alloc_array(machine, char, strlen(s) + 1);
- p = r;
- while (*s)
- {
- if (*s != ' ')
- *p++ = *s++;
- else
- {
- while (*s && *s == ' ')
- s++;
- if (*s)
- *p++ = ' ';
- }
- }
- *p = 0;
- return r;
-}
-
-static void devmap_register(device_map_t *devmap, int physical_idx, char *name)
-{
- int found = 0;
- int stick, i;
-
- for (i=0;i<MAX_DEVMAP_ENTRIES;i++)
- {
- if (strcmp(name,devmap->map[i].name) == 0 && devmap->map[i].physical < 0)
- {
- devmap->map[i].physical = physical_idx;
- found = 1;
- devmap->logical[physical_idx] = i;
- }
- }
- if (found == 0)
- {
- stick = devmap_leastfree(devmap);
- devmap->map[stick].physical = physical_idx;
- devmap->map[stick].name = name;
- devmap->logical[physical_idx] = stick;
- }
-
-}
-
-//============================================================
-// init_joymap
-//============================================================
-
-static void devmap_init(running_machine &machine, device_map_t *devmap, const char *opt, int max_devices, const char *label)
-{
- int dev;
- char defname[20];
-
- assert(max_devices <= MAX_DEVMAP_ENTRIES);
-
- for (dev = 0; dev < MAX_DEVMAP_ENTRIES; dev++)
- {
- devmap->map[dev].name = (char *)"";
- devmap->map[dev].physical = -1;
- devmap->logical[dev] = -1;
- }
- devmap->initialized = 0;
-
- for (dev = 0; dev < max_devices; dev++)
- {
- const char *dev_name;
- sprintf(defname, "%s%d", opt, dev + 1);
-
- dev_name = machine.options().value(defname);
- if (dev_name && *dev_name && strcmp(dev_name,OSDOPTVAL_AUTO))
- {
- devmap->map[dev].name = remove_spaces(machine, dev_name);
- osd_printf_verbose("%s: Logical id %d: %s\n", label, dev + 1, devmap->map[dev].name);
- devmap->initialized = 1;
- }
- }
-}
-
-static device_info *devmap_class_register(running_machine &machine, device_map_t *devmap,
- int index, device_info **devlist, input_device_class devclass)
-{
- device_info *devinfo = NULL;
- char tempname[20];
-
- if (*devmap->map[index].name == 0)
- {
- /* only map place holders if there were mappings specified is enabled */
- if (devmap->initialized)
- {
- sprintf(tempname, "NC%d", index);
- devinfo = generic_device_alloc(devlist, tempname);
- devinfo->device = machine.input().device_class(devclass).add_device(devinfo->name.c_str(), devinfo);
- }
- return NULL;
- }
- else
- {
- devinfo = generic_device_alloc(devlist, devmap->map[index].name);
- devinfo->device = machine.input().device_class(devclass).add_device(devinfo->name.c_str(), devinfo);
- }
- return devinfo;
-}
-
-
-//============================================================
-// sdlinput_register_joysticks
-//============================================================
-
-static void sdlinput_register_joysticks(running_machine &machine)
-{
- device_info *devinfo;
- int physical_stick, axis, button, hat, stick, ball;
- char tempname[512];
- SDL_Joystick *joy;
-
- devmap_init(machine, &joy_map, SDLOPTION_JOYINDEX, 8, "Joystick mapping");
-
- osd_printf_verbose("Joystick: Start initialization\n");
- for (physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++)
- {
- char *joy_name;
-
- joy = SDL_JoystickOpen(physical_stick);
- joy_name = remove_spaces(machine, SDL_JoystickName(joy));
- SDL_JoystickClose(joy);
- devmap_register(&joy_map, physical_stick, joy_name);
- }
-
- for (stick = 0; stick < MAX_DEVMAP_ENTRIES; stick++)
- {
- devinfo = devmap_class_register(machine, &joy_map, stick, &joystick_list, DEVICE_CLASS_JOYSTICK);
-
- if (devinfo == NULL)
- continue;
-
- physical_stick = joy_map.map[stick].physical;
-
- joy = SDL_JoystickOpen(physical_stick);
-
- devinfo->joystick.device = joy;
-
- osd_printf_verbose("Joystick: %s\n", devinfo->name.c_str());
- osd_printf_verbose("Joystick: ... %d axes, %d buttons %d hats %d balls\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy));
- osd_printf_verbose("Joystick: ... Physical id %d mapped to logical id %d\n", physical_stick, stick + 1);
-
- // loop over all axes
- for (axis = 0; axis < SDL_JoystickNumAxes(joy); axis++)
- {
- input_item_id itemid;
-
- if (axis < INPUT_MAX_AXIS)
- itemid = (input_item_id) (ITEM_ID_XAXIS + axis);
- else if (axis < INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE)
- itemid = (input_item_id) (ITEM_ID_ADD_ABSOLUTE1 - INPUT_MAX_AXIS + axis);
- else
- itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE;
-
- sprintf(tempname, "A%d %s", axis, devinfo->name.c_str());
- devinfo->device->add_item(tempname, itemid, generic_axis_get_state, &devinfo->joystick.axes[axis]);
- }
-
- // loop over all buttons
- for (button = 0; button < SDL_JoystickNumButtons(joy); button++)
- {
- input_item_id itemid;
-
- devinfo->joystick.buttons[button] = 0;
-
- if (button < INPUT_MAX_BUTTONS)
- itemid = (input_item_id) (ITEM_ID_BUTTON1 + button);
- else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH)
- itemid = (input_item_id) (ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + button);
- else
- itemid = ITEM_ID_OTHER_SWITCH;
-
- sprintf(tempname, "button %d", button);
- devinfo->device->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.buttons[button]);
- }
-
- // loop over all hats
- for (hat = 0; hat < SDL_JoystickNumHats(joy); hat++)
- {
- input_item_id itemid;
-
- sprintf(tempname, "hat %d Up", hat);
- itemid = (input_item_id) ((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsU[hat]);
- sprintf(tempname, "hat %d Down", hat);
- itemid = (input_item_id) ((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsD[hat]);
- sprintf(tempname, "hat %d Left", hat);
- itemid = (input_item_id) ((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsL[hat]);
- sprintf(tempname, "hat %d Right", hat);
- itemid = (input_item_id) ((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH);
- devinfo->device->add_item(tempname, itemid, generic_button_get_state, &devinfo->joystick.hatsR[hat]);
- }
-
- // loop over all (track)balls
- for (ball = 0; ball < SDL_JoystickNumBalls(joy); ball++)
- {
- int itemid;
-
- if (ball * 2 < INPUT_MAX_ADD_RELATIVE)
- itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2;
- else
- itemid = ITEM_ID_OTHER_AXIS_RELATIVE;
-
- sprintf(tempname, "R%d %s", ball * 2, devinfo->name.c_str());
- devinfo->device->add_item(tempname, (input_item_id) itemid, generic_axis_get_state, &devinfo->joystick.balls[ball * 2]);
- sprintf(tempname, "R%d %s", ball * 2 + 1, devinfo->name.c_str());
- devinfo->device->add_item(tempname, (input_item_id) (itemid + 1), generic_axis_get_state, &devinfo->joystick.balls[ball * 2 + 1]);
- }
- }
- osd_printf_verbose("Joystick: End initialization\n");
-}
-
-//============================================================
-// sdlinput_deregister_joysticks
-//============================================================
-
-static void sdlinput_deregister_joysticks(running_machine &machine)
-{
- device_info *curdev;
-
- osd_printf_verbose("Joystick: Start deinitialization\n");
-
- for (curdev = joystick_list; curdev != NULL; curdev = curdev->next)
- {
- SDL_JoystickClose(curdev->joystick.device);
- }
-
- osd_printf_verbose("Joystick: End deinitialization\n");
-}
-
-//============================================================
-// sdlinput_register_mice
-//============================================================
-
-#if defined(SDL2_MULTIAPI) && 0
-static void sdlinput_register_mice(running_machine &machine)
-{
- int index, physical_mouse;
-
- mouse_enabled = machine.options().mouse();
-
- devmap_init(machine, &mouse_map, SDLOPTION_MOUSEINDEX, 8, "Mouse mapping");
-
- for (physical_mouse = 0; physical_mouse < SDL_GetNumMice(); physical_mouse++)
- {
- char *mouse_name = remove_spaces(machine, SDL_GetMouseName(physical_mouse));
-
- devmap_register(&mouse_map, physical_mouse, mouse_name);
- }
-
- osd_printf_verbose("Mouse: Start initialization\n");
- for (index = 0; index < MAX_DEVMAP_ENTRIES; index++)
- {
- device_info *devinfo;
- char defname[90];
- int button;
-
- devinfo = devmap_class_register(machine, &mouse_map, index, &mouse_list, DEVICE_CLASS_MOUSE);
-
- if (devinfo == NULL)
- continue;
-
- // add the axes
- sprintf(defname, "X %s", devinfo->name.c_str());
- devinfo->device->add_item(defname, ITEM_ID_XAXIS, generic_axis_get_state, &devinfo->mouse.lX);
- sprintf(defname, "Y %s", devinfo->name.c_str());
- devinfo->device->add_item(defname, ITEM_ID_YAXIS, generic_axis_get_state, &devinfo->mouse.lY);
-
- for (button = 0; button < 4; button++)
- {
- input_item_id itemid;
-
- sprintf(defname, "B%d", button + 1);
- itemid = (input_item_id) (ITEM_ID_BUTTON1+button);
-
- devinfo->device->add_item(defname, itemid, generic_button_get_state, &devinfo->mouse.buttons[button]);
- }
-
- if (0 && mouse_enabled)
- SDL_SetRelativeMouseMode(index, SDL_TRUE);
- osd_printf_verbose("Mouse: Registered %s\n", devinfo->name.c_str());
- }
- osd_printf_verbose("Mouse: End initialization\n");
-}
-#else
-static void sdlinput_register_mice(running_machine &machine)
-{
- device_info *devinfo;
- char defname[20];
- int button;
-
- osd_printf_verbose("Mouse: Start initialization\n");
-
- mouse_map.logical[0] = 0;
-
- // SDL 1.2 has only 1 mouse - 1.3+ will also change that, so revisit this then
- devinfo = generic_device_alloc(&mouse_list, "System mouse");
- devinfo->device = machine.input().device_class(DEVICE_CLASS_MOUSE).add_device(devinfo->name.c_str(), devinfo);
-
- mouse_enabled = machine.options().mouse();
-
- // add the axes
- devinfo->device->add_item("X", ITEM_ID_XAXIS, generic_axis_get_state, &devinfo->mouse.lX);
- devinfo->device->add_item("Y", ITEM_ID_YAXIS, generic_axis_get_state, &devinfo->mouse.lY);
-
- for (button = 0; button < 4; button++)
- {
- input_item_id itemid = (input_item_id) (ITEM_ID_BUTTON1+button);
- sprintf(defname, "B%d", button + 1);
-
- devinfo->device->add_item(defname, itemid, generic_button_get_state, &devinfo->mouse.buttons[button]);
- }
-
- osd_printf_verbose("Mouse: Registered %s\n", devinfo->name.c_str());
- osd_printf_verbose("Mouse: End initialization\n");
-}
-#endif
-
-#if (USE_XINPUT)
-//============================================================
-// lightgun helpers: copy-past from xinfo
-//============================================================
-
-XDeviceInfo*
-find_device_info(Display *display,
- char *name,
- Bool only_extended)
-{
- XDeviceInfo *devices;
- XDeviceInfo *found = NULL;
- int loop;
- int num_devices;
- int len = strlen(name);
- Bool is_id = True;
- XID id = (XID)-1;
-
- for(loop=0; loop<len; loop++) {
- if (!isdigit(name[loop])) {
- is_id = False;
- break;
- }
- }
-
- if (is_id) {
- id = atoi(name);
- }
-
- devices = XListInputDevices(display, &num_devices);
-
- for(loop=0; loop<num_devices; loop++) {
- if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
- ((!is_id && strcmp(devices[loop].name, name) == 0) ||
- (is_id && devices[loop].id == id))) {
- if (found) {
- fprintf(stderr,
- "Warning: There are multiple devices named \"%s\".\n"
- "To ensure the correct one is selected, please use "
- "the device ID instead.\n\n", name);
- } else {
- found = &devices[loop];
- }
- }
- }
- return found;
-}
-
-//Copypasted from xinfo
-static int
-register_events(Display *dpy,
- XDeviceInfo *info,
- char *dev_name,
- Bool handle_proximity)
-{
- int number = 0; /* number of events registered */
- XEventClass event_list[7];
- int i;
- XDevice *device;
- Window root_win;
- unsigned long screen;
- XInputClassInfo *ip;
-
- screen = DefaultScreen(dpy);
- root_win = RootWindow(dpy, screen);
-
- device = XOpenDevice(dpy, info->id);
-
- if (!device) {
- fprintf(stderr, "unable to open device %s\n", dev_name);
- return 0;
- }
-
- if (device->num_classes > 0) {
- for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) {
- switch (ip->input_class) {
- case KeyClass:
- DeviceKeyPress(device, key_press_type, event_list[number]); number++;
- DeviceKeyRelease(device, key_release_type, event_list[number]); number++;
- break;
-
- case ButtonClass:
- DeviceButtonPress(device, button_press_type, event_list[number]); number++;
- DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
- break;
-
- case ValuatorClass:
- DeviceMotionNotify(device, motion_type, event_list[number]); number++;
- fprintf(stderr, "Motion = %i\n",motion_type);
- if (handle_proximity) {
- ProximityIn(device, proximity_in_type, event_list[number]); number++;
- ProximityOut(device, proximity_out_type, event_list[number]); number++;
- }
- break;
-
- default:
- fprintf(stderr, "unknown class\n");
- break;
- }
- }
-
- if (XSelectExtensionEvent(dpy, root_win, event_list, number)) {
- fprintf(stderr, "error selecting extended events\n");
- return 0;
- }
- }
- return number;
-}
-
-//============================================================
-// sdlinput_register_lightguns
-//============================================================
-
-static void sdlinput_register_lightguns(running_machine &machine)
-{
- int index;
- XExtensionVersion *version;
-
- lightgun_enabled = machine.options().lightgun();
- devmap_init(machine, &lightgun_map, SDLOPTION_LIGHTGUNINDEX, 8, "Lightgun mapping");
-
- XDisplay = XOpenDisplay(NULL);
-
- if (XDisplay == NULL) {
- fprintf(stderr, "Unable to connect to X server\n");
- return;
- }
-
- version = XGetExtensionVersion(XDisplay, INAME);
-
- if (!version || (version == (XExtensionVersion*) NoSuchExtension)) {
- fprintf(stderr, "xinput extension not available!\n");
- return;
- }
-
-
- for (index=0; index<8; index++) {
- XDeviceInfo *info;
- if (strlen(lightgun_map.map[index].name)!=0) {
- device_info *devinfo;
- char *name=lightgun_map.map[index].name;
- char defname[512];
- devinfo = devmap_class_register(machine, &lightgun_map, index, &lightgun_list, DEVICE_CLASS_LIGHTGUN);
- fprintf(stderr, "%i: %s\n",index, name);
- info=find_device_info(XDisplay, name, 0);
- if (!info) continue;
-
- //Grab device info and translate to stuff mame can use
- if (info->num_classes > 0) {
- XAnyClassPtr any = (XAnyClassPtr) (info->inputclassinfo);
- int i;
- for (i=0; i<info->num_classes; i++) {
- int button;
- XValuatorInfoPtr v;
- XAxisInfoPtr a;
- int j;
- XButtonInfoPtr b;
-#if defined(__cplusplus) || defined(c_plusplus)
- switch (any->c_class) {
-#else
- switch (any->class) {
-#endif
- case ButtonClass:
- b = (XButtonInfoPtr) any;
- for (button = 0; button < b->num_buttons; button++)
- {
- input_item_id itemid;
- itemid = (input_item_id) (ITEM_ID_BUTTON1 + button);
- sprintf(defname, "B%d", button + 1);
- devinfo->device->add_item(defname, itemid, generic_button_get_state, &devinfo->lightgun.buttons[button]);
- }
- break;
- case ValuatorClass:
- v = (XValuatorInfoPtr) any;
- a = (XAxisInfoPtr) ((char *) v + sizeof (XValuatorInfo));
- for (j=0; j<v->num_axes; j++, a++) {
- if (j==0) {
-#if (USE_XINPUT_DEBUG)
- fprintf(stderr, "For index %d: Set minx=%d, maxx=%d\n",
- index,
- a->min_value, a->max_value);
-#endif
- devinfo->lightgun.maxx=a->max_value;
- devinfo->lightgun.minx=a->min_value;
- }
- if (j==1) {
-#if (USE_XINPUT_DEBUG)
- fprintf(stderr, "For index %d: Set miny=%d, maxy=%d\n",
- index,
- a->min_value, a->max_value);
-#endif
- devinfo->lightgun.maxy=a->max_value;
- devinfo->lightgun.miny=a->min_value;
- }
- }
- break;
- }
- any = (XAnyClassPtr) ((char *) any + any->length);
- }
- }
-
-
- sprintf(defname, "X %s", devinfo->name.c_str());
- devinfo->device->add_item(defname, ITEM_ID_XAXIS, generic_axis_get_state, &devinfo->lightgun.lX);
- sprintf(defname, "Y %s", devinfo->name.c_str());
- devinfo->device->add_item(defname, ITEM_ID_YAXIS, generic_axis_get_state, &devinfo->lightgun.lY);
-
-
- devinfo->lightgun.deviceid=info->id;
- if (!info) {
- fprintf(stderr, "Can't find device %s!\n", lightgun_map.map[index].name);
- } else {
- fprintf(stderr, "Device %i: Registered %i events.\n",(int)info->id, register_events(XDisplay, info, lightgun_map.map[index].name, 0));
- }
- }
- }
- osd_printf_verbose("Lightgun: End initialization\n");
-}
-#endif
-
-//============================================================
-// lookup_sdl_code
-//============================================================
-
-static int lookup_sdl_code(const char *scode)
-{
- int i=0;
-
- while (sdl_lookup_table[i].code>=0)
- {
- if (!strcmp(scode, sdl_lookup_table[i].name))
- return sdl_lookup_table[i].code;
- i++;
- }
- return -1;
-}
-
-
-//============================================================
-// lookup_mame_code
-//============================================================
-
-static int lookup_mame_index(const char *scode)
-{
- int index, i;
-
- index=-1;
- i=0;
- while (sdl_key_trans_table[i].mame_key != ITEM_ID_INVALID)
- {
- if (!strcmp(scode, sdl_key_trans_table[i].mame_key_name))
- {
- index=i;
- break;
- }
- i++;
- }
- return index;
-}
-
-static input_item_id lookup_mame_code(const char *scode)
-{
- int index;
- index = lookup_mame_index(scode);
- if (index >= 0)
- return sdl_key_trans_table[index].mame_key;
- else
- return ITEM_ID_INVALID;
-}
-
-
-//============================================================
-// sdlinput_read_keymap
-//============================================================
-
-static kt_table * sdlinput_read_keymap(running_machine &machine)
-{
- char *keymap_filename;
- kt_table *key_trans_table;
- FILE *keymap_file;
- int line = 1;
- int index,i, sk, vk, ak;
- char buf[256];
- char mks[41];
- char sks[41];
- char kns[41];
- int sdl2section=0;
-
- if (!machine.options().bool_value(SDLOPTION_KEYMAP))
- return sdl_key_trans_table;
-
- keymap_filename = (char *)downcast<sdl_options &>(machine.options()).keymap_file();
- osd_printf_verbose("Keymap: Start reading keymap_file %s\n", keymap_filename);
-
- keymap_file = fopen(keymap_filename, "r");
- if (keymap_file == NULL)
- {
- osd_printf_warning( "Keymap: Unable to open keymap %s, using default\n", keymap_filename);
- return sdl_key_trans_table;
- }
-
- key_trans_table = auto_alloc_array(machine, kt_table, ARRAY_LENGTH(sdl_key_trans_table));
- memcpy((void *) key_trans_table, sdl_key_trans_table, sizeof(sdl_key_trans_table));
-
- while (!feof(keymap_file))
- {
- char *ret = fgets(buf, 255, keymap_file);
- if (ret && buf[0] != '\n' && buf[0] != '#')
- {
- buf[255]=0;
- i=strlen(buf);
- if (i && buf[i-1] == '\n')
- buf[i-1] = 0;
- if (strncmp(buf,"[SDL2]",6) == 0)
- {
- sdl2section = 1;
- }
- else if (((1) ^ sdl2section) == 0)
- {
- mks[0]=0;
- sks[0]=0;
- memset(kns, 0, ARRAY_LENGTH(kns));
- sscanf(buf, "%40s %40s %x %x %40c\n",
- mks, sks, &vk, &ak, kns);
-
- index=lookup_mame_index(mks);
- sk = lookup_sdl_code(sks);
-
- if ( sk >= 0 && index >=0)
- {
- key_trans_table[index].sdl_key = sk;
- // vk and ak are not really needed
- //key_trans_table[index][VIRTUAL_KEY] = vk;
- //key_trans_table[index][ASCII_KEY] = ak;
- key_trans_table[index].ui_name = auto_alloc_array(machine, char, strlen(kns)+1);
- strcpy(key_trans_table[index].ui_name, kns);
- osd_printf_verbose("Keymap: Mapped <%s> to <%s> with ui-text <%s>\n", sks, mks, kns);
- }
- else
- osd_printf_warning("Keymap: Error on line %d - %s key not found: %s\n", line, (sk<0) ? "sdl" : "mame", buf);
- }
- }
- line++;
- }
- fclose(keymap_file);
- osd_printf_verbose("Keymap: Processed %d lines\n", line);
-
- return key_trans_table;
-}
-
-
-//============================================================
-// sdlinput_register_keyboards
-//============================================================
-
-#ifdef SDL2_MULTIAPI
-static void sdlinput_register_keyboards(running_machine &machine)
-{
- int physical_keyboard;
- int index;
- kt_table *key_trans_table;
-
- key_trans_table = sdlinput_read_keymap(machine);
-
- devmap_init(machine, &keyboard_map, SDLOPTION_KEYBINDEX, 8, "Keyboard mapping");
-
- for (physical_keyboard = 0; physical_keyboard < SDL_GetNumKeyboards(); physical_keyboard++)
- {
- //char defname[90];
- //snprintf(defname, sizeof(defname)-1, "Keyboard #%d", physical_keyboard + 1);
- char *defname = remove_spaces(machine, SDL_GetKeyboardName(SDL_GetKeyboard(physical_keyboard) ));
-
- devmap_register(&keyboard_map, physical_keyboard, defname);
- }
-
- osd_printf_verbose("Keyboard: Start initialization\n");
- for (index = 0; index < MAX_DEVMAP_ENTRIES; index++)
- {
- device_info *devinfo;
- char defname[90];
- int keynum;
-
- devinfo = devmap_class_register(machine, &keyboard_map, index, &keyboard_list, DEVICE_CLASS_KEYBOARD);
-
- if (devinfo == NULL)
- continue;
-
- // populate it
- for (keynum = 0; sdl_key_trans_table[keynum].mame_key!= ITEM_ID_INVALID; keynum++)
- {
- input_item_id itemid;
-
- itemid = key_trans_table[keynum].mame_key;
-
- // generate the default / modified name
- snprintf(defname, sizeof(defname)-1, "%s", key_trans_table[keynum].ui_name);
-
- // add the item to the device
- devinfo->device->add_item(defname, itemid, generic_button_get_state, &devinfo->keyboard.state[OSD_SDL_INDEX(key_trans_table[keynum].sdl_key)]);
- }
-
- osd_printf_verbose("Keyboard: Registered %s\n", devinfo->name.c_str());
- }
- osd_printf_verbose("Keyboard: End initialization\n");
-}
-#else
-static void sdlinput_register_keyboards(running_machine &machine)
-{
- device_info *devinfo;
- char defname[20];
- int keynum;
- kt_table *key_trans_table;
-
- key_trans_table = sdlinput_read_keymap(machine);
-
- keyboard_map.logical[0] = 0;
-
- osd_printf_verbose("Keyboard: Start initialization\n");
-
- // SDL 1.2 only has 1 keyboard (1.3+ will have multiple, this must be revisited then)
- // add it now
- devinfo = generic_device_alloc(&keyboard_list, "System keyboard");
- devinfo->device = machine.input().device_class(DEVICE_CLASS_KEYBOARD).add_device(devinfo->name.c_str(), devinfo);
-
- // populate it
- for (keynum = 0; sdl_key_trans_table[keynum].mame_key != ITEM_ID_INVALID; keynum++)
- {
- input_item_id itemid;
-
- itemid = key_trans_table[keynum].mame_key;
-
- // generate the default / modified name
- snprintf(defname, sizeof(defname)-1, "%s", key_trans_table[keynum].ui_name);
-
- // add the item to the device
-// printf("Keynum %d => sdl key %d\n", keynum, OSD_SDL_INDEX(key_trans_table[keynum].sdl_key));
- devinfo->device->add_item(defname, itemid, generic_button_get_state, &devinfo->keyboard.state[OSD_SDL_INDEX(key_trans_table[keynum].sdl_key)]);
- }
-
- osd_printf_verbose("Keyboard: Registered %s\n", devinfo->name.c_str());
- osd_printf_verbose("Keyboard: End initialization\n");
-}
-#endif
-
-//============================================================
-// input_init
-//============================================================
-
-bool sdl_osd_interface::input_init()
-{
- keyboard_list = NULL;
- joystick_list = NULL;
- mouse_list = NULL;
- lightgun_list = NULL;
-
- app_has_mouse_focus = 1;
-
- // register the keyboards
- sdlinput_register_keyboards(machine());
-
- // register the mice
- sdlinput_register_mice(machine());
-
-#if (USE_XINPUT)
- // register the lightguns
- sdlinput_register_lightguns(machine());
-#endif
-
- if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED)
- {
- osd_printf_warning("Debug Build: Disabling input grab for -debug\n");
- mouse_enabled = 0;
- }
-
- // get Sixaxis special mode info
- sixaxis_mode = options().sixaxis();
-
- // register the joysticks
- sdlinput_register_joysticks(machine());
-
- // now reset all devices
- device_list_reset_devices(keyboard_list);
- device_list_reset_devices(mouse_list);
- device_list_reset_devices(joystick_list);
-#if (USE_XINPUT)
- device_list_reset_devices(lightgun_list);
-#endif
- return true;
-}
-
-
-//============================================================
-// sdlinput_pause
-//============================================================
-
-void sdl_osd_interface::input_pause()
-{
- // keep track of the paused state
- input_paused = true;
-}
-
-void sdl_osd_interface::input_resume()
-{
- // keep track of the paused state
- input_paused = false;
-}
-
-
-//============================================================
-// sdlinput_exit
-//============================================================
-
-void sdl_osd_interface::input_exit()
-{
- // deregister
-
- sdlinput_deregister_joysticks(machine());
-
- // free all devices
- device_list_free_devices(&keyboard_list);
- device_list_free_devices(&mouse_list);
- device_list_free_devices(&joystick_list);
-}
-
-
-//============================================================
-// sdlinput_get_focus_window
-//============================================================
-
-sdl_window_info *sdlinput_get_focus_window()
-{
- if (focus_window) // only be set on SDL >= 1.3
- return focus_window;
- else
- return sdl_window_list;
-}
-
-#if (USE_XINPUT)
-device_info *get_lightgun_info_for_deviceid(XID deviceid) {
- device_info *devinfo;
- int index;
- //Find lightgun according to device id
- for (index=0; ; index++) {
- devinfo = generic_device_find_index(lightgun_list, index);
- if (devinfo==NULL) break;
- if (devinfo->lightgun.deviceid==deviceid) break;
- }
- return devinfo;
-}
-
-INT32 normalize_absolute_axis(INT32 raw, INT32 rawmin, INT32 rawmax)
-{
- INT32 rv;
-
- INT32 center = ((INT64)rawmax + (INT64)rawmin) / 2;
-
- // make sure we have valid data
- if (rawmin >= rawmax)
- {
- rv = raw;
- goto out;
- }
-
- // above center
- if (raw >= center)
- {
- INT32 result = (INT64)(raw - center) * (INT64)INPUT_ABSOLUTE_MAX / (INT64)(rawmax - center);
- rv = MIN(result, INPUT_ABSOLUTE_MAX);
- goto out;
- }
-
- // below center
- else
- {
- INT32 result = -((INT64)(center - raw) * (INT64)-INPUT_ABSOLUTE_MIN / (INT64)(center - rawmin));
- rv = MAX(result, INPUT_ABSOLUTE_MIN);
- goto out;
- }
-
- out:
-
-#if (USE_XINPUT_DEBUG)
- fprintf(stderr, "raw: %d, rawmin: %d, rawmax: %d, center: %d, rv: %d, ABS_MIN: %d, ABS_MAX: %d\n",
- raw, rawmin, rawmax, center, rv, INPUT_ABSOLUTE_MIN, INPUT_ABSOLUTE_MAX);
-#endif
-
- return rv;
-}
-#endif
-
-//============================================================
-// sdlinput_poll
-//============================================================
-
-static inline sdl_window_info * window_from_id(Uint32 windowID)
-{
- sdl_window_info *w;
- SDL_Window *window = SDL_GetWindowFromID(windowID);
-
- for (w = sdl_window_list; w != NULL; w = w->m_next)
- {
- //printf("w->window_id: %d\n", w->window_id);
- if (w->sdl_window() == window)
- {
- return w;
- }
- }
- return NULL;
-}
-
-static inline void resize_all_windows(void)
-{
- sdl_window_info *w;
- osd_ticks_t now = osd_ticks();
-
- if (SDL13_COMBINE_RESIZE)
- {
- for (w = sdl_window_list; w != NULL; w = w->m_next)
- {
- if (w->m_resize_width && w->m_resize_height && ((now - w->m_last_resize) > osd_ticks_per_second() / 10))
- {
- w->resize(w->m_resize_width, w->m_resize_height);
- w->m_resize_width = 0;
- w->m_resize_height = 0;
- }
- }
- }
-}
-
-void sdlinput_process_events_buf()
-{
- SDL_Event event;
-
- if (SDLMAME_EVENTS_IN_WORKER_THREAD)
- {
- std::lock_guard<std::mutex> lock(input_lock);
- /* Make sure we get all pending events */
- SDL_PumpEvents();
- while(SDL_PollEvent(&event))
- {
- if (event_buf_count < MAX_BUF_EVENTS)
- event_buf[event_buf_count++] = event;
- else
- osd_printf_warning("Event Buffer Overflow!\n");
- }
- }
- else
- SDL_PumpEvents();
-}
-
-
-void sdlinput_poll(running_machine &machine)
-{
- device_info *devinfo;
- SDL_Event event;
- int index;
-
- // only for SDLMAME_EVENTS_IN_WORKER_THREAD
- SDL_Event loc_event_buf[MAX_BUF_EVENTS];
- int loc_event_buf_count;
- int bufp;
-
-#if (USE_XINPUT)
- XEvent xevent;
-#endif
-
- for (index=0; ;index++)
- {
- devinfo = generic_device_find_index( mouse_list, index);
- if (devinfo == NULL)
- break;
- devinfo->mouse.lX = 0;
- devinfo->mouse.lY = 0;
- }
-
-#if (USE_XINPUT)
- //Get XInput events
- while (XPending(XDisplay)!=0)
- {
- XNextEvent(XDisplay, &xevent);
- if (xevent.type==motion_type)
- {
- XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &xevent;
-
-#if (USE_XINPUT_DEBUG)
- /*
- * print a lot of debug informations of the motion event(s).
- */
- fprintf(stderr,
- "XDeviceMotionEvent:\n"
- " type: %d\n"
- " serial: %lu\n"
- " send_event: %d\n"
- " display: %p\n"
- " window: --\n"
- " deviceid: %lu\n"
- " root: --\n"
- " subwindow: --\n"
- " time: --\n"
- " x: %d, y: %d\n"
- " x_root: %d, y_root: %d\n"
- " state: %u\n"
- " is_hint: %2.2X\n"
- " same_screen: %d\n"
- " device_state: %u\n"
- " axes_count: %2.2X\n"
- " first_axis: %2.2X\n"
- " axis_data[6]: {%d,%d,%d,%d,%d,%d}\n",
- motion->type,
- motion->serial,
- motion->send_event,
- motion->display,
- /* motion->window, */
- motion->deviceid,
- /* motion->root */
- /* motion->subwindow */
- /* motion->time, */
- motion->x, motion->y,
- motion->x_root, motion->y_root,
- motion->state,
- motion->is_hint,
- motion->same_screen,
- motion->device_state,
- motion->axes_count,
- motion->first_axis,
- motion->axis_data[0], motion->axis_data[1], motion->axis_data[2], motion->axis_data[3], motion->axis_data[4], motion->axis_data[5]
- );
-#endif
-
- devinfo=get_lightgun_info_for_deviceid(motion->deviceid);
-
- /*
- * We have to check with axis will start on array index 0.
- * We have also to check the number of axes that are stored in the array.
- */
- switch (motion->first_axis)
- {
- /*
- * Starting with x, check number of axis, if there is also the y axis stored.
- */
- case 0:
- if (motion->axes_count >= 1)
- {
- devinfo->lightgun.lX=normalize_absolute_axis(motion->axis_data[0], devinfo->lightgun.minx, devinfo->lightgun.maxx);
- if (motion->axes_count >= 2)
- {
- devinfo->lightgun.lY=normalize_absolute_axis(motion->axis_data[1], devinfo->lightgun.miny, devinfo->lightgun.maxy);
- }
- }
- break;
-
- /*
- * Starting with y, ...
- */
- case 1:
- if (motion->axes_count >= 1)
- {
- devinfo->lightgun.lY=normalize_absolute_axis(motion->axis_data[0], devinfo->lightgun.miny, devinfo->lightgun.maxy);
- }
- break;
- }
- }
- else if (xevent.type==button_press_type || xevent.type==button_release_type)
- {
- XDeviceButtonEvent *button = (XDeviceButtonEvent *) &xevent;
- devinfo=get_lightgun_info_for_deviceid(button->deviceid);
- devinfo->lightgun.buttons[button->button]=(xevent.type==button_press_type)?0x80:0;
- }
- }
-#endif
-
- if (SDLMAME_EVENTS_IN_WORKER_THREAD)
- {
- std::lock_guard<std::mutex> lock(input_lock);
- memcpy(loc_event_buf, event_buf, sizeof(event_buf));
- loc_event_buf_count = event_buf_count;
- event_buf_count = 0;
- bufp = 0;
- }
-
- while (TRUE)
- {
- if (SDLMAME_EVENTS_IN_WORKER_THREAD)
- {
- if (bufp >= loc_event_buf_count)
- break;
- event = loc_event_buf[bufp++];
- }
- else
- {
- if (!SDL_PollEvent(&event))
- break;
- }
- switch(event.type) {
- case SDL_KEYDOWN:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index( keyboard_list, keyboard_map.logical[event.key.which]);
- //printf("Key down %d %d %s => %d %s (scrlock keycode is %d)\n", event.key.which, event.key.keysym.scancode, devinfo->name.c_str(), OSD_SDL_INDEX_KEYSYM(&event.key.keysym), sdl_key_trans_table[event.key.keysym.scancode].mame_key_name, KEYCODE_SCRLOCK);
-#else
- devinfo = generic_device_find_index( keyboard_list, keyboard_map.logical[0]);
-#endif
- devinfo->keyboard.state[OSD_SDL_INDEX_KEYSYM(&event.key.keysym)] = 0x80;
- if (event.key.keysym.sym < 0x20)
- machine.ui_input().push_char_event(sdl_window_list->target(), event.key.keysym.sym);
- break;
- case SDL_KEYUP:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index( keyboard_list, keyboard_map.logical[event.key.which]);
- //printf("Key up: %d %d\n", OSD_SDL_INDEX_KEYSYM(&event.key.keysym), event.key.which);
-#else
- devinfo = generic_device_find_index( keyboard_list, keyboard_map.logical[0]);
-#endif
- devinfo->keyboard.state[OSD_SDL_INDEX_KEYSYM(&event.key.keysym)] = 0x00;
- break;
- case SDL_JOYAXISMOTION:
- devinfo = generic_device_find_index(joystick_list, joy_map.logical[event.jaxis.which]);
- if (devinfo)
- {
- if (sixaxis_mode)
- {
- int axis = event.jaxis.axis;
-
- if (axis <= 3)
- {
- devinfo->joystick.axes[event.jaxis.axis] = (event.jaxis.value * 2);
- }
- else
- {
- int magic = (event.jaxis.value / 2) + 16384;
-
- devinfo->joystick.axes[event.jaxis.axis] = magic;
- }
- }
- else
- {
- devinfo->joystick.axes[event.jaxis.axis] = (event.jaxis.value * 2);
- }
- }
- break;
- case SDL_JOYHATMOTION:
- devinfo = generic_device_find_index(joystick_list, joy_map.logical[event.jhat.which]);
- if (devinfo)
- {
- if (event.jhat.value & SDL_HAT_UP)
- {
- devinfo->joystick.hatsU[event.jhat.hat] = 0x80;
- }
- else
- {
- devinfo->joystick.hatsU[event.jhat.hat] = 0;
- }
- if (event.jhat.value & SDL_HAT_DOWN)
- {
- devinfo->joystick.hatsD[event.jhat.hat] = 0x80;
- }
- else
- {
- devinfo->joystick.hatsD[event.jhat.hat] = 0;
- }
- if (event.jhat.value & SDL_HAT_LEFT)
- {
- devinfo->joystick.hatsL[event.jhat.hat] = 0x80;
- }
- else
- {
- devinfo->joystick.hatsL[event.jhat.hat] = 0;
- }
- if (event.jhat.value & SDL_HAT_RIGHT)
- {
- devinfo->joystick.hatsR[event.jhat.hat] = 0x80;
- }
- else
- {
- devinfo->joystick.hatsR[event.jhat.hat] = 0;
- }
- }
- break;
- case SDL_JOYBUTTONDOWN:
- case SDL_JOYBUTTONUP:
- devinfo = generic_device_find_index(joystick_list, joy_map.logical[event.jbutton.which]);
- if (devinfo)
- {
- devinfo->joystick.buttons[event.jbutton.button] = (event.jbutton.state == SDL_PRESSED) ? 0x80 : 0;
- }
- break;
- case SDL_MOUSEBUTTONDOWN:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[event.button.which]);
-#else
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[0]);
-#endif
- devinfo->mouse.buttons[event.button.button-1] = 0x80;
- //printf("But down %d %d %d %d %s\n", event.button.which, event.button.button, event.button.x, event.button.y, devinfo->name.c_str());
- if (event.button.button == 1)
- {
- // FIXME Move static declaration
- static osd_ticks_t last_click = 0;
- static int last_x = 0;
- static int last_y = 0;
- int cx, cy;
- osd_ticks_t click = osd_ticks() * 1000 / osd_ticks_per_second();
- sdl_window_info *window = GET_FOCUS_WINDOW(&event.button);
- if (window != NULL && window->xy_to_render_target(event.button.x,event.button.y, &cx, &cy) )
- {
- machine.ui_input().push_mouse_down_event(window->target(), cx, cy);
- // FIXME Parameter ?
- if ((click-last_click < 250)
- && (cx >= last_x - 4 && cx <= last_x + 4)
- && (cy >= last_y - 4 && cy <= last_y + 4) )
- {
- last_click = 0;
- machine.ui_input().push_mouse_double_click_event(window->target(), cx, cy);
- }
- else
- {
- last_click = click;
- last_x = cx;
- last_y = cy;
- }
- }
- }
- break;
- case SDL_MOUSEWHEEL:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[event.wheel.which]);
-#else
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[0]);
-#endif
- if (devinfo)
- {
- sdl_window_info *window = GET_FOCUS_WINDOW(&event.wheel);
- if (window != NULL)
- machine.ui_input().push_mouse_wheel_event(window->target(), 0, 0, event.wheel.y, 3);
- }
- break;
- case SDL_MOUSEBUTTONUP:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[event.button.which]);
-#else
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[0]);
-#endif
- devinfo->mouse.buttons[event.button.button-1] = 0;
- //printf("But up %d %d %d %d\n", event.button.which, event.button.button, event.button.x, event.button.y);
-
- if (event.button.button == 1)
- {
- int cx, cy;
- sdl_window_info *window = GET_FOCUS_WINDOW(&event.button);
-
- if (window != NULL && window->xy_to_render_target(event.button.x,event.button.y, &cx, &cy) )
- {
- machine.ui_input().push_mouse_up_event(window->target(), cx, cy);
- }
- }
- break;
- case SDL_MOUSEMOTION:
-#ifdef SDL2_MULTIAPI
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[event.motion.which]);
-#else
- devinfo = generic_device_find_index(mouse_list, mouse_map.logical[0]);
-#endif
- // FIXME: may apply to 1.2 as well ...
- //printf("Motion %d %d %d %s\n", event.motion.which, event.motion.x, event.motion.y, devinfo->name.c_str());
- devinfo->mouse.lX += event.motion.xrel * INPUT_RELATIVE_PER_PIXEL;
- devinfo->mouse.lY += event.motion.yrel * INPUT_RELATIVE_PER_PIXEL;
- {
- int cx=-1, cy=-1;
- sdl_window_info *window = GET_FOCUS_WINDOW(&event.motion);
-
- if (window != NULL && window->xy_to_render_target(event.motion.x, event.motion.y, &cx, &cy) )
- machine.ui_input().push_mouse_move_event(window->target(), cx, cy);
- }
- break;
- case SDL_JOYBALLMOTION:
- devinfo = generic_device_find_index(joystick_list, joy_map.logical[event.jball.which]);
- //printf("Ball %d %d\n", event.jball.xrel, event.jball.yrel);
- devinfo->joystick.balls[event.jball.ball * 2] = event.jball.xrel * INPUT_RELATIVE_PER_PIXEL;
- devinfo->joystick.balls[event.jball.ball * 2 + 1] = event.jball.yrel * INPUT_RELATIVE_PER_PIXEL;
- break;
- case SDL_TEXTINPUT:
- if (*event.text.text)
- {
- sdl_window_info *window = GET_FOCUS_WINDOW(&event.text);
- //printf("Focus window is %p - wl %p\n", window, sdl_window_list);
- unicode_char result;
- if (window != NULL )
- {
- osd_uchar_from_osdchar(&result, event.text.text, 1);
- machine.ui_input().push_char_event(window->target(), result);
- }
- }
- break;
- case SDL_WINDOWEVENT:
- {
- sdl_window_info *window = GET_WINDOW(&event.window);
-
- if (window == NULL)
- break;
-
- switch (event.window.event)
- {
- case SDL_WINDOWEVENT_CLOSE:
- machine.schedule_exit();
- break;
- case SDL_WINDOWEVENT_LEAVE:
- machine.ui_input().push_mouse_leave_event(window->target());
- app_has_mouse_focus = 0;
- break;
- case SDL_WINDOWEVENT_MOVED:
- window->notify_changed();
- focus_window = window;
- break;
- case SDL_WINDOWEVENT_RESIZED:
- if (SDL13_COMBINE_RESIZE)
- {
- window->m_resize_width = event.window.data1;
- window->m_resize_height = event.window.data2;
- window->m_last_resize = osd_ticks();
- }
- else
- {
-#ifndef SDLMAME_WIN32
- /* FIXME: SDL2 sends some spurious resize events on Ubuntu
- * while in fullscreen mode. Ignore them for now.
- */
- if (!window->fullscreen())
-#endif
- {
- //printf("event data1,data2 %d x %d %ld\n", event.window.data1, event.window.data2, sizeof(SDL_Event));
- window->resize(event.window.data1, event.window.data2);
- }
- }
- focus_window = window;
- break;
- case SDL_WINDOWEVENT_ENTER:
- app_has_mouse_focus = 1;
- /* fall through */
- case SDL_WINDOWEVENT_FOCUS_GAINED:
- case SDL_WINDOWEVENT_EXPOSED:
- case SDL_WINDOWEVENT_MAXIMIZED:
- case SDL_WINDOWEVENT_RESTORED:
- focus_window = window;
- break;
- }
- break;
- }
- }
- }
- resize_all_windows();
-}
-
-
-//============================================================
-// sdlinput_release_keys
-//============================================================
-
-
-void sdlinput_release_keys()
-{
- device_info *devinfo;
- int index;
-
- for (index = 0; ;index++)
- {
- devinfo = generic_device_find_index( keyboard_list, index);
- if (devinfo == NULL)
- break;
- memset(&devinfo->keyboard.state, 0, sizeof(devinfo->keyboard.state));
- }
-}
-
-
-//============================================================
-// sdlinput_should_hide_mouse
-//============================================================
-
-int sdlinput_should_hide_mouse()
-{
- // if we are paused, no
- if (input_paused)
- return FALSE;
-
- // if neither mice nor lightguns enabled in the core, then no
- if (!mouse_enabled && !lightgun_enabled)
- return FALSE;
-
- if (!app_has_mouse_focus)
- return FALSE;
-
- // otherwise, yes
- return TRUE;
-}
-
-
-//============================================================
-// customize_input_type_list
-//============================================================
-
-void sdl_osd_interface::customize_input_type_list(simple_list<input_type_entry> &typelist)
-{
- input_item_id mameid_code;
- input_code ui_code;
- input_type_entry *entry;
- const char* uimode;
- char fullmode[64];
-
- // loop over the defaults
- for (entry = typelist.first(); entry != NULL; entry = entry->next())
- {
- switch (entry->type())
- {
- // configurable UI mode switch
- case IPT_UI_TOGGLE_UI:
- uimode = options().ui_mode_key();
- if(!strcmp(uimode,"auto"))
- {
- #if defined(__APPLE__) && defined(__MACH__)
- mameid_code = lookup_mame_code("ITEM_ID_INSERT");
- #else
- mameid_code = lookup_mame_code("ITEM_ID_SCRLOCK");
- #endif
- }
- else
- {
- snprintf(fullmode, 63, "ITEM_ID_%s", uimode);
- mameid_code = lookup_mame_code(fullmode);
- }
- 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);
- break;
-
- // disable UI_SELECT when LALT is down, this stops selecting
- // things in the menu when toggling fullscreen with LALT+ENTER
-/* case IPT_UI_SELECT:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT);
- break;*/
-
- // page down for fastforward (must be OSD_3 as per src/emu/ui.c)
- case IPT_UI_FAST_FORWARD:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_PGDN);
- break;
-
- // OSD hotkeys use LCTRL and start at F3, they start at
- // F3 because F1-F2 are hardcoded into many drivers to
- // various dipswitches, and pressing them together with
- // LCTRL will still press/toggle these dipswitches.
-
- // LCTRL-F3 to toggle fullstretch
- case IPT_OSD_2:
- entry->configure_osd("TOGGLE_FULLSTRETCH", "Toggle Uneven stretch");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F3, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the reset key
- case IPT_UI_SOFT_RESET:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F3, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
- break;
-
- // LCTRL-F4 to toggle keep aspect
- case IPT_OSD_4:
- entry->configure_osd("TOGGLE_KEEP_ASPECT", "Toggle Keepaspect");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F4, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the show gfx key
- case IPT_UI_SHOW_GFX:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F4, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F5 to toggle OpenGL filtering
- case IPT_OSD_5:
- entry->configure_osd("TOGGLE_FILTER", "Toggle Filter");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the toggle debug key
- case IPT_UI_TOGGLE_DEBUG:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F6 to decrease OpenGL prescaling
- case IPT_OSD_6:
- entry->configure_osd("DECREASE_PRESCALE", "Decrease Prescaling");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the toggle cheat key
- case IPT_UI_TOGGLE_CHEAT:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // LCTRL-F7 to increase OpenGL prescaling
- case IPT_OSD_7:
- entry->configure_osd("INCREASE_PRESCALE", "Increase Prescaling");
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, KEYCODE_LCONTROL);
- break;
- // add a Not lcrtl condition to the load state key
- case IPT_UI_LOAD_STATE:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, input_seq::not_code, KEYCODE_LCONTROL, input_seq::not_code, KEYCODE_LSHIFT);
- break;
-
- // add a Not lcrtl condition to the throttle key
- case IPT_UI_THROTTLE:
- entry->defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F10, input_seq::not_code, KEYCODE_LCONTROL);
- break;
-
- // disable the config menu if the ALT key is down
- // (allows ALT-TAB to switch between 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;
-
- // leave everything else alone
- default:
- break;
- }
- }
-}
-
-
-//============================================================
-// 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);
-}
-
-
-//============================================================
-// device_list_free_devices
-//============================================================
-
-static void device_list_free_devices(device_info **devlist_head)
-{
- device_info *curdev, *next;
-
- for (curdev = *devlist_head; curdev != NULL; )
- {
- next = curdev->next;
- generic_device_free(curdev);
- curdev = next;
- }
- *devlist_head = NULL;
-}
-
-
-//============================================================
-// generic_device_alloc
-//============================================================
-
-static device_info *generic_device_alloc(device_info **devlist_head_ptr, const char *name)
-{
- device_info **curdev_ptr;
- device_info *devinfo;
-
- // allocate memory for the device object
- devinfo = global_alloc_clear<device_info>();
- devinfo->head = devlist_head_ptr;
-
- // allocate a UTF8 copy of the name
- devinfo->name.assign(name);
-
- // append us to the list
- for (curdev_ptr = devinfo->head; *curdev_ptr != NULL; curdev_ptr = &(*curdev_ptr)->next) ;
- *curdev_ptr = devinfo;
-
- return devinfo;
-}
-
-
-//============================================================
-// 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;
-
- // 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;
-}
-
-
-static device_info *generic_device_find_index(device_info *devlist_head, int index)
-{
- device_info *orig_head = devlist_head;
-
- while (devlist_head != NULL)
- {
- if (generic_device_index(orig_head, devlist_head) == index)
- {
- return devlist_head;
- }
-
- devlist_head = devlist_head->next;
- }
- return NULL;
-}
-
-
-//============================================================
-// generic_device_reset
-//============================================================
-
-static void generic_device_reset(device_info *devinfo)
-{
- // keyboard case
- if (devinfo->head == &keyboard_list)
- memset(&devinfo->keyboard, 0, sizeof(devinfo->keyboard));
-
- // mouse/lightgun case
- else if (devinfo->head == &mouse_list || devinfo->head == &lightgun_list)
- memset(&devinfo->mouse, 0, sizeof(devinfo->mouse));
-
- // joystick case
- else if (devinfo->head == &joystick_list)
- {
- memset(&devinfo->joystick, 0, sizeof(devinfo->joystick));
- }
-}
-
-
-//============================================================
-// generic_button_get_state
-//============================================================
-
-static INT32 generic_button_get_state(void *device_internal, void *item_internal)
-{
- INT32 *itemdata = (INT32 *) item_internal;
-
- // return the current state
- return *itemdata >> 7;
-}
-
-
-//============================================================
-// generic_axis_get_state
-//============================================================
-
-static INT32 generic_axis_get_state(void *device_internal, void *item_internal)
-{
- INT32 *axisdata = (INT32 *) item_internal;
-
- // return the current state
- return *axisdata;
-}
diff --git a/src/osd/sdl/input.h b/src/osd/sdl/input.h
deleted file mode 100644
index aa87375a663..00000000000
--- a/src/osd/sdl/input.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// input.h - SDL implementation of MAME input routines
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#ifndef __SDLINPUT_H__
-#define __SDLINPUT_H__
-
-#include "window.h"
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-void sdlinput_poll(running_machine &machine);
-int sdlinput_should_hide_mouse();
-
-sdl_window_info *sdlinput_get_focus_window();
-
-void sdlinput_process_events_buf();
-void sdlinput_release_keys();
-
-#endif /* __SDLINPUT_H__ */
diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h
index 7b3e83c3134..e61008275ec 100644
--- a/src/osd/sdl/osdsdl.h
+++ b/src/osd/sdl/osdsdl.h
@@ -149,18 +149,28 @@ public:
virtual bool video_init() override;
virtual bool window_init() override;
+#ifdef USE_OLD_SDL_INPUT
virtual bool input_init() override;
virtual void input_pause() override;
virtual void input_resume() override;
+#endif
virtual bool output_init() override;
//virtual bool midi_init();
virtual void video_exit() override;
virtual void window_exit() override;
+#ifdef USE_OLD_SDL_INPUT
virtual void input_exit() override;
+#endif
virtual void output_exit() override;
//virtual void midi_exit();
+ // sdl specific
+ void poll_inputs(running_machine &machine);
+ void release_keys();
+ bool should_hide_mouse();
+ void process_events_buf();
+
sdl_options &options() { return m_options; }
private:
diff --git a/src/osd/sdl/sdlmain.cpp b/src/osd/sdl/sdlmain.cpp
index f9015e80552..1a52a105fd5 100644
--- a/src/osd/sdl/sdlmain.cpp
+++ b/src/osd/sdl/sdlmain.cpp
@@ -42,7 +42,6 @@
// OSD headers
#include "video.h"
-#include "input.h"
#include "osdsdl.h"
#include "modules/lib/osdlib.h"
@@ -524,3 +523,4 @@ void sdl_osd_interface::init(running_machine &machine)
SDL_EventState(SDL_TEXTINPUT, SDL_TRUE);
#endif
}
+
diff --git a/src/osd/sdl/video.cpp b/src/osd/sdl/video.cpp
index 503f9149d8f..3df00d90078 100644
--- a/src/osd/sdl/video.cpp
+++ b/src/osd/sdl/video.cpp
@@ -20,7 +20,6 @@
// MAMEOS headers
#include "video.h"
#include "window.h"
-#include "input.h"
#include "osdsdl.h"
#include "modules/lib/osdlib.h"
@@ -163,7 +162,8 @@ void sdl_osd_interface::update(bool skip_redraw)
}
// poll the joystick values here
- sdlinput_poll(machine());
+ downcast<sdl_osd_interface&>(machine().osd()).poll_inputs(machine());
+
check_osd_inputs(machine());
// if we're running, disable some parts of the debugger
if ((machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) != 0)
@@ -286,7 +286,12 @@ finishit:
static void check_osd_inputs(running_machine &machine)
{
+#ifdef USE_OLD_SDL_INPUT
sdl_window_info *window = sdlinput_get_focus_window();
+#else
+ // BUG: TODO: Fix focus window support
+ sdl_window_info *window = sdl_window_list;
+#endif
// check for toggling fullscreen mode
if (machine.ui_input().pressed(IPT_OSD_1))
diff --git a/src/osd/sdl/window.cpp b/src/osd/sdl/window.cpp
index eed3a9afd67..0c5bb7a51ca 100644
--- a/src/osd/sdl/window.cpp
+++ b/src/osd/sdl/window.cpp
@@ -34,7 +34,6 @@
// OSD headers
#include "window.h"
-#include "input.h"
#include "osdsdl.h"
#include "modules/render/drawbgfx.h"
#include "modules/render/drawsdl.h"
@@ -250,14 +249,14 @@ bool sdl_osd_interface::window_init()
if (renderer_sdl2::init(machine()))
{
video_config.mode = VIDEO_MODE_SOFT;
- }
+ }
}
if (video_config.mode == VIDEO_MODE_SOFT)
{
if (renderer_sdl1::init(machine()))
{
return false;
- }
+ }
}
/* We may want to set a number of the hints SDL2 provides.
@@ -579,7 +578,8 @@ OSDWORK_CALLBACK( sdl_window_info::sdlwindow_toggle_full_screen_wt )
SDL_SetWindowFullscreen(window->sdl_window(), SDL_WINDOW_FULLSCREEN); // Try to set mode
}
SDL_DestroyWindow(window->sdl_window());
- sdlinput_release_keys();
+
+ downcast<sdl_osd_interface &>(window->machine().osd()).release_keys();
window->set_renderer(osd_renderer::make_for_type(video_config.mode, reinterpret_cast<osd_window *>(window)));
@@ -651,7 +651,12 @@ void sdl_window_info::update_cursor_state()
{
//FIXME: SDL1.3: really broken: the whole SDL code
// will only work correct with relative mouse movements ...
- if (!fullscreen() && !sdlinput_should_hide_mouse())
+#ifdef USE_OLD_SDL_INPUT
+ bool should_hide_mouse = sdlinput_should_hide_mouse();
+#else
+ bool should_hide_mouse = downcast<sdl_osd_interface&>(machine().osd()).should_hide_mouse();
+#endif
+ if (!fullscreen() && !should_hide_mouse)
{
SDL_ShowCursor(SDL_ENABLE);
if (SDL_GetWindowGrab(sdl_window() ))
@@ -666,7 +671,7 @@ void sdl_window_info::update_cursor_state()
SDL_SetRelativeMouseMode(SDL_TRUE);
}
SDL_SetCursor(nullptr); // Force an update in case the underlying driver has changed visibility
- }
+ }
#endif
}
@@ -775,7 +780,11 @@ OSDWORK_CALLBACK( sdl_window_info::sdlwindow_video_window_destroy_wt )
}
SDL_DestroyWindow(window->sdl_window());
// release all keys ...
+#ifdef USE_OLD_SDL_INPUT
sdlinput_release_keys();
+#else
+ downcast<sdl_osd_interface &>(window->machine().osd()).release_keys();
+#endif
osd_free(wp);
@@ -1119,11 +1128,11 @@ OSDWORK_CALLBACK( sdl_window_info::complete_create_wt )
for (auto w = sdl_window_list; w != nullptr; w = w->m_next)
{
if (w->m_index == 0)
- {
+ {
window->m_main = w;
break;
- }
- }
+ }
+ }
}
window->monitor()->refresh();
// initialize the drawing backend
@@ -1194,7 +1203,11 @@ OSDWORK_CALLBACK( sdl_window_info::draw_video_contents_wt )
ASSERT_REDRAW_THREAD();
// Some configurations require events to be polled in the worker thread
+#ifdef USE_OLD_SDL_INPUT
sdlinput_process_events_buf();
+#else
+ downcast< sdl_osd_interface& >(window->machine().osd()).process_events_buf();
+#endif
// Check whether window has vector screens
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;
-}
diff --git a/src/osd/windows/input.h b/src/osd/windows/input.h
index 983d1867d6f..39a1d63fa5e 100644
--- a/src/osd/windows/input.h
+++ b/src/osd/windows/input.h
@@ -10,18 +10,6 @@
#define __INPUT_H
-//============================================================
-// PROTOTYPES
-//============================================================
-
-void wininput_poll(running_machine &machine);
-
-BOOL wininput_handle_mouse_button(int button, int down, int x, int y);
-BOOL wininput_handle_raw(HANDLE device);
-
-bool wininput_should_hide_mouse(void);
-
-int wininput_vkey_for_mame_code(input_code code);
+#endif /* __INPUT_H */
-#endif /* __INPUT_H */
diff --git a/src/osd/windows/video.cpp b/src/osd/windows/video.cpp
index b2fa493469d..df01b1865d0 100644
--- a/src/osd/windows/video.cpp
+++ b/src/osd/windows/video.cpp
@@ -206,7 +206,7 @@ void windows_osd_interface::update(bool skip_redraw)
// poll the joystick values here
winwindow_process_events(machine(), TRUE, FALSE);
- wininput_poll(machine());
+ poll_input(machine());
check_osd_inputs(machine());
// if we're running, disable some parts of the debugger
if ((machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) != 0)
diff --git a/src/osd/windows/window.cpp b/src/osd/windows/window.cpp
index cc5a219ff01..cf1ec588876 100644
--- a/src/osd/windows/window.cpp
+++ b/src/osd/windows/window.cpp
@@ -36,6 +36,12 @@
#include "modules/render/drawogl.h"
#endif
+#define NOT_ALREADY_DOWN(x) (x & 0x40000000) == 0
+#define SCAN_CODE(x) ((x >> 16) & 0xff)
+#define IS_EXTENDED(x) (0x01000000 & x)
+#define MAKE_DI_SCAN(scan, isextended) (scan & 0x7f) | (isextended ? 0x80 : 0x00)
+#define WINOSD(machine) downcast<windows_osd_interface*>(&machine.osd())
+
//============================================================
// PARAMETERS
//============================================================
@@ -188,7 +194,7 @@ bool windows_osd_interface::window_init()
fatalerror("Failed to create window thread ready event\n");
// create a thread to run the windows from
- temp = _beginthreadex(nullptr, 0, win_window_info::thread_entry, nullptr, 0, (unsigned *)&window_threadid);
+ temp = _beginthreadex(nullptr, 0, win_window_info::thread_entry, this, 0, (unsigned *)&window_threadid);
window_thread = (HANDLE)temp;
if (window_thread == nullptr)
fatalerror("Failed to create window thread\n");
@@ -225,7 +231,7 @@ bool windows_osd_interface::window_init()
{
bool error = false;
switch(current_mode)
- {
+ {
case VIDEO_MODE_NONE:
error = renderer_none::init(machine());
break;
@@ -401,7 +407,7 @@ win_window_info::~win_window_info()
if (m_renderer != nullptr)
{
delete m_renderer;
- }
+}
}
@@ -437,7 +443,31 @@ static BOOL is_mame_window(HWND hwnd)
return FALSE;
}
+inline static BOOL handle_mouse_button(windows_osd_interface *osd, int button, int down, int x, int y)
+{
+ MouseButtonEventArgs args;
+ args.button = button;
+ args.keydown = down;
+ args.xpos = x;
+ args.ypos = y;
+
+ bool handled = osd->handle_input_event(INPUT_EVENT_MOUSE_BUTTON, &args);
+
+ // When in lightgun mode or mouse mode, the mouse click may be routed to the input system
+ // because the mouse interactions in the UI are routed from the video_window_proc below
+ // we need to make sure they aren't suppressed in these cases.
+ return handled && !osd->options().lightgun() && !osd->options().mouse();
+}
+
+inline static BOOL handle_keypress(windows_osd_interface *osd, int vkey, int down, int scancode, BOOL extended_key)
+{
+ KeyPressEventArgs args;
+ args.event_id = down ? INPUT_EVENT_KEYDOWN : INPUT_EVENT_KEYUP;
+ args.scancode = MAKE_DI_SCAN(scancode, extended_key);
+ args.vkey = vkey;
+ return osd->handle_input_event(args.event_id, &args);
+}
//============================================================
// winwindow_process_events
@@ -478,36 +508,45 @@ void winwindow_process_events(running_machine &machine, int ingame, bool nodispa
// forward mouse button downs to the input system
case WM_LBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_RBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_MBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_XBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
// forward mouse button ups to the input system
case WM_LBUTTONUP:
- dispatch = !wininput_handle_mouse_button(0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_RBUTTONUP:
- dispatch = !wininput_handle_mouse_button(1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_MBUTTONUP:
- dispatch = !wininput_handle_mouse_button(2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_XBUTTONUP:
- dispatch = !wininput_handle_mouse_button(3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(WINOSD(machine), 3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ break;
+
+ case WM_KEYDOWN:
+ if (NOT_ALREADY_DOWN(message.lParam))
+ dispatch = !handle_keypress(WINOSD(machine), message.wParam, TRUE, SCAN_CODE(message.lParam), IS_EXTENDED(message.lParam));
+ break;
+
+ case WM_KEYUP:
+ dispatch = !handle_keypress(WINOSD(machine), message.wParam, FALSE, SCAN_CODE(message.lParam), IS_EXTENDED(message.lParam));
break;
}
}
@@ -688,7 +727,7 @@ void winwindow_update_cursor_state(running_machine &machine)
// 2. we also hide the cursor in full screen mode and when the window doesn't have a menu
// 3. we also hide the cursor in windowed mode if we're not paused and
// the input system requests it
- if (winwindow_has_focus() && ((!video_config.windowed && !win_window_list->win_has_menu()) || (!machine.paused() && wininput_should_hide_mouse())))
+ if (winwindow_has_focus() && ((!video_config.windowed && !win_window_list->win_has_menu()) || (!machine.paused() && downcast<windows_osd_interface&>(machine.osd()).should_hide_mouse())))
{
win_window_info *window = win_window_list;
RECT bounds;
@@ -1152,6 +1191,7 @@ int win_window_info::wnd_extra_height()
unsigned __stdcall win_window_info::thread_entry(void *param)
{
MSG message;
+ windows_osd_interface *osd = static_cast<windows_osd_interface*>(param);
// make a bogus user call to make us a message thread
PeekMessage(&message, nullptr, 0, 0, PM_NOREMOVE);
@@ -1179,36 +1219,36 @@ unsigned __stdcall win_window_info::thread_entry(void *param)
// forward mouse button downs to the input system
case WM_LBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 0, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_RBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 1, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_MBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 2, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_XBUTTONDOWN:
- dispatch = !wininput_handle_mouse_button(3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 3, TRUE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
// forward mouse button ups to the input system
case WM_LBUTTONUP:
- dispatch = !wininput_handle_mouse_button(0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 0, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_RBUTTONUP:
- dispatch = !wininput_handle_mouse_button(1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 1, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_MBUTTONUP:
- dispatch = !wininput_handle_mouse_button(2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 2, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
case WM_XBUTTONUP:
- dispatch = !wininput_handle_mouse_button(3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
+ dispatch = !handle_mouse_button(osd, 3, FALSE, GET_X_LPARAM(message.lParam), GET_Y_LPARAM(message.lParam));
break;
// a terminate message to the thread posts a quit
@@ -1369,7 +1409,7 @@ LRESULT CALLBACK win_window_info::video_window_proc(HWND wnd, UINT message, WPAR
// input: handle the raw input
case WM_INPUT:
- wininput_handle_raw((HRAWINPUT)lparam);
+ downcast<windows_osd_interface&>(window->machine().osd()).handle_input_event(INPUT_EVENT_RAWINPUT, &lparam);
break;
// syskeys - ignore
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index 952831f68bc..9869f3bfecf 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -238,6 +238,29 @@ private:
// TYPE DEFINITIONS
//============================================================
+enum input_event
+{
+ INPUT_EVENT_KEYDOWN,
+ INPUT_EVENT_KEYUP,
+ INPUT_EVENT_RAWINPUT,
+ INPUT_EVENT_MOUSE_BUTTON
+};
+
+struct KeyPressEventArgs
+{
+ input_event event_id;
+ UINT8 vkey;
+ UINT8 scancode;
+};
+
+struct MouseButtonEventArgs
+{
+ int button;
+ int keydown;
+ int xpos;
+ int ypos;
+};
+
class windows_osd_interface : public osd_common_t
{
public:
@@ -252,25 +275,25 @@ public:
// video overridables
virtual slider_state *get_slider_list() override;
- // input overridables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
virtual void video_register() override;
virtual bool video_init() override;
virtual bool window_init() override;
- virtual bool input_init() override;
- virtual void input_pause() override;
- virtual void input_resume() override;
virtual bool output_init() override;
virtual void video_exit() override;
virtual void window_exit() override;
- virtual void input_exit() override;
virtual void output_exit() override;
void extract_video_config();
+ // windows osd specific
+ bool handle_input_event(input_event eventid, void *eventdata);
+ bool should_hide_mouse();
+ void poll_input(running_machine &machine);
+
windows_options &options() { return m_options; }
private: