1515 * If not, see <http://www.gnu.org/licenses/>.
1616 */
1717
18+ #include <pc.h>
19+ #include <dos.h>
20+ #include <go32.h>
21+ #include <dpmi.h>
22+ #include <sys/segments.h>
1823#include <stdint.h>
1924#include <stdlib.h>
2025
2631
2732#define MAX_KEYS LAST_KEYCODE + 1
2833
29- /* TODO/FIXME -
30- * fix game focus toggle */
34+ #define END_FUNC (x ) static void x##_End() { }
35+
36+ #define LOCK_VAR (x ) LockData((void*)&x, sizeof(x))
37+ #define LOCK_FUNC (x ) LockCode(x, (int)x##_End - (int)x)
38+
39+ /* TODO/FIXME - static globals */
40+ static uint16_t normal_keys [MAX_KEYS ];
41+ static _go32_dpmi_seginfo old_kbd_int ;
42+ static _go32_dpmi_seginfo kbd_int ;
43+
44+ static int LockData (void * a , int size )
45+ {
46+ uint32_t baseaddr ;
47+ if (__dpmi_get_segment_base_address (_my_ds (), & baseaddr ) != -1 )
48+ {
49+ __dpmi_meminfo region ;
50+ region .handle = 0 ;
51+ region .size = size ;
52+ region .address = baseaddr + (uint32_t )a ;
53+ if (__dpmi_lock_linear_region (& region ) != -1 )
54+ return 0 ;
55+ }
56+ return -1 ;
57+ }
58+
59+ static int LockCode (void * a , int size )
60+ {
61+ uint32_t baseaddr ;
62+ if (__dpmi_get_segment_base_address (_my_cs (), & baseaddr ) != -1 )
63+ {
64+ __dpmi_meminfo region ;
65+ region .handle = 0 ;
66+ region .size = size ;
67+ region .address = baseaddr + (uint32_t )a ;
68+ if (__dpmi_lock_linear_region (& region ) != -1 )
69+ return 0 ;
70+ }
71+ return -1 ;
72+ }
73+
74+ static void keyb_int (void )
75+ {
76+ unsigned char buffer = normal_keys [LAST_KEYCODE ];
77+ unsigned char rawcode = inp (0x60 );
78+ /* read scancode from keyboard controller */
79+ unsigned char make_break = !(rawcode & 0x80 );
80+ /* bit 7: 0 = make, 1 = break */
81+ int scancode = rawcode & 0x7F ;
82+
83+ if (buffer == 0xE0 )
84+ {
85+ /* second byte of an extended key */
86+ if (scancode < 0x60 )
87+ normal_keys [scancode | (1 << 8 )] = make_break ;
88+
89+ buffer = 0 ;
90+ }
91+ else if (buffer >= 0xE1 && buffer <= 0xE2 )
92+ buffer = 0 ; /* ignore these extended keys */
93+ else if (rawcode >= 0xE0 && rawcode <= 0xE2 )
94+ buffer = rawcode ; /* first byte of an extended key */
95+ else if (scancode < 0x60 )
96+ {
97+ normal_keys [scancode ] = make_break ;
98+ buffer = 0 ;
99+ }
100+ normal_keys [LAST_KEYCODE ] = buffer ;
101+ outp (0x20 , 0x20 ); /* must send EOI to finish interrupt */
102+ }
103+ END_FUNC (keyb_int )
31104
32- /* First ports are used to keeping track of gamepad states. Last port is used for keyboard state */
33105/* TODO/FIXME - static globals */
34- static uint16_t dos_key_state [DEFAULT_MAX_PADS + 1 ][ MAX_KEYS ];
106+ static uint16_t dos_key_state [MAX_KEYS ];
35107
36- uint16_t * dos_keyboard_state_get (unsigned port )
108+ uint16_t * dos_keyboard_state_get (void )
37109{
38- return dos_key_state [ port ] ;
110+ return dos_key_state ;
39111}
40112
41113static void dos_keyboard_free (void )
42114{
43- unsigned i , j ;
115+ unsigned j ;
44116
45- for (i = 0 ; i < DEFAULT_MAX_PADS ; i ++ )
46- for (j = 0 ; j < MAX_KEYS ; j ++ )
47- dos_key_state [i ][j ] = 0 ;
117+ for (j = 0 ; j < MAX_KEYS ; j ++ )
118+ dos_key_state [j ] = 0 ;
48119}
49120
50121static int16_t dos_input_state (
@@ -59,7 +130,7 @@ static int16_t dos_input_state(
59130 unsigned idx ,
60131 unsigned id )
61132{
62- if (port <= 0 )
133+ if (port < MAX_USERS )
63134 {
64135 switch (device )
65136 {
@@ -69,13 +140,11 @@ static int16_t dos_input_state(
69140 unsigned i ;
70141 int16_t ret = 0 ;
71142
72- for (i = 0 ; i < RARCH_FIRST_CUSTOM_BIND ; i ++ )
143+ for (i = 0 ; i < RARCH_FIRST_CUSTOM_BIND && ! keyboard_mapping_blocked ; i ++ )
73144 {
74- if (binds [port ][i ].valid )
145+ if (binds [port ][i ].valid && binds [ port ][ i ]. key && binds [ port ][ i ]. key < RETROK_LAST )
75146 {
76- if (id < RARCH_BIND_LIST_END )
77- if (dos_key_state [DOS_KEYBOARD_PORT ]
78- [rarch_keysym_lut [binds [port ][i ].key ]])
147+ if (dos_key_state [rarch_keysym_lut [(enum retro_key )binds [port ][i ].key ]])
79148 ret |= (1 << i );
80149 }
81150 }
@@ -85,44 +154,87 @@ static int16_t dos_input_state(
85154
86155 if (binds [port ][id ].valid )
87156 {
88- if (
89- (id < RARCH_BIND_LIST_END
90- && dos_key_state [DOS_KEYBOARD_PORT ]
91- [ rarch_keysym_lut [ binds [ port ][ id ]. key ]] )
157+ if ( ( binds [ port ][ id ]. key && binds [ port ][ id ]. key < RETROK_LAST )
158+ && (id < RARCH_BIND_LIST_END
159+ && dos_key_state [rarch_keysym_lut [( enum retro_key ) binds [ port ][ id ]. key ]])
160+ && ( id == RARCH_GAME_FOCUS_TOGGLE || ! keyboard_mapping_blocked )
92161 )
93162 return 1 ;
94163 }
95164 break ;
96165 case RETRO_DEVICE_KEYBOARD :
97- if (id < RARCH_BIND_LIST_END )
98- return (dos_key_state [DOS_KEYBOARD_PORT ]
99- [rarch_keysym_lut [binds [port ][id ].key ]]);
166+
167+ if (id && id < RETROK_LAST )
168+ {
169+ unsigned sym = rarch_keysym_lut [(enum retro_key )id ] & LAST_KEYCODE ;
170+ return dos_key_state [sym ];
171+ }
100172 break ;
101173 }
102174 }
103175
104176 return 0 ;
105177}
106178
179+ static void dos_input_poll (void * data )
180+ {
181+ uint32_t key ;
182+ uint16_t * cur_state = dos_keyboard_state_get ();
183+
184+ for (key = 0 ; key < LAST_KEYCODE ; key ++ )
185+ {
186+ if (cur_state [key ] != normal_keys [key ])
187+ {
188+ unsigned code = input_keymaps_translate_keysym_to_rk (key );
189+ input_keyboard_event (normal_keys [key ], code , code , 0 , RETRO_DEVICE_KEYBOARD );
190+ }
191+ }
192+ memcpy (cur_state , normal_keys , sizeof (normal_keys ));
193+ }
194+
107195static void dos_input_free_input (void * data )
108196{
109197 dos_keyboard_free ();
198+ if (old_kbd_int .pm_offset )
199+ {
200+ _go32_dpmi_set_protected_mode_interrupt_vector (9 , & old_kbd_int );
201+ _go32_dpmi_free_iret_wrapper (& kbd_int );
202+
203+ memset (& old_kbd_int , 0 , sizeof (old_kbd_int ));
204+ }
205+
110206}
111207
112208static void * dos_input_init (const char * joypad_driver )
113209{
210+ _go32_dpmi_get_protected_mode_interrupt_vector (9 , & old_kbd_int );
211+
212+ memset (& kbd_int , 0 , sizeof (kbd_int ));
213+ memset (normal_keys , 0 , sizeof (normal_keys ));
214+
215+ LOCK_FUNC (keyb_int );
216+ LOCK_VAR (normal_keys );
217+
218+ kbd_int .pm_selector = _go32_my_cs ();
219+ kbd_int .pm_offset = (uint32_t )& keyb_int ;
220+
221+ _go32_dpmi_allocate_iret_wrapper (& kbd_int );
222+
223+ _go32_dpmi_set_protected_mode_interrupt_vector (9 , & kbd_int );
224+
114225 input_keymaps_init_keyboard_lut (rarch_key_map_dos );
115226 return (void * )-1 ;
116227}
117228
118229static uint64_t dos_input_get_capabilities (void * data )
119230{
120- return UINT64_C (1 ) << RETRO_DEVICE_JOYPAD ;
231+ return (1 << RETRO_DEVICE_JOYPAD )
232+ | (1 << RETRO_DEVICE_KEYBOARD );
121233}
122234
123235input_driver_t input_dos = {
124236 dos_input_init ,
125- NULL , /* poll */
237+ dos_input_poll ,
126238 dos_input_state ,
127239 dos_input_free_input ,
128240 NULL ,
0 commit comments