v1.16.3: Keyboard module rewrite
There are still a few regressions to address, but keyCode-to-simCode-to-scanCode conversion feels more robust/cleaner, and new features like programmable repeat rates will actually be doable now
This commit is contained in:
parent
028684366e
commit
88cc526c32
146 changed files with 8127 additions and 1880 deletions
|
|
@ -4050,8 +4050,7 @@ ChipSet.prototype.in8042OutBuff = function(port, addrFrom)
|
|||
var b = this.b8042OutBuff;
|
||||
this.messagePort(port, null, addrFrom, "8042_OUTBUFF", b, Debugger.MESSAGE.C8042);
|
||||
this.b8042Status &= ~(ChipSet.KBC.STATUS.OUTBUFF_FULL | ChipSet.KBC.STATUS.OUTBUFF_DELAY);
|
||||
var bNext = this.kbd && this.kbd.readScanCode(true);
|
||||
if (bNext) this.set8042OutBuff(bNext);
|
||||
if (this.kbd) this.kbd.checkScanCode();
|
||||
return b;
|
||||
};
|
||||
|
||||
|
|
@ -4290,23 +4289,24 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
|
|||
|
||||
case ChipSet.KBC.CMD.DISABLE_KBD: // 0xAD
|
||||
this.set8042CmdData(this.b8042CmdData | ChipSet.KBC.DATA.CMD.NO_CLOCK);
|
||||
if (DEBUG) this.messageDebugger("keyboard disabled", Debugger.MESSAGE.KBD | Debugger.MESSAGE.PORT);
|
||||
if (DEBUG) this.messageDebugger("keyboard disabled", Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT);
|
||||
/*
|
||||
* NOTE: The MODEL_5170 BIOS calls "KBD_RESET" (F000:17D2) while the keyboard interface is disabled,
|
||||
* yet we must still deliver the Keyboard's CMDRES.BAT_SUCC response code? Seems like an odd thing for
|
||||
* yet we must still deliver the Keyboard's CMDRES.BAT_OK response code? Seems like an odd thing for
|
||||
* a "disabled interface" to do.
|
||||
*/
|
||||
break;
|
||||
|
||||
case ChipSet.KBC.CMD.ENABLE_KBD: // 0xAE
|
||||
this.set8042CmdData(this.b8042CmdData & ~ChipSet.KBC.DATA.CMD.NO_CLOCK);
|
||||
if (DEBUG) this.messageDebugger("keyboard re-enabled", Debugger.MESSAGE.KBD | Debugger.MESSAGE.PORT);
|
||||
if (this.kbd) this.kbd.checkScanCode();
|
||||
if (DEBUG) this.messageDebugger("keyboard re-enabled", Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT);
|
||||
break;
|
||||
|
||||
case ChipSet.KBC.CMD.SELF_TEST: // 0xAA
|
||||
if (this.kbd) this.kbd.shiftScanCode(true);
|
||||
if (this.kbd) this.kbd.flushScanCode();
|
||||
this.set8042CmdData(this.b8042CmdData | ChipSet.KBC.DATA.CMD.NO_CLOCK);
|
||||
if (DEBUG) this.messageDebugger("keyboard disabled on reset", Debugger.MESSAGE.KBD | Debugger.MESSAGE.PORT);
|
||||
if (DEBUG) this.messageDebugger("keyboard disabled on reset", Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT);
|
||||
this.set8042OutBuff(ChipSet.KBC.DATA.SELF_TEST.OK);
|
||||
this.set8042OutPort(ChipSet.KBC.OUTPORT.NO_RESET | ChipSet.KBC.OUTPORT.A20_ON);
|
||||
break;
|
||||
|
|
@ -4356,7 +4356,7 @@ ChipSet.prototype.set8042CmdData = function(b)
|
|||
*
|
||||
* And indeed, if we call the original MODEL_5150/MODEL_5160 setEnable() Keyboard interface here,
|
||||
* and both the data and clock lines have transitioned high (ie, both parameters are true), then it
|
||||
* will call resetDevice(), generating a Keyboard.CMDRES.BAT_SUCC response.
|
||||
* will call resetDevice(), generating a Keyboard.CMDRES.BAT_OK response.
|
||||
*
|
||||
* This agrees with my understanding of what happens when the 8042 toggles the clock line high
|
||||
* (ie, clears NO_CLOCK): the TechRef's "Basic Assurance Test" section says that when the Keyboard is
|
||||
|
|
@ -4364,12 +4364,7 @@ ChipSet.prototype.set8042CmdData = function(b)
|
|||
* a completion code (eg, 0xAA for success, or 0xFC or something else for failure).
|
||||
*/
|
||||
var bClockEnabled = !(b & ChipSet.KBC.DATA.CMD.NO_CLOCK);
|
||||
if (this.kbd.setEnable(!!(b & ChipSet.KBC.DATA.CMD.NO_INHIBIT), bClockEnabled)) {
|
||||
this.set8042OutBuff(this.kbd.readScanCode(true));
|
||||
}
|
||||
if (!bClockWasEnabled && bClockEnabled && this.kbd.readScanCode()) {
|
||||
this.notifyKbdData(true);
|
||||
}
|
||||
this.kbd.setEnable(!!(b & ChipSet.KBC.DATA.CMD.NO_INHIBIT), bClockEnabled);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -4385,6 +4380,9 @@ ChipSet.prototype.set8042OutBuff = function(b)
|
|||
this.b8042OutBuff = b;
|
||||
this.b8042Status &= ~ChipSet.KBC.STATUS.OUTBUFF_FULL;
|
||||
this.b8042Status |= ChipSet.KBC.STATUS.OUTBUFF_DELAY;
|
||||
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT)) {
|
||||
this.messageDebugger("set8042OutBuff(0x" + str.toHexByte(b) + ")", true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -4413,11 +4411,11 @@ ChipSet.prototype.set8042OutPort = function(b)
|
|||
};
|
||||
|
||||
/**
|
||||
* notifyKbdData(fAvail)
|
||||
* notifyKbdData(b)
|
||||
*
|
||||
* In the old days of PCjs, the Keyboard component would simply call setIRR() when it had some data for the
|
||||
* keyboard controller. However, the sole responsibility of the Keyboard is to emulate an actual keyboard and
|
||||
* call notifyKbdData() whenever it has some data; it has no business messing with IRQ lines.
|
||||
* keyboard controller. However, the Keyboard's sole responsibility is to emulate an actual keyboard and call
|
||||
* notifyKbdData() whenever it has some data; it's not supposed to mess with IRQ lines.
|
||||
*
|
||||
* If there's an 8042, we check (this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK); if NO_CLOCK is clear,
|
||||
* we can raise the IRQ immediately. Well, not quite immediately....
|
||||
|
|
@ -4488,9 +4486,9 @@ ChipSet.prototype.set8042OutPort = function(b)
|
|||
* instructions, just to be safe, and pass that along to every setIRR() call we make here.
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {boolean} fAvail is true if the Keyboard has data to send, false if not
|
||||
* @param {number} b
|
||||
*/
|
||||
ChipSet.prototype.notifyKbdData = function(fAvail)
|
||||
ChipSet.prototype.notifyKbdData = function(b)
|
||||
{
|
||||
if (this.model < ChipSet.MODEL_5170) {
|
||||
/*
|
||||
|
|
@ -4499,12 +4497,29 @@ ChipSet.prototype.notifyKbdData = function(fAvail)
|
|||
this.setIRR(ChipSet.IRQ.KBD, 4);
|
||||
}
|
||||
else {
|
||||
if (!(this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK) && fAvail) {
|
||||
if (!(this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK)) {
|
||||
/*
|
||||
* A delay of 4 instructions was originally requested as part of the the Keyboard's resetDevice()
|
||||
* response, but a much larger delay (120) is now needed for MODEL_5170 machines, per the discussion above.
|
||||
* The next read of b8042OutBuff will clear both of these bits and call kbd.checkScanCode(),
|
||||
* which will call notifyKbdData() again if there's still keyboard data to process.
|
||||
*/
|
||||
this.setIRR(ChipSet.IRQ.KBD, 120);
|
||||
if (!(this.b8042Status & (ChipSet.KBC.STATUS.OUTBUFF_FULL | ChipSet.KBC.STATUS.OUTBUFF_DELAY))) {
|
||||
this.set8042OutBuff(b);
|
||||
this.kbd.shiftScanCode();
|
||||
/*
|
||||
* A delay of 4 instructions was originally requested as part of the the Keyboard's resetDevice()
|
||||
* response, but a much larger delay (120) is now needed for MODEL_5170 machines, per the discussion above.
|
||||
*/
|
||||
this.setIRR(ChipSet.IRQ.KBD, 120);
|
||||
}
|
||||
else {
|
||||
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT)) {
|
||||
this.messageDebugger("notifyKbdData(0x" + str.toHexByte(b) + "): output buffer full", true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYBOARD | Debugger.MESSAGE.PORT)) {
|
||||
this.messageDebugger("notifyKbdData(0x" + str.toHexByte(b) + "): disabled", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -4828,7 +4843,7 @@ ChipSet.prototype.messageBitsIRQ = function(nIRQ)
|
|||
if (nIRQ == ChipSet.IRQ.TIMER0) { // IRQ 0
|
||||
bitsMessage |= Debugger.MESSAGE.TIMER;
|
||||
} else if (nIRQ == ChipSet.IRQ.KBD) { // IRQ 1
|
||||
bitsMessage |= Debugger.MESSAGE.KBD;
|
||||
bitsMessage |= Debugger.MESSAGE.KEYBOARD;
|
||||
} else if (nIRQ == ChipSet.IRQ.SLAVE) { // IRQ 2 (MODEL_5170 and up)
|
||||
bitsMessage |= Debugger.MESSAGE.CHIPSET;
|
||||
} else if (nIRQ == ChipSet.IRQ.XTC) { // IRQ 5 (MODEL_5160)
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ Debugger.MESSAGE = {
|
|||
RTC: 0x00001000,
|
||||
C8042: 0x00002000,
|
||||
CHIPSET: 0x00004000,
|
||||
KBD: 0x00008000,
|
||||
KEYBOARD: 0x00008000,
|
||||
KEYS: 0x00010000,
|
||||
VIDEO: 0x00020000,
|
||||
FDC: 0x00040000,
|
||||
|
|
@ -246,7 +246,7 @@ if (DEBUGGER) {
|
|||
0x10: Debugger.MESSAGE.VIDEO,
|
||||
0x13: Debugger.MESSAGE.FDC,
|
||||
0x15: Debugger.MESSAGE.CHIPSET,
|
||||
0x16: Debugger.MESSAGE.KBD,
|
||||
0x16: Debugger.MESSAGE.KEYBOARD,
|
||||
// 0x1a: Debugger.MESSAGE.RTC, // ChipSet contains its own specialized messageInt() handler for the RTC
|
||||
0x1c: Debugger.MESSAGE.TIMER,
|
||||
0x21: Debugger.MESSAGE.DOS,
|
||||
|
|
@ -525,7 +525,7 @@ if (DEBUGGER) {
|
|||
"rtc": Debugger.MESSAGE.RTC,
|
||||
"8042": Debugger.MESSAGE.C8042,
|
||||
"chipset": Debugger.MESSAGE.CHIPSET, // ie, anything else in ChipSet besides DMA, PIC, TIMER, CMOS, RTC and 8042
|
||||
"kbd": Debugger.MESSAGE.KBD,
|
||||
"keyboard": Debugger.MESSAGE.KEYBOARD,
|
||||
"key": Debugger.MESSAGE.KEYS, // using "keys" instead of "key" causes an unfortunate JavaScript property collision
|
||||
"video": Debugger.MESSAGE.VIDEO,
|
||||
"fdc": Debugger.MESSAGE.FDC,
|
||||
|
|
@ -1562,7 +1562,7 @@ if (DEBUGGER) {
|
|||
this.bitsMessage = this.bitsWarning = Debugger.MESSAGE.WARN;
|
||||
this.sMessagePrev = null;
|
||||
this.afnDumpers = [];
|
||||
var aEnable = this.parseCommand(sEnable);
|
||||
var aEnable = this.parseCommand(sEnable.replace("keys","key").replace("kbd","keyboard"));
|
||||
if (aEnable.length) {
|
||||
for (var m in Debugger.MESSAGES) {
|
||||
if (aEnable.indexOf(m) >= 0) {
|
||||
|
|
@ -4145,6 +4145,8 @@ if (DEBUGGER) {
|
|||
fCriteria = false;
|
||||
sCategory = null;
|
||||
} else {
|
||||
if (sCategory == "keys") sCategory = "key";
|
||||
if (sCategory == "kbd") sCategory = "keyboard";
|
||||
for (m in Debugger.MESSAGES) {
|
||||
if (sCategory == m) {
|
||||
bitsMessage = Debugger.MESSAGES[m];
|
||||
|
|
@ -4181,6 +4183,7 @@ if (DEBUGGER) {
|
|||
if (fCriteria !== null && fCriteria != fEnabled) continue;
|
||||
if (sCategories) sCategories += ",";
|
||||
if (!(++n % 10)) sCategories += "\n\t"; // jshint ignore:line
|
||||
if (m == "key") m = "keys";
|
||||
sCategories += m;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2305,15 +2305,15 @@ Video.prototype.processTouchEvent = function(event, fStart)
|
|||
*/
|
||||
if (/* xThird == 1 && */ yThird != 1) {
|
||||
if (!yThird) {
|
||||
this.kbd.keySimulatePress(Keyboard.aButtonCodes.up, true);
|
||||
this.kbd.addActiveKey(Keyboard.CLICKCODES.UP, true);
|
||||
} else {
|
||||
this.kbd.keySimulatePress(Keyboard.aButtonCodes.down, true);
|
||||
this.kbd.addActiveKey(Keyboard.CLICKCODES.DOWN, true);
|
||||
}
|
||||
} else if (/* yThird == 1 && */ xThird != 1) {
|
||||
if (!xThird) {
|
||||
this.kbd.keySimulatePress(Keyboard.aButtonCodes.left, true);
|
||||
this.kbd.addActiveKey(Keyboard.CLICKCODES.LEFT, true);
|
||||
} else {
|
||||
this.kbd.keySimulatePress(Keyboard.aButtonCodes.right, true);
|
||||
this.kbd.addActiveKey(Keyboard.CLICKCODES.RIGHT, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
|
|||
/*
|
||||
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
|
||||
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
|
||||
* starting with a 15-cycle difference. Obviously the difference will be much greater when the load fails.
|
||||
* starting with a 15-cycle difference. Obviously the difference will vary with the instruction,
|
||||
* and will be much greater whenever the load fails.
|
||||
*/
|
||||
if (!fSuppress) cpu.nStepCycles -= 15;
|
||||
return this.loadDesc8(addrDesc, sel, fSuppress);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
body {
|
||||
margin: 0;
|
||||
background: #1d1d1d;
|
||||
background: #202020;
|
||||
}
|
||||
h1, h2 {
|
||||
margin-top: 0;
|
||||
|
|
@ -81,7 +81,7 @@ pre a, code a {
|
|||
font-weight: bold;
|
||||
}
|
||||
.common-top {
|
||||
background: #1d1d1d;
|
||||
background: #202020;
|
||||
font-size: small;
|
||||
}
|
||||
.common-top-left {
|
||||
|
|
@ -118,7 +118,7 @@ pre a, code a {
|
|||
.common-middle {
|
||||
clear: both;
|
||||
padding: 1px 1em 1px 1em;
|
||||
background: #303030;
|
||||
background: #404040;
|
||||
}
|
||||
.common-sidebar {
|
||||
float: left;
|
||||
|
|
|
|||
Loading…
Reference in a new issue