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:
Jeff Parsons 2014-12-09 16:34:46 -08:00 committed by jeffpar
commit 88cc526c32
146 changed files with 8127 additions and 1880 deletions

View file

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

View file

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

View file

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

View file

@ -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);

View file

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