--- /dev/null
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ * Copyright (C) 2002 Ben Parnell\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <signal.h>\r
+#include <string.h>\r
+#include <pc.h>\r
+#include <dpmi.h>\r
+#include <go32.h>\r
+#include "keyscan.h"\r
+\r
+static unsigned char lastsc;\r
+static char keybuf[256];\r
+int newk;\r
+\r
+/* Read scan code from port $60 */\r
+/* Acknowledge interrupt( output $20 to port $20) */\r
+\r
+static void ihandler(_go32_dpmi_registers *r)\r
+{\r
+ unsigned char scode=inp(0x60); /* Get scan code. */\r
+\r
+\r
+ if(scode!=0xE0)\r
+ {\r
+ int offs=0;\r
+\r
+ /* I'm only interested in preserving the independent status of the\r
+ right ALT and CONTROL keys.\r
+ */\r
+ if(lastsc==0xE0)\r
+ if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)\r
+ offs=0x80;\r
+ \r
+\r
+ keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);\r
+ newk++;\r
+ }\r
+ lastsc=scode;\r
+\r
+ outp(0x20,0x20); /* Acknowledge interrupt. */\r
+}\r
+\r
+static _go32_dpmi_seginfo KBIBack,KBIBackRM;\r
+static _go32_dpmi_seginfo KBI,KBIRM;\r
+static _go32_dpmi_registers KBIRMRegs;\r
+static int initdone=0;\r
+\r
+int InitKeyboard(void)\r
+{\r
+ /* I'll assume that the keyboard is in the correct scancode mode(translated\r
+ mode 2, I think).\r
+ */\r
+ newk=0;\r
+ memset(keybuf,0,sizeof(keybuf));\r
+ KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;\r
+ KBIRM.pm_selector=KBI.pm_selector=_my_cs();\r
+\r
+ _go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);\r
+ _go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);\r
+ _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);\r
+\r
+ _go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);\r
+ _go32_dpmi_allocate_iret_wrapper(&KBI);\r
+ _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);\r
+ lastsc=0;\r
+ initdone=1;\r
+ return(1);\r
+}\r
+\r
+void KillKeyboard(void)\r
+{\r
+ if(initdone)\r
+ {\r
+ _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);\r
+ _go32_dpmi_free_iret_wrapper(&KBI);\r
+\r
+ _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);\r
+ _go32_dpmi_free_real_mode_callback(&KBIRM);\r
+ initdone=0;\r
+ }\r
+}\r
+\r
+/* In FCE Ultra, it doesn't matter if the key states change\r
+ in the middle of the keyboard handling code. If you want\r
+ to use this code elsewhere, you may want to memcpy() keybuf\r
+ to another buffer and return that when GetKeyboard() is\r
+ called.\r
+*/\r
+\r
+char *GetKeyboard(void)\r
+{\r
+ return keybuf;\r
+}\r
+\r
+/* Returns 1 on new scan codes generated, 0 on no new scan codes. */\r
+int UpdateKeyboard(void)\r
+{\r
+ int t=newk;\r
+\r
+ if(t)\r
+ {\r
+ asm volatile(\r
+ "subl %%eax,_newk\n\t"\r
+ :\r
+ : "a" (t)\r
+ );\r
+\r
+ if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])\r
+ raise(SIGINT);\r
+ return(1);\r
+ }\r
+ return(0);\r
+}\r