Rev 56 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
56 | pj | 1 | /* |
2 | * PC/HW routine collection v1.1 for DOS/DJGPP |
||
3 | * |
||
4 | * Copyright (C) 2002 - Borca Daniel |
||
5 | * Email : dborca@yahoo.com |
||
6 | * Web : http://www.geocities.com/dborca |
||
7 | */ |
||
8 | |||
9 | |||
10 | #include <pc.h> |
||
11 | #include <sys/exceptn.h> |
||
12 | #include <sys/farptr.h> |
||
13 | |||
14 | #include "pc_hw.h" |
||
15 | |||
16 | |||
17 | |||
18 | #define KEYB_IRQ 1 |
||
19 | |||
20 | #define KEY_BUFFER_SIZE 64 |
||
21 | |||
22 | #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG) |
||
23 | #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG) |
||
24 | |||
25 | static int keyboard_installed; |
||
26 | |||
27 | static volatile struct { |
||
28 | volatile int start, end; |
||
29 | volatile int key[KEY_BUFFER_SIZE]; |
||
30 | } key_buffer; |
||
31 | |||
32 | static volatile int key_enhanced, key_pause_loop, key_shifts; |
||
33 | static int leds_ok = TRUE; |
||
34 | static int in_a_terrupt = FALSE; |
||
35 | static volatile char pc_key[KEY_MAX]; |
||
36 | |||
37 | |||
38 | |||
39 | /* convert Allegro format scancodes into key_shifts flag bits */ |
||
40 | static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = |
||
41 | { |
||
42 | KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG, |
||
43 | KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG, |
||
44 | KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG, |
||
45 | KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG |
||
46 | }; |
||
47 | |||
48 | |||
49 | |||
50 | /* lookup table for converting hardware scancodes into Allegro format */ |
||
51 | static unsigned char hw_to_mycode[128] = |
||
52 | { |
||
53 | /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, |
||
54 | /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, |
||
55 | /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, |
||
56 | /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, |
||
57 | /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R, |
||
58 | /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I, |
||
59 | /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, |
||
60 | /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S, |
||
61 | /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, |
||
62 | /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, |
||
63 | /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH, |
||
64 | /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, |
||
65 | /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, |
||
66 | /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK, |
||
67 | /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, |
||
68 | /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, |
||
69 | /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, |
||
70 | /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD, |
||
71 | /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD, |
||
72 | /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD, |
||
73 | /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD, |
||
74 | /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, |
||
75 | /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, |
||
76 | /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, |
||
77 | /* 0x60 */ 0, 0, 0, 0, |
||
78 | /* 0x64 */ 0, 0, 0, 0, |
||
79 | /* 0x68 */ 0, 0, 0, 0, |
||
80 | /* 0x6C */ 0, 0, 0, 0, |
||
81 | /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1, |
||
82 | /* 0x74 */ 0, 0, 0, 0, |
||
83 | /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT, |
||
84 | /* 0x7C */ 0, KEY_YEN, 0, 0 |
||
85 | }; |
||
86 | |||
87 | |||
88 | |||
89 | /* lookup table for converting extended hardware codes into Allegro format */ |
||
90 | static unsigned char hw_to_mycode_ex[128] = |
||
91 | { |
||
92 | /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2, |
||
93 | /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6, |
||
94 | /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0, |
||
95 | /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, |
||
96 | /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R, |
||
97 | /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I, |
||
98 | /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE, |
||
99 | /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S, |
||
100 | /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H, |
||
101 | /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON, |
||
102 | /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH, |
||
103 | /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V, |
||
104 | /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA, |
||
105 | /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR, |
||
106 | /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, |
||
107 | /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5, |
||
108 | /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9, |
||
109 | /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME, |
||
110 | /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT, |
||
111 | /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END, |
||
112 | /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL, |
||
113 | /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11, |
||
114 | /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN, |
||
115 | /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0, |
||
116 | /* 0x60 */ 0, 0, 0, 0, |
||
117 | /* 0x64 */ 0, 0, 0, 0, |
||
118 | /* 0x68 */ 0, 0, 0, 0, |
||
119 | /* 0x6C */ 0, 0, 0, 0, |
||
120 | /* 0x70 */ 0, 0, 0, 0, |
||
121 | /* 0x74 */ 0, 0, 0, 0, |
||
122 | /* 0x78 */ 0, 0, 0, 0, |
||
123 | /* 0x7C */ 0, 0, 0, 0 |
||
124 | }; |
||
125 | |||
126 | |||
127 | |||
128 | /* default mapping table for the US keyboard layout */ |
||
129 | static unsigned short standard_key_ascii_table[KEY_MAX] = |
||
130 | { |
||
131 | /* start */ 0, |
||
132 | /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
||
133 | /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
134 | /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
135 | /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
136 | /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', |
||
137 | /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
138 | /* numpad */ '/', '*', '-', '+', '.', 13, |
||
139 | /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
||
140 | }; |
||
141 | |||
142 | |||
143 | |||
144 | /* capslock mapping table for the US keyboard layout */ |
||
145 | static unsigned short standard_key_capslock_table[KEY_MAX] = |
||
146 | { |
||
147 | /* start */ 0, |
||
148 | /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
149 | /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
150 | /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
151 | /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
152 | /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ', |
||
153 | /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
154 | /* numpad */ '/', '*', '-', '+', '.', 13, |
||
155 | /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
||
156 | }; |
||
157 | |||
158 | |||
159 | |||
160 | /* shifted mapping table for the US keyboard layout */ |
||
161 | static unsigned short standard_key_shift_table[KEY_MAX] = |
||
162 | { |
||
163 | /* start */ 0, |
||
164 | /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
165 | /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', |
||
166 | /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
167 | /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
168 | /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ', |
||
169 | /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
170 | /* numpad */ '/', '*', '-', '+', '.', 13, |
||
171 | /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
||
172 | }; |
||
173 | |||
174 | |||
175 | |||
176 | /* ctrl+key mapping table for the US keyboard layout */ |
||
177 | static unsigned short standard_key_control_table[KEY_MAX] = |
||
178 | { |
||
179 | /* start */ 0, |
||
180 | /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, |
||
181 | /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
||
182 | /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', |
||
183 | /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
184 | /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, |
||
185 | /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
||
186 | /* numpad */ 2, 2, 2, 2, 2, 10, |
||
187 | /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
||
188 | }; |
||
189 | |||
190 | |||
191 | |||
192 | /* convert numeric pad scancodes into arrow codes */ |
||
193 | static unsigned char numlock_table[10] = |
||
194 | { |
||
195 | KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT, |
||
196 | KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP |
||
197 | }; |
||
198 | |||
199 | |||
200 | |||
201 | /* kb_wait_for_write_ready: |
||
202 | * Wait for the keyboard controller to set the ready-for-write bit. |
||
203 | */ |
||
204 | static __inline int kb_wait_for_write_ready (void) |
||
205 | { |
||
206 | int timeout = 4096; |
||
207 | |||
208 | while ((timeout>0) && (inportb(0x64)&2)) timeout--; |
||
209 | |||
210 | return (timeout>0); |
||
211 | } |
||
212 | |||
213 | |||
214 | |||
215 | /* kb_wait_for_read_ready: |
||
216 | * Wait for the keyboard controller to set the ready-for-read bit. |
||
217 | */ |
||
218 | static __inline int kb_wait_for_read_ready (void) |
||
219 | { |
||
220 | int timeout = 16384; |
||
221 | |||
222 | while ((timeout>0) && (!(inportb(0x64)&1))) timeout--; |
||
223 | |||
224 | return (timeout>0); |
||
225 | } |
||
226 | |||
227 | |||
228 | |||
229 | /* kb_send_data: |
||
230 | * Sends a byte to the keyboard controller. Returns 1 if all OK. |
||
231 | */ |
||
232 | static __inline int kb_send_data (unsigned char data) |
||
233 | { |
||
234 | int resends = 4; |
||
235 | int timeout, temp; |
||
236 | |||
237 | do { |
||
238 | if (!kb_wait_for_write_ready()) |
||
239 | return 0; |
||
240 | |||
241 | outportb(0x60, data); |
||
242 | timeout = 4096; |
||
243 | |||
244 | while (--timeout>0) { |
||
245 | if (!kb_wait_for_read_ready()) |
||
246 | return 0; |
||
247 | |||
248 | temp = inportb(0x60); |
||
249 | |||
250 | if (temp == 0xFA) |
||
251 | return 1; |
||
252 | |||
253 | if (temp == 0xFE) |
||
254 | break; |
||
255 | } |
||
256 | } while ((resends-- > 0) && (timeout > 0)); |
||
257 | |||
258 | return 0; |
||
259 | } |
||
260 | |||
261 | |||
262 | |||
263 | static void update_leds (int leds) |
||
264 | { |
||
265 | if (leds_ok) { |
||
266 | if (!in_a_terrupt) |
||
267 | DISABLE(); |
||
268 | |||
269 | if (!kb_send_data(0xED)) { |
||
270 | kb_send_data(0xF4); |
||
271 | leds_ok = FALSE; |
||
272 | } else if (!kb_send_data((leds>>8)&7)) { |
||
273 | kb_send_data(0xF4); |
||
274 | leds_ok = FALSE; |
||
275 | } |
||
276 | |||
277 | if (!in_a_terrupt) |
||
278 | ENABLE(); |
||
279 | } |
||
280 | } ENDOFUNC(update_leds) |
||
281 | |||
282 | |||
283 | |||
284 | static void inject_key (int scancode) |
||
285 | { |
||
286 | unsigned short *table; |
||
287 | |||
288 | if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) { |
||
289 | if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) { |
||
290 | scancode = numlock_table[scancode - KEY_0_PAD]; |
||
291 | } |
||
292 | table = standard_key_ascii_table; |
||
293 | } else if (key_shifts & KB_CTRL_FLAG) { |
||
294 | table = standard_key_control_table; |
||
295 | } else if (key_shifts & KB_SHIFT_FLAG) { |
||
296 | if (key_shifts & KB_CAPSLOCK_FLAG) { |
||
297 | if (standard_key_ascii_table[scancode]==standard_key_capslock_table[scancode]) { |
||
298 | table = standard_key_shift_table; |
||
299 | } else { |
||
300 | table = standard_key_ascii_table; |
||
301 | } |
||
302 | } else { |
||
303 | table = standard_key_shift_table; |
||
304 | } |
||
305 | } else if (key_shifts & KB_CAPSLOCK_FLAG) { |
||
306 | table = standard_key_capslock_table; |
||
307 | } else { |
||
308 | table = standard_key_ascii_table; |
||
309 | } |
||
310 | |||
311 | key_buffer.key[key_buffer.end++] = (scancode<<16)|table[scancode]; |
||
312 | |||
313 | if (key_buffer.end>=KEY_BUFFER_SIZE) |
||
314 | key_buffer.end = 0; |
||
315 | if (key_buffer.end==key_buffer.start) { |
||
316 | key_buffer.start++; |
||
317 | if (key_buffer.start>=KEY_BUFFER_SIZE) |
||
318 | key_buffer.start = 0; |
||
319 | } |
||
320 | } ENDOFUNC(inject_key) |
||
321 | |||
322 | static void handle_code (int scancode, int keycode) |
||
323 | { |
||
324 | in_a_terrupt++; |
||
325 | |||
326 | if (keycode==0) { /* pause */ |
||
327 | inject_key(scancode); |
||
328 | pc_key[KEY_PAUSE] ^= TRUE; |
||
329 | } else if (scancode) { |
||
330 | int flag; |
||
331 | |||
332 | if (scancode>=KEY_MODIFIERS) { |
||
333 | flag = modifier_table[scancode - KEY_MODIFIERS]; |
||
334 | } else { |
||
335 | flag = 0; |
||
336 | } |
||
337 | if ((char)keycode<0) { /* release */ |
||
338 | pc_key[scancode] = FALSE; |
||
339 | if (flag&KB_MODIFIERS) { |
||
340 | key_shifts &= ~flag; |
||
341 | } |
||
342 | } else { /* keypress */ |
||
343 | pc_key[scancode] = TRUE; |
||
344 | if (flag&KB_MODIFIERS) { |
||
345 | key_shifts |= flag; |
||
346 | } |
||
347 | if (flag&KB_LED_FLAGS) { |
||
348 | key_shifts ^= flag; |
||
349 | update_leds(key_shifts); |
||
350 | } |
||
351 | if (scancode<KEY_MODIFIERS) { |
||
352 | inject_key(scancode); |
||
353 | } |
||
354 | } |
||
355 | } |
||
356 | |||
357 | in_a_terrupt--; |
||
358 | } ENDOFUNC(handle_code) |
||
359 | |||
360 | static __inline void satisfy (void) |
||
361 | { |
||
362 | __asm("\n\ |
||
363 | inb $0x61, %%al \n\ |
||
364 | movb %%al, %%ah \n\ |
||
365 | orb $0x80, %%al \n\ |
||
366 | outb %%al, $0x61 \n\ |
||
367 | xchgb %%al, %%ah \n\ |
||
368 | outb %%al, $0x61 \n\ |
||
369 | movb $0x20, %%al \n\ |
||
370 | outb %%al, $0x20 \n\ |
||
371 | ":::"%eax"); |
||
372 | } |
||
373 | |||
374 | static int keyboard () |
||
375 | { |
||
376 | unsigned char temp, scancode; |
||
377 | |||
378 | temp = inportb(0x60); |
||
379 | |||
380 | if (temp<=0xe1) { |
||
381 | if (key_pause_loop) { |
||
382 | if (!--key_pause_loop) handle_code(KEY_PAUSE, 0); |
||
383 | } else |
||
384 | switch (temp) { |
||
385 | case 0xe0: |
||
386 | key_enhanced = TRUE; |
||
387 | break; |
||
388 | case 0xe1: |
||
389 | key_pause_loop = 5; |
||
390 | break; |
||
391 | default: |
||
392 | if (key_enhanced) { |
||
393 | key_enhanced = FALSE; |
||
394 | scancode = hw_to_mycode_ex[temp&0x7f]; |
||
395 | } else { |
||
396 | scancode = hw_to_mycode[temp&0x7f]; |
||
397 | } |
||
398 | handle_code(scancode, temp); |
||
399 | } |
||
400 | } |
||
401 | |||
402 | if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) { |
||
403 | /* Hack alert: |
||
404 | only SIGINT (but not Ctrl-Break) |
||
405 | calls the destructors and will safely clean up |
||
406 | */ |
||
407 | __asm("\n\ |
||
408 | movb $0x79, %%al \n\ |
||
409 | call ___djgpp_hw_exception \n\ |
||
410 | ":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); |
||
411 | } |
||
412 | |||
413 | satisfy(); |
||
414 | return 0; |
||
415 | } ENDOFUNC(keyboard) |
||
416 | |||
417 | |||
418 | int pc_keypressed (void) |
||
419 | { |
||
420 | return (key_buffer.start!=key_buffer.end); |
||
421 | } |
||
422 | |||
423 | int pc_readkey (void) |
||
424 | { |
||
425 | if (keyboard_installed) { |
||
426 | int key; |
||
427 | |||
428 | do { |
||
429 | } while (key_buffer.start==key_buffer.end); |
||
430 | |||
431 | DISABLE(); |
||
432 | key = key_buffer.key[key_buffer.start++]; |
||
433 | if (key_buffer.start>=KEY_BUFFER_SIZE) |
||
434 | key_buffer.start = 0; |
||
435 | ENABLE(); |
||
436 | |||
437 | return key; |
||
438 | } else { |
||
439 | return 0; |
||
440 | } |
||
441 | } |
||
442 | |||
443 | int pc_keydown (int code) |
||
444 | { |
||
445 | return pc_key[code]; |
||
446 | } |
||
447 | |||
448 | void pc_remove_keyb (void) |
||
449 | { |
||
450 | if (keyboard_installed) { |
||
451 | int s1, s2, s3; |
||
452 | |||
453 | keyboard_installed = FALSE; |
||
454 | pc_clexit(pc_remove_keyb); |
||
455 | |||
456 | DISABLE(); |
||
457 | _farsetsel(__djgpp_dos_sel); |
||
458 | _farnspokew(0x41c, _farnspeekw(0x41a)); |
||
459 | |||
460 | s1 = _farnspeekb(0x417) & 0x80; |
||
461 | s2 = _farnspeekb(0x418) & 0xFC; |
||
462 | s3 = _farnspeekb(0x496) & 0xF3; |
||
463 | |||
464 | if (pc_key[KEY_RSHIFT]) { s1 |= 1; } |
||
465 | if (pc_key[KEY_LSHIFT]) { s1 |= 2; } |
||
466 | if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; } |
||
467 | if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; } |
||
468 | if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; } |
||
469 | if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; } |
||
470 | |||
471 | if (key_shifts&KB_SCROLOCK_FLAG) s1 |= 16; |
||
472 | if (key_shifts&KB_NUMLOCK_FLAG) s1 |= 32; |
||
473 | if (key_shifts&KB_CAPSLOCK_FLAG) s1 |= 64; |
||
474 | |||
475 | _farnspokeb(0x417, s1); |
||
476 | _farnspokeb(0x418, s2); |
||
477 | _farnspokeb(0x496, s3); |
||
478 | update_leds(key_shifts); |
||
479 | |||
480 | ENABLE(); |
||
481 | pc_remove_irq(KEYB_IRQ); |
||
482 | } |
||
483 | } |
||
484 | |||
485 | int pc_install_keyb (void) |
||
486 | { |
||
487 | if (keyboard_installed||pc_install_irq(KEYB_IRQ, keyboard)) { |
||
488 | return -1; |
||
489 | } else { |
||
490 | int s1, s2, s3; |
||
491 | |||
492 | LOCKDATA(key_buffer); |
||
493 | LOCKDATA(key_enhanced); |
||
494 | LOCKDATA(key_pause_loop); |
||
495 | LOCKDATA(key_shifts); |
||
496 | LOCKDATA(leds_ok); |
||
497 | LOCKDATA(in_a_terrupt); |
||
498 | LOCKDATA(pc_key); |
||
499 | LOCKDATA(modifier_table); |
||
500 | LOCKDATA(hw_to_mycode); |
||
501 | LOCKDATA(hw_to_mycode_ex); |
||
502 | LOCKDATA(standard_key_ascii_table); |
||
503 | LOCKDATA(standard_key_capslock_table); |
||
504 | LOCKDATA(standard_key_shift_table); |
||
505 | LOCKDATA(standard_key_control_table); |
||
506 | LOCKDATA(numlock_table); |
||
507 | LOCKFUNC(update_leds); |
||
508 | LOCKFUNC(inject_key); |
||
509 | LOCKFUNC(handle_code); |
||
510 | LOCKFUNC(keyboard); |
||
511 | |||
512 | DISABLE(); |
||
513 | _farsetsel(__djgpp_dos_sel); |
||
514 | _farnspokew(0x41c, _farnspeekw(0x41a)); |
||
515 | |||
516 | key_shifts = 0; |
||
517 | s1 = _farnspeekb(0x417); |
||
518 | s2 = _farnspeekb(0x418); |
||
519 | s3 = _farnspeekb(0x496); |
||
520 | |||
521 | if (s1&1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; } |
||
522 | if (s1&2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; } |
||
523 | if (s2&1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; } |
||
524 | if (s2&2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; } |
||
525 | if (s3&4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; } |
||
526 | if (s3&8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; } |
||
527 | |||
528 | if (s1&16) key_shifts |= KB_SCROLOCK_FLAG; |
||
529 | if (s1&32) key_shifts |= KB_NUMLOCK_FLAG; |
||
530 | if (s1&64) key_shifts |= KB_CAPSLOCK_FLAG; |
||
531 | update_leds(key_shifts); |
||
532 | |||
533 | key_enhanced = key_pause_loop = 0; |
||
534 | key_buffer.start = key_buffer.end = 0; |
||
535 | ENABLE(); |
||
536 | |||
537 | pc_atexit(pc_remove_keyb); |
||
538 | keyboard_installed = TRUE; |
||
539 | return 0; |
||
540 | } |
||
541 | } |