DOS: add keyboard driver to support non-joypad keys

This commit is contained in:
Brad Parker 2017-02-05 13:55:19 -05:00
parent fa341f03a0
commit 83619b25e6
7 changed files with 356 additions and 40 deletions

View File

@ -1273,7 +1273,7 @@ endif
ifneq ($(findstring DOS,$(OS)),)
OBJ += gfx/drivers/vga_gfx.o gfx/drivers_font/vga_font.o \
input/drivers/dos_input.o input/drivers_joypad/dos_joypad.o \
frontend/drivers/platform_dos.o
frontend/drivers/platform_dos.o input/drivers_keyboard/keyboard_event_dos.o
ifeq ($(HAVE_MENU_COMMON), 1)
OBJ += menu/drivers_display/menu_display_vga.o

View File

@ -14,16 +14,17 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../input_driver.h"
#include "../input_keymaps.h"
#include "../input_joypad_driver.h"
#include "../drivers_keyboard/keyboard_event_dos.h"
typedef struct dos_input
{
const input_device_driver_t *joypad;
unsigned char normal_keys[256];
unsigned char extended_keys[256];
} dos_input_t;
static void dos_input_poll(void *data)
@ -48,7 +49,10 @@ static int16_t dos_input_state(void *data,
switch (device)
{
case RETRO_DEVICE_JOYPAD:
return input_joypad_pressed(dos->joypad, joypad_info, port, binds[port], id);
return input_joypad_pressed(dos->joypad, joypad_info, port, binds[port], id) ||
dos_keyboard_port_input_pressed(binds[port], id);
case RETRO_DEVICE_KEYBOARD:
return dos_keyboard_port_input_pressed(binds[port], id);
}
return 0;
@ -61,6 +65,8 @@ static void dos_input_free_input(void *data)
if (dos && dos->joypad)
dos->joypad->destroy();
dos_keyboard_free();
if (data)
free(data);
}
@ -72,8 +78,12 @@ static void* dos_input_init(const char *joypad_driver)
if (!dos)
return NULL;
dos_keyboard_free();
dos->joypad = input_joypad_init_driver(joypad_driver, dos);
input_keymaps_init_keyboard_lut(rarch_key_map_dos);
return dos;
}
@ -87,7 +97,6 @@ static uint64_t dos_input_get_capabilities(void *data)
uint64_t caps = 0;
caps |= UINT64_C(1) << RETRO_DEVICE_JOYPAD;
caps |= UINT64_C(1) << RETRO_DEVICE_KEYBOARD;
return caps;
}

View File

@ -20,7 +20,6 @@
#include <dpmi.h>
#include <sys/segments.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@ -30,19 +29,17 @@
#include "../input_joypad_driver.h"
#include "../input_driver.h"
#include "../input_config.h"
#include "../input_keyboard.h"
#include "../input_keymaps.h"
#include "../../tasks/tasks_internal.h"
#define MAX_PADS 1
#include "../drivers_keyboard/keyboard_event_dos.h"
#define END_FUNC(x) static void x##_End() { }
#define LOCK_VAR(x) LockData((void*)&x, sizeof(x))
#define LOCK_FUNC(x) LockCode(x, (int)x##_End - (int)x)
static uint64_t dos_key_state[MAX_PADS];
static unsigned char normal_keys[256];
static unsigned char extended_keys[256];
static uint16_t normal_keys[LAST_KEYCODE + 1];
static _go32_dpmi_seginfo old_kbd_int;
static _go32_dpmi_seginfo kbd_int;
@ -85,7 +82,7 @@ int LockCode(void *a, int size)
static void keyb_int(void)
{
static unsigned char buffer;
static unsigned char buffer = 0;
unsigned char rawcode;
unsigned char make_break;
int scancode;
@ -99,14 +96,14 @@ static void keyb_int(void)
/* second byte of an extended key */
if (scancode < 0x60)
{
extended_keys[scancode] = make_break;
normal_keys[scancode | (1 << 8)] = make_break;
}
buffer = 0;
}
else if (buffer >= 0xE1 && buffer <= 0xE2)
{
buffer = 0; /* ingore these extended keys */
buffer = 0; /* ignore these extended keys */
}
else if (rawcode >= 0xE0 && rawcode <= 0xE2)
{
@ -126,10 +123,10 @@ static void hook_keyb_int(void)
_go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_int);
memset(&kbd_int, 0, sizeof(kbd_int));
memset(normal_keys, 0, sizeof(normal_keys));
LOCK_FUNC(keyb_int);
LOCK_VAR(normal_keys);
LOCK_VAR(extended_keys);
kbd_int.pm_selector = _go32_my_cs();
kbd_int.pm_offset = (uint32_t)&keyb_int;
@ -170,8 +167,6 @@ static void dos_joypad_autodetect_add(unsigned autoconf_pad)
static bool dos_joypad_init(void *data)
{
memset(dos_key_state, 0, sizeof(dos_key_state));
hook_keyb_int();
dos_joypad_autodetect_add(0);
@ -183,44 +178,64 @@ static bool dos_joypad_init(void *data)
static bool dos_joypad_button(unsigned port_num, uint16_t key)
{
uint16_t *buf = dos_keyboard_state_get(port_num);
if (port_num >= MAX_PADS)
return false;
return (dos_key_state[port_num] & (UINT64_C(1) << key));
}
switch (key)
{
case RETRO_DEVICE_ID_JOYPAD_A:
return buf[DOSKEY_x];
case RETRO_DEVICE_ID_JOYPAD_B:
return buf[DOSKEY_z];
case RETRO_DEVICE_ID_JOYPAD_X:
return buf[DOSKEY_s];
case RETRO_DEVICE_ID_JOYPAD_Y:
return buf[DOSKEY_a];
case RETRO_DEVICE_ID_JOYPAD_SELECT:
return buf[DOSKEY_RSHIFT];
case RETRO_DEVICE_ID_JOYPAD_START:
return buf[DOSKEY_RETURN];
case RETRO_DEVICE_ID_JOYPAD_UP:
return buf[DOSKEY_UP];
case RETRO_DEVICE_ID_JOYPAD_DOWN:
return buf[DOSKEY_DOWN];
case RETRO_DEVICE_ID_JOYPAD_LEFT:
return buf[DOSKEY_LEFT];
case RETRO_DEVICE_ID_JOYPAD_RIGHT:
return buf[DOSKEY_RIGHT];
}
static uint64_t dos_joypad_get_buttons(unsigned port_num)
{
if (port_num >= MAX_PADS)
return 0;
return dos_key_state[port_num];
return false;
}
static void dos_joypad_poll(void)
{
uint32_t i;
for (i = 0; i < MAX_PADS; i++)
for (i = 0; i <= MAX_PADS; i++)
{
uint64_t *cur_state = &dos_key_state[i];
uint16_t *cur_state = dos_keyboard_state_get(i);
uint32_t key;
*cur_state = 0;
*cur_state |= extended_keys[75] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT : 0;
*cur_state |= extended_keys[77] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT : 0;
*cur_state |= extended_keys[72] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP : 0;
*cur_state |= extended_keys[80] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN : 0;
*cur_state |= normal_keys[28] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START : 0; /* ENTER */
*cur_state |= normal_keys[54] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT : 0; /* RSHIFT */
*cur_state |= normal_keys[44] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B : 0; /* Z */
*cur_state |= normal_keys[45] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A : 0; /* X */
*cur_state |= normal_keys[30] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y : 0; /* A */
*cur_state |= normal_keys[31] ? UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X : 0; /* S */
for (key = 0; key < LAST_KEYCODE; key++)
{
if (cur_state[key] != normal_keys[key])
{
unsigned code = input_keymaps_translate_keysym_to_rk(key);
input_keyboard_event(normal_keys[key], code, code, 0, RETRO_DEVICE_KEYBOARD);
}
}
memcpy(cur_state, normal_keys, sizeof(normal_keys));
}
}
static bool dos_joypad_query_pad(unsigned pad)
{
return pad < MAX_USERS && dos_key_state[pad];
return (pad < MAX_USERS);
}
static int16_t dos_joypad_axis(unsigned port_num, uint32_t joyaxis)
@ -238,7 +253,7 @@ input_device_driver_t dos_joypad = {
dos_joypad_query_pad,
dos_joypad_destroy,
dos_joypad_button,
dos_joypad_get_buttons,
NULL,
dos_joypad_axis,
dos_joypad_poll,
NULL,

View File

@ -0,0 +1,56 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <retro_miscellaneous.h>
#include "keyboard_event_dos.h"
#include "../input_keymaps.h"
#define MAX_KEYS LAST_KEYCODE + 1
// First ports are used to keeping track of gamepad states. Last port is used for keyboard state
static uint16_t dos_key_state[MAX_PADS+1][MAX_KEYS];
bool dos_keyboard_port_input_pressed(const struct retro_keybind *binds, unsigned id)
{
if (id < RARCH_BIND_LIST_END)
{
const struct retro_keybind *bind = &binds[id];
unsigned key = input_keymaps_translate_rk_to_keysym(bind->key);
return dos_key_state[DOS_KEYBOARD_PORT][key];
}
return false;
}
bool dos_keyboard_input_pressed(unsigned key)
{
unsigned keysym = input_keymaps_translate_rk_to_keysym(key);
return dos_key_state[DOS_KEYBOARD_PORT][keysym];
}
uint16_t *dos_keyboard_state_get(unsigned port)
{
return dos_key_state[port];
}
void dos_keyboard_free(void)
{
unsigned i, j;
for (i = 0; i < MAX_PADS; i++)
for (j = 0; j < MAX_KEYS; j++)
dos_key_state[i][j] = 0;
}

View File

@ -0,0 +1,137 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _KEYBOARD_EVENT_DOS_H
#define _KEYBOARD_EVENT_DOS_H
#include "../input_driver.h"
/*
* Key codes.
*/
enum {
DOSKEY_ESCAPE = 0x1,
DOSKEY_F1 = 0x3b,
DOSKEY_F2 = 0x3c,
DOSKEY_F3 = 0x3d,
DOSKEY_F4 = 0x3e,
DOSKEY_F5 = 0x3f,
DOSKEY_F6 = 0x40,
DOSKEY_F7 = 0x41,
DOSKEY_F8 = 0x42,
DOSKEY_F9 = 0x43,
DOSKEY_F10 = 0x44,
DOSKEY_BACKQUOTE = 0x29,
DOSKEY_1 = 0x2,
DOSKEY_2 = 0x3,
DOSKEY_3 = 0x4,
DOSKEY_4 = 0x5,
DOSKEY_5 = 0x6,
DOSKEY_6 = 0x7,
DOSKEY_7 = 0x8,
DOSKEY_8 = 0x9,
DOSKEY_9 = 0xa,
DOSKEY_0 = 0xb,
DOSKEY_MINUS = 0xc,
DOSKEY_EQUAL = 0xd,
DOSKEY_BACKSPACE = 0xe,
DOSKEY_TAB = 0xf,
DOSKEY_q = 0x10,
DOSKEY_w = 0x11,
DOSKEY_e = 0x12,
DOSKEY_r = 0x13,
DOSKEY_t = 0x14,
DOSKEY_y = 0x15,
DOSKEY_u = 0x16,
DOSKEY_i = 0x17,
DOSKEY_o = 0x18,
DOSKEY_p = 0x19,
DOSKEY_LBRACKET = 0x1a,
DOSKEY_RBRACKET = 0x1b,
DOSKEY_BACKSLASH = 0x2b,
DOSKEY_CAPSLOCK = 0x3a,
DOSKEY_a = 0x1e,
DOSKEY_s = 0x1f,
DOSKEY_d = 0x20,
DOSKEY_f = 0x21,
DOSKEY_g = 0x22,
DOSKEY_h = 0x23,
DOSKEY_j = 0x24,
DOSKEY_k = 0x25,
DOSKEY_l = 0x26,
DOSKEY_SEMICOLON = 0x27,
DOSKEY_QUOTE = 0x28,
DOSKEY_RETURN = 0x1c,
DOSKEY_LSHIFT = 0x2a,
DOSKEY_z = 0x2c,
DOSKEY_x = 0x2d,
DOSKEY_c = 0x2e,
DOSKEY_v = 0x2f,
DOSKEY_b = 0x30,
DOSKEY_n = 0x31,
DOSKEY_m = 0x32,
DOSKEY_COMMA = 0x33,
DOSKEY_PERIOD = 0x34,
DOSKEY_SLASH = 0x35,
DOSKEY_RSHIFT = 0x36,
DOSKEY_LCTRL = 0x1d,
DOSKEY_LSUPER = 0x15b,
DOSKEY_LALT = 0x38,
DOSKEY_SPACE = 0x39,
DOSKEY_RALT = 0x138,
DOSKEY_RSUPER = 0x15c,
DOSKEY_MENU = 0x15d,
DOSKEY_RCTRL = 0x11d,
DOSKEY_UP = 0x148,
DOSKEY_DOWN = 0x150,
DOSKEY_LEFT = 0x14b,
DOSKEY_RIGHT = 0x14d,
DOSKEY_HOME = 0x147,
DOSKEY_END = 0x14f,
DOSKEY_PGUP = 0x149,
DOSKEY_PGDN = 0x151,
};
#include <stdint.h>
#include <boolean.h>
#define LAST_KEYCODE 0x1ff
#ifndef MAX_PADS
#define MAX_PADS 1
#endif
#define DOS_KEYBOARD_PORT MAX_PADS
bool dos_keyboard_port_input_pressed(const struct retro_keybind *binds, unsigned id);
bool dos_keyboard_input_pressed(unsigned key);
uint16_t *dos_keyboard_state_get(unsigned port);
void dos_keyboard_init(void);
void dos_keyboard_free(void);
#endif

View File

@ -32,6 +32,10 @@
#include "drivers_keyboard/keyboard_event_android.h"
#endif
#ifdef DJGPP
#include "drivers_keyboard/keyboard_event_dos.h"
#endif
#ifdef __QNX__
#include <sys/keycodes.h>
#endif
@ -1311,6 +1315,100 @@ const struct rarch_key_map rarch_key_map_apple_hid[] = {
};
#endif
#ifdef DJGPP
const struct rarch_key_map rarch_key_map_dos[] = {
{ DOSKEY_ESCAPE, RETROK_ESCAPE },
{ DOSKEY_F1, RETROK_F1 },
{ DOSKEY_F2, RETROK_F2 },
{ DOSKEY_F3, RETROK_F3 },
{ DOSKEY_F4, RETROK_F4 },
{ DOSKEY_F5, RETROK_F5 },
{ DOSKEY_F6, RETROK_F6 },
{ DOSKEY_F7, RETROK_F7 },
{ DOSKEY_F8, RETROK_F8 },
{ DOSKEY_F9, RETROK_F9 },
{ DOSKEY_F10, RETROK_F10 },
{ DOSKEY_BACKQUOTE, RETROK_BACKQUOTE },
{ DOSKEY_1, RETROK_1 },
{ DOSKEY_2, RETROK_2 },
{ DOSKEY_3, RETROK_3 },
{ DOSKEY_4, RETROK_4 },
{ DOSKEY_5, RETROK_5 },
{ DOSKEY_6, RETROK_6 },
{ DOSKEY_7, RETROK_7 },
{ DOSKEY_8, RETROK_8 },
{ DOSKEY_9, RETROK_9 },
{ DOSKEY_0, RETROK_0 },
{ DOSKEY_MINUS, RETROK_MINUS },
{ DOSKEY_EQUAL, RETROK_EQUALS },
{ DOSKEY_BACKSPACE, RETROK_BACKSPACE },
{ DOSKEY_TAB, RETROK_TAB },
{ DOSKEY_q, RETROK_q },
{ DOSKEY_w, RETROK_w },
{ DOSKEY_e, RETROK_e },
{ DOSKEY_r, RETROK_r },
{ DOSKEY_t, RETROK_t },
{ DOSKEY_y, RETROK_y },
{ DOSKEY_u, RETROK_u },
{ DOSKEY_i, RETROK_i },
{ DOSKEY_o, RETROK_o },
{ DOSKEY_p, RETROK_p },
{ DOSKEY_LBRACKET, RETROK_LEFTBRACKET },
{ DOSKEY_RBRACKET, RETROK_RIGHTBRACKET },
{ DOSKEY_BACKSLASH, RETROK_BACKSLASH },
{ DOSKEY_CAPSLOCK, RETROK_CAPSLOCK },
{ DOSKEY_a, RETROK_a },
{ DOSKEY_s, RETROK_s },
{ DOSKEY_d, RETROK_d },
{ DOSKEY_f, RETROK_f },
{ DOSKEY_g, RETROK_g },
{ DOSKEY_h, RETROK_h },
{ DOSKEY_j, RETROK_j },
{ DOSKEY_k, RETROK_k },
{ DOSKEY_l, RETROK_l },
{ DOSKEY_SEMICOLON, RETROK_SEMICOLON },
{ DOSKEY_QUOTE, RETROK_QUOTE },
{ DOSKEY_RETURN, RETROK_RETURN },
{ DOSKEY_LSHIFT, RETROK_LSHIFT },
{ DOSKEY_z, RETROK_z },
{ DOSKEY_x, RETROK_x },
{ DOSKEY_c, RETROK_c },
{ DOSKEY_v, RETROK_v },
{ DOSKEY_b, RETROK_b },
{ DOSKEY_n, RETROK_n },
{ DOSKEY_m, RETROK_m },
{ DOSKEY_COMMA, RETROK_COMMA },
{ DOSKEY_PERIOD, RETROK_PERIOD },
{ DOSKEY_SLASH, RETROK_SLASH },
{ DOSKEY_RSHIFT, RETROK_RSHIFT },
{ DOSKEY_LCTRL, RETROK_LCTRL },
{ DOSKEY_LSUPER, RETROK_LSUPER },
{ DOSKEY_LALT, RETROK_LALT },
{ DOSKEY_SPACE, RETROK_SPACE },
{ DOSKEY_RALT, RETROK_RALT },
{ DOSKEY_RSUPER, RETROK_RSUPER },
{ DOSKEY_MENU, RETROK_MENU },
{ DOSKEY_RCTRL, RETROK_RCTRL },
{ DOSKEY_UP, RETROK_UP },
{ DOSKEY_DOWN, RETROK_DOWN },
{ DOSKEY_LEFT, RETROK_LEFT },
{ DOSKEY_RIGHT, RETROK_RIGHT },
{ DOSKEY_HOME, RETROK_HOME },
{ DOSKEY_END, RETROK_END },
{ DOSKEY_PGUP, RETROK_PAGEUP },
{ DOSKEY_PGDN, RETROK_PAGEDOWN },
{ 0, RETROK_UNKNOWN }
};
#endif
static enum retro_key rarch_keysym_lut[RETROK_LAST];
/**

View File

@ -57,6 +57,7 @@ extern const struct rarch_key_map rarch_key_map_linux[];
extern const struct rarch_key_map rarch_key_map_apple_hid[];
extern const struct rarch_key_map rarch_key_map_android[];
extern const struct rarch_key_map rarch_key_map_qnx[];
extern const struct rarch_key_map rarch_key_map_dos[];
/**
* input_keymaps_init_keyboard_lut: