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:
parent
bc1ef40805
commit
a48880d4e4
2 changed files with 161 additions and 69 deletions
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue