bugfix: keyboard led synchronization now compares against LEDs bitmask,

and only updates then, just like a real BIOS. this fixes LED flickering
when running code that directly communicates with the controller.
This commit is contained in:
Jonathan Campbell
2015-08-27 13:09:09 -07:00
parent 5fcf21a5c9
commit 6ad7dd1797
3 changed files with 17 additions and 15 deletions

View File

@@ -302,18 +302,6 @@ void KEYBOARD_SetLEDs(Bit8u bits) {
LOG(LOG_KEYBOARD,LOG_DEBUG)("Keyboard LEDs: SCR=%u NUM=%u CAPS=%u",bits&1,(bits>>1)&1,(bits>>2)&1);
}
// believe it or not most BIOSes will also periodically check the BIOS data area
// and send updated keyboard LED state from it if it changes, from within IRQ 0 (INT 8h).
// This is not documented anywhere I know, but it's been my experience with DOS
// programming and Windows 3.1/9x keyboard handling seems to rely on it.
void KEYBOARD_BIOS_CheckLEDs_From_DataArea(Bitu bits) {
if ((bits & 7) != (keyb.led_state & 7)) {
keyb.led_state = bits;
UpdateKeyboardLEDState(bits);
LOG(LOG_KEYBOARD, LOG_DEBUG)("Keyboard LEDs (from BIOS data area update): SCR=%u NUM=%u CAPS=%u", bits & 1, (bits >> 1) & 1, (bits >> 2) & 1);
}
}
static Bitu read_p60(Bitu port,Bitu iolen) {
keyb.p60changed=false;
keyb.auxchanged=false;

View File

@@ -1894,7 +1894,16 @@ static void BIOS_HostTimeSync() {
// TODO: make option
bool enable_bios_timer_synchronize_keyboard_leds = true;
void KEYBOARD_BIOS_CheckLEDs_From_DataArea(Bitu x);
void KEYBOARD_SetLEDs(Bit8u bits);
void BIOS_KEYBOARD_SetLEDs(Bitu state) {
Bitu x = mem_readb(BIOS_KEYBOARD_LEDS);
x &= ~7;
x |= (state & 7);
mem_writeb(BIOS_KEYBOARD_LEDS,x);
KEYBOARD_SetLEDs(state);
}
static Bitu INT8_Handler(void) {
/* Increase the bios tick counter */
@@ -1913,8 +1922,13 @@ static Bitu INT8_Handler(void) {
it when handling the keyboard from it's own driver. Their driver does
hook the keyboard and handles keyboard I/O by itself, but it still
allows the BIOS to do the keyboard magic from IRQ 0 (INT 8h). Yech. */
if (enable_bios_timer_synchronize_keyboard_leds)
KEYBOARD_BIOS_CheckLEDs_From_DataArea((mem_readb(BIOS_KEYBOARD_STATE) >> 4) & 7);
if (enable_bios_timer_synchronize_keyboard_leds) {
Bitu should_be = (mem_readb(BIOS_KEYBOARD_STATE) >> 4) & 7;
Bitu led_state = (mem_readb(BIOS_KEYBOARD_LEDS) & 7);
if (should_be != led_state)
BIOS_KEYBOARD_SetLEDs(should_be);
}
#if DOSBOX_CLOCKSYNC
static bool check = false;

Binary file not shown.