diff --git a/src/hardware/keyboard.cpp b/src/hardware/keyboard.cpp index 4d0c8927..0e919b55 100644 --- a/src/hardware/keyboard.cpp +++ b/src/hardware/keyboard.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: keyboard.cpp,v 1.22 2004-04-03 19:35:34 harekiet Exp $ */ +/* $Id: keyboard.cpp,v 1.23 2004-04-07 09:36:59 qbix79 Exp $ */ #include #include "dosbox.h" @@ -83,6 +83,7 @@ void KEYBOARD_ClrBuffer(void) { keyb.scheduled=false; PIC_DeActivateIRQ(1); keyb.key_on_60=false; +/* maybe remove PIC_EVENTS */ } /* Read an entry from the keycode buffer */ @@ -122,7 +123,7 @@ void KEYBOARD_AddCode(Bit8u scancode,Bit8u ascii,Bitu mod,KeyStates state) { PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } } - +/* Disabled as it's not used anymore. Left in here incase new code fails void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { keyb.key_on_60=false; //else no new keys get scheduled :) switch (keyb.buf.state) { @@ -146,6 +147,7 @@ void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { break; } } +*/ static Bitu read_p60(Bitu port,Bitu iolen) { keyb.key_on_60 = false; @@ -247,6 +249,7 @@ static void write_p64(Bitu port,Bitu val,Bitu iolen) { keyb.active=false; PIC_DeActivateIRQ(1); PIC_RemoveEvents(KEYBOARD_GetCode); + keyb.scheduled=false; LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated"); break; case 0xd0: /* Outport on buffer */ diff --git a/src/ints/bios_keyboard.cpp b/src/ints/bios_keyboard.cpp index 09aa5cd1..4b52b6e5 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.cpp @@ -27,7 +27,6 @@ static Bitu call_int16,call_irq1; - /* Nice table from BOCHS i should feel bad for ripping this */ #define none 0 #define MAX_SCAN_CODE 0x53 @@ -108,18 +107,18 @@ static struct { { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* F10 */ { none, none, none, none }, /* Num Lock */ { none, none, none, none }, /* Scroll Lock */ - { 0x4700, 0x4737, 0x7700, none }, /* 7 Home */ - { 0x4800, 0x4838, none, none }, /* 8 UP */ - { 0x4900, 0x4939, 0x8400, none }, /* 9 PgUp */ + { 0x4700, 0x4737, 0x7700, 0x0007 }, /* 7 Home */ + { 0x4800, 0x4838, none, 0x0008 }, /* 8 UP */ + { 0x4900, 0x4939, 0x8400, 0x0009 }, /* 9 PgUp */ { 0x4a2d, 0x4a2d, none, none }, /* - */ - { 0x4b00, 0x4b34, 0x7300, none }, /* 4 Left */ - { 0x4c00, 0x4c35, none, none }, /* 5 */ - { 0x4d00, 0x4d36, 0x7400, none }, /* 6 Right */ + { 0x4b00, 0x4b34, 0x7300, 0x0004 }, /* 4 Left */ + { 0x4c00, 0x4c35, none, 0x0005 }, /* 5 */ + { 0x4d00, 0x4d36, 0x7400, 0x0006 }, /* 6 Right */ { 0x4e2b, 0x4e2b, none, none }, /* + */ - { 0x4f00, 0x4f31, 0x7500, none }, /* 1 End */ - { 0x5000, 0x5032, none, none }, /* 2 Down */ - { 0x5100, 0x5133, 0x7600, none }, /* 3 PgDn */ - { 0x5200, 0x5230, none, none }, /* 0 Ins */ + { 0x4f00, 0x4f31, 0x7500, 0x0001 }, /* 1 End */ + { 0x5000, 0x5032, none, 0x0002 }, /* 2 Down */ + { 0x5100, 0x5133, 0x7600, 0x0003 }, /* 3 PgDn */ + { 0x5200, 0x5230, none, 0x0000 }, /* 0 Ins */ { 0x5300, 0x532e, none, none } /* Del */ }; @@ -143,7 +142,7 @@ static void add_key(Bit16u code) { static Bit16u get_key(void) { Bit16u start,end,head,tail,thead; start=mem_readw(BIOS_KEYBOARD_BUFFER_START); - end =mem_readw(BIOS_KEYBOARD_BUFFER_END); + end =mem_readw(BIOS_KEYBOARD_BUFFER_END); head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); @@ -162,7 +161,6 @@ static Bit16u check_key(void) { return real_readw(0x40,head); } - /* Flag Byte 1 bit 7 =1 INSert active bit 6 =1 Caps Lock active @@ -196,107 +194,180 @@ static Bit16u check_key(void) { */ + static Bitu IRQ1_Handler(void) { +/* handling of the locks key is difficult as sdl only gives states for + * numlock capslock. + */ +/* in reg_al is the scancode */ + /* Read the code */ - Bitu scancode,ascii,mod; -#if 0 - scancode=IO_Read(0x60); - ascii=0; - mod=0; + Bitu scancode; //,ascii,mod; +#if 1 + scancode=reg_al; //IO_Read(0x60); moved out of handler +// ascii=0; +// mod=0; #else + /* Old code capable of unicode keys. Dropped Readkey disabled in keyboard.cpp */ KEYBOARD_ReadKey(scancode,ascii,mod); -// LOG(0,"Got code %X ascii %C mod %X",scancode,ascii,mod); + LOG_MSG("Got code %X ascii %C mod %X",scancode,ascii,mod); #endif Bit16u old_ax=reg_ax; reg_flags|=1; reg_ah=0x4f;reg_al=scancode; CALLBACK_RunRealInt(0x15); - reg_ax=old_ax;Bit8u flags1,flags2,flags3; + reg_ax=old_ax;Bit8u flags1,flags2,flags3,leds; if (!(reg_flags&1)) goto irq1_return; //TODO maybe implement the int 0x15 ah=4f scancode lookup hook flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); + leds =mem_readb(BIOS_KEYBOARD_LEDS); + flags2&=~(0x40+0x20);//remove numlock/capslock pressed (hack for sdl only reporting states) switch (scancode) { /* First the hard ones */ - case 0xe0: /* Extended key */ - flags3|=2; + case 0xfa: /* ack. Do nothing for now */ break; - case 29: /* Ctrl Pressed */ - flags1|=4; - if (flags3 & 2) flags3|=4; - else flags2|=1; + case 0xe1: /* Extended key special. Only pause uses this */ + LOG(LOG_KEYBOARD,LOG_ERROR)("someone is putting the pause key in the keyboard buffer"); break; - case 157: /* Ctrl Released */ - flags1&=~4; - if (flags3 & 2) flags3&=~4; - else flags2&=~1; + case 0xe0: /* Extended key */ + flags3 |=0x02; break; - case 42: /* Left Shift Pressed */ - flags1|=2; + case 0x1d: /* Ctrl Pressed */ + flags1 |=0x04; + if (flags3 &0x02) flags3 |=0x04; + else flags2 |=0x01; break; - case 170: /* Left Shift Released */ - flags1&=~2; + case 0x9d: /* Ctrl Released */ + if (flags3 &0x02) flags3 &=~0x04; + else flags2 &=~0x01; + if( !( (flags3 &0x04) || (flags2 &0x01) ) ) flags1 &=~0x04; break; - case 54: /* Right Shift Pressed */ - flags1|=1; + case 0x2a: /* Left Shift Pressed */ + flags1 |=0x02; break; - case 182: /* Right Shift Released */ - flags1&=~1; + case 0xaa: /* Left Shift Released */ + flags1 &=~0x02; break; - case 56: /* Alt Pressed */ - flags1|=8; - if (flags3 & 2) flags3|=8; - else flags2|=2; + case 0x36: /* Right Shift Pressed */ + flags1 |=0x01; break; - case 184: /* Alt Released */ - flags1&=~8; - if (flags3 & 2) flags3&=~8; - else flags2&=~2; + case 0xb6: /* Right Shift Released */ + flags1 &=~0x01; + break; + case 0x38: /* Alt Pressed */ + flags1 |=0x08; + if (flags3 &0x02) flags3 |=0x08; + else flags2 |=0x02; + break; + case 0xb8: /* Alt Released */ + if (flags3 &0x02) flags3 &= ~0x08; + else flags2 &= ~0x02; + if( !( (flags3 &0x08) || (flags2 &0x02) ) ) { /* Both alt released */ + flags1 &= ~0x08; + Bit16u token =mem_readb(BIOS_KEYBOARD_TOKEN); + if(token != 0){ + add_key(token); + mem_writeb(BIOS_KEYBOARD_TOKEN,0); + } + } break; -#if 0 - case 58:p_capslock=true;break; /* Caps Lock */ - case 186:p_capslock=false;break; - case 69:p_numlock=true;break; /* Num Lock */ - case 197:p_numlock=false;break; - case 70:p_scrolllock=true;break; /* Scroll Lock */ - case 198:p_scrolllock=false;break; - case 82:p_insert=true;break; /* Insert */ - case 210:p_insert=false;a_insert=!a_insert;break; -#endif - default: /* Normal Key */ + + case 0x3a:flags2 |=0x40;flags1 |=0x40;leds |=0x04;break; //SDL gives only the state instead of the toggle /* Caps Lock */ + case 0xba:flags1 &=~0x40;leds &=~0x04;break; + case 0x45:flags2 |=0x20;flags1 |=0x20;leds |=0x02;break; /* Num Lock */ + case 0xc5:flags1 &=~0x20;leds &=~0x02;break; + case 0x46:flags2 |=0x10;break; /* Scroll Lock SDL Seems to do this one fine (so break and make codes) */ + case 0xc6:flags1 ^=0x10;flags2 &=~0x10;leds ^=0x01;break; +// case 0x52:flags2|=128;break;//See numpad /* Insert */ + case 0xd2: + if(flags3&0x02) { + flags1^=0x80; + flags2&=~0x80; + break; + } else { + goto irq1_end;/*Normal release*/ + } + case 0x47: /* Numpad */ + case 0x48: + case 0x49: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4f: + case 0x50: + case 0x51: + case 0x52: + if(flags3 &0x02) { /*extend key. e.g key above arrows or arrows*/ + if(scancode == 0x52) { /* press insert */ + flags2 |=0x80; + break; + } + add_key((scancode <<8)|0xe0); + break; + } + if(flags1 &0x08) { + Bit8u token = mem_readb(BIOS_KEYBOARD_TOKEN); + token= token*10 + scan_to_scanascii[scancode].alt; + mem_writeb(BIOS_KEYBOARD_TOKEN,token); + } else if( ((flags1 &0x3)!=0) ^ ((flags1 &0x20) !=0) ) { + add_key(scan_to_scanascii[scancode].shift); + } else if (flags1 &0x04) { + add_key(scan_to_scanascii[scancode].control); + } else add_key(scan_to_scanascii[scancode].normal); + break; + + default: /* Normal Key */ Bit16u asciiscan; /* Now Handle the releasing of keys and see if they match up for a code */ - flags3&=~2; //Reset 0xE0 Flag /* Handle the actual scancode */ if (scancode & 0x80) goto irq1_end; if (scancode > MAX_SCAN_CODE) goto irq1_end; - if (mod & KBD_MOD_ALT) { /* Alt is being pressed */ + if (flags1 & 0x08) { /* Alt is being pressed */ asciiscan=scan_to_scanascii[scancode].alt; +#if 0 /* old unicode support disabled*/ } else if (ascii) { asciiscan=(scancode << 8) | ascii; - } else if (mod & KBD_MOD_CTRL) { /* Ctrl is being pressed */ +#endif + } else if (flags1 & 0x04) { /* Ctrl is being pressed */ asciiscan=scan_to_scanascii[scancode].control; - } else if (mod & KBD_MOD_SHIFT) { /* Either shift is being pressed */ + } else if (flags1 & 0x03) { /* Either shift is being pressed */ asciiscan=scan_to_scanascii[scancode].shift; } else { asciiscan=scan_to_scanascii[scancode].normal; } + /* cancel shift is letter and capslock active */ + if(flags1&64) { + if(flags1&3) { + /*cancel shift */ + if(((asciiscan&0x00ff) >0x40) && ((asciiscan&0x00ff) <0x5b)) + asciiscan=scan_to_scanascii[scancode].normal; + } else { + /* add shift */ + if(((asciiscan&0x00ff) >0x60) && ((asciiscan&0x00ff) <0x7b)) + asciiscan=scan_to_scanascii[scancode].shift; + } + } add_key(asciiscan); + break; }; irq1_end: + if(scancode !=0xe0) flags3 &=~0x02; //Reset 0xE0 Flag mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); + mem_writeb(BIOS_KEYBOARD_LEDS,leds); irq1_return: - IO_Write(0x20,0x20); +/* IO_Write(0x20,0x20); moved out of handler to be virtualizable */ #if 0 - /* Signal the keyboard for next code */ +/* Signal the keyboard for next code */ +/* In dosbox port 60 reads do this as well */ Bit8u old61=IO_Read(0x61); IO_Write(0x61,old61 | 128); - IO_Write(0x61,old61 & 127); + IO_Write(0x64,0xae); #endif return CBRET_NONE; } @@ -313,6 +384,7 @@ static Bitu INT16_Handler(void) { if (temp==0) { CALLBACK_Idle();}; } while (temp==0); reg_ax=temp; + if(reg_al==0xe0) reg_al=0; //extended key break; } case 0x01: /* CHECK FOR KEYSTROKE */ @@ -323,13 +395,14 @@ static Bitu INT16_Handler(void) { } else { CALLBACK_SZF(false); reg_ax=temp; + if(reg_al==0xe0) reg_al=0; //extended key } break; case 0x02: /* GET SHIFT FlAGS */ reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); break; case 0x03: /* SET TYPEMATIC RATE AND DELAY */ - LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled Typematic Rate Call %2X",reg_al); + LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled Typematic Rate Call %2X BX=%X",reg_al,reg_bx); break; case 0x05: /* STORE KEYSTROKE IN KEYBOARD BUFFER */ //TODO make add_key bool :) @@ -362,6 +435,8 @@ static void InitBiosSegment(void) { mem_writeb(BIOS_KEYBOARD_FLAGS1,0); mem_writeb(BIOS_KEYBOARD_FLAGS2,0); mem_writeb(BIOS_KEYBOARD_FLAGS3,16); /* Enhanced keyboard installed */ + mem_writeb(BIOS_KEYBOARD_TOKEN,0); + mem_writeb(BIOS_KEYBOARD_LEDS,16); } void BIOS_SetupKeyboard(void) { @@ -370,9 +445,23 @@ void BIOS_SetupKeyboard(void) { /* Allocate a callback for int 0x16 and for standard IRQ 1 handler */ call_int16=CALLBACK_Allocate(); call_irq1=CALLBACK_Allocate(); - CALLBACK_Setup(call_int16,&INT16_Handler,CB_IRET_STI); + CALLBACK_Setup(call_int16,&INT16_Handler,CB_IRET_STI,"keyboard"); RealSetVec(0x16,CALLBACK_RealPointer(call_int16)); - CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRET); + CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRET,"keyboard irq"); RealSetVec(0x9,CALLBACK_RealPointer(call_irq1)); + + /* bring the all port operations outside the callback */ + phys_writeb(CB_BASE+(call_irq1<<4)+0x00,(Bit8u)0x50); // push ax + phys_writeb(CB_BASE+(call_irq1<<4)+0x01,(Bit8u)0xe4); // in al, 0x60 + phys_writeb(CB_BASE+(call_irq1<<4)+0x02,(Bit8u)0x60); + phys_writeb(CB_BASE+(call_irq1<<4)+0x03,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(call_irq1<<4)+0x04,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(call_irq1<<4)+0x05,call_irq1); //The immediate word + phys_writeb(CB_BASE+(call_irq1<<4)+0x07,(Bit8u)0xb0); // mov al, 0x20 + phys_writeb(CB_BASE+(call_irq1<<4)+0x08,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_irq1<<4)+0x09,(Bit8u)0xe6); // out 0x20, al + phys_writeb(CB_BASE+(call_irq1<<4)+0x0a,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_irq1<<4)+0x0b,(Bit8u)0x58); // pop ax + phys_writeb(CB_BASE+(call_irq1<<4)+0x0c,(Bit8u)0xcf); // iret }