gpfce patch
[fceu.git] / drivers / cli / dos-keyboard.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 2002 Ben Parnell\r
5  *\r
6  * This program is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  */\r
20 \r
21 #include <stdio.h>\r
22 #include <signal.h>\r
23 #include <string.h>\r
24 #include <pc.h>\r
25 #include <dpmi.h>\r
26 #include <go32.h>\r
27 #include "keyscan.h"\r
28 \r
29 static unsigned char lastsc;\r
30 static char keybuf[256];\r
31 int newk;\r
32 \r
33 /* Read scan code from port $60 */\r
34 /* Acknowledge interrupt( output $20 to port $20) */\r
35 \r
36 static void ihandler(_go32_dpmi_registers *r)\r
37 {\r
38  unsigned char scode=inp(0x60); /* Get scan code. */\r
39 \r
40 \r
41  if(scode!=0xE0)\r
42  {\r
43   int offs=0;\r
44 \r
45   /* I'm only interested in preserving the independent status of the\r
46      right ALT and CONTROL keys.\r
47   */\r
48   if(lastsc==0xE0)\r
49    if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)\r
50     offs=0x80;\r
51   \r
52 \r
53   keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);\r
54   newk++;\r
55  }\r
56  lastsc=scode;\r
57 \r
58  outp(0x20,0x20);       /* Acknowledge interrupt. */\r
59 }\r
60 \r
61 static _go32_dpmi_seginfo KBIBack,KBIBackRM;\r
62 static _go32_dpmi_seginfo KBI,KBIRM;\r
63 static _go32_dpmi_registers KBIRMRegs;\r
64 static int initdone=0;\r
65 \r
66 int InitKeyboard(void)\r
67 {\r
68  /* I'll assume that the keyboard is in the correct scancode mode(translated\r
69     mode 2, I think).\r
70  */\r
71   newk=0;\r
72   memset(keybuf,0,sizeof(keybuf));\r
73   KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;\r
74   KBIRM.pm_selector=KBI.pm_selector=_my_cs();\r
75 \r
76   _go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);\r
77   _go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);\r
78   _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);\r
79 \r
80   _go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);\r
81   _go32_dpmi_allocate_iret_wrapper(&KBI);\r
82   _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);\r
83   lastsc=0;\r
84   initdone=1;\r
85   return(1);\r
86 }\r
87 \r
88 void KillKeyboard(void)\r
89 {\r
90  if(initdone)\r
91  {\r
92   _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);\r
93   _go32_dpmi_free_iret_wrapper(&KBI);\r
94 \r
95   _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);\r
96   _go32_dpmi_free_real_mode_callback(&KBIRM);\r
97   initdone=0;\r
98  }\r
99 }\r
100 \r
101 /* In FCE Ultra, it doesn't matter if the key states change\r
102    in the middle of the keyboard handling code.  If you want\r
103    to use this code elsewhere, you may want to memcpy() keybuf\r
104    to another buffer and return that when GetKeyboard() is\r
105    called.\r
106 */\r
107 \r
108 char *GetKeyboard(void)\r
109 {\r
110  return keybuf;\r
111 }\r
112 \r
113 /* Returns 1 on new scan codes generated, 0 on no new scan codes. */\r
114 int UpdateKeyboard(void)\r
115 {\r
116  int t=newk;\r
117 \r
118  if(t)\r
119  {\r
120   asm volatile(\r
121         "subl %%eax,_newk\n\t"\r
122         :\r
123         : "a" (t)\r
124   );\r
125 \r
126   if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])\r
127    raise(SIGINT);\r
128   return(1);\r
129  }\r
130  return(0);\r
131 }\r