1
0
Fork 0

set keyb.scheduled to false if the events are removed.

Handle numlock scrollock capslock and insert.
Produce proper codes for extended arrow keys.
Make shift and capslock/numlock mutually exclusive.
Handle the numeric keyboard.
Update int 16 to handle the extended arrow keys.
Implemented Alt-numeric.
Made keyboard vitualazation under win3.x possible.
Handle Some more keyboard flags.
Fixed flags when 2 alts/ctrl were presed and one was released.


Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1764
This commit is contained in:
Peter Veenstra 2004-04-07 09:36:59 +00:00
parent bc1ef40805
commit a48880d4e4
2 changed files with 161 additions and 69 deletions

View file

@ -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 <string.h>
#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 */

View file

@ -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
}