Fixed space handling on iOS 9.1
This commit is contained in:
parent
3bad5547c2
commit
bf75b8a059
5 changed files with 136 additions and 50 deletions
|
|
@ -47,11 +47,11 @@ if (NODE) {
|
|||
*
|
||||
* The Keyboard component can be configured with the following (parmsKbd) properties:
|
||||
*
|
||||
* model: model string; should be one of:
|
||||
* model: keyboard model string, which must match one of the values listed in Keyboard.MODELS:
|
||||
*
|
||||
* us83 (default)
|
||||
* us84 (TODO: awaiting implementation)
|
||||
* us101 (TODO: awaiting implementation)
|
||||
* "US83" (default)
|
||||
* "US84"
|
||||
* "US101"
|
||||
*
|
||||
* Its main purpose is to receive binding requests for various keyboard events, and to use those events
|
||||
* to simulate the PC's keyboard hardware.
|
||||
|
|
@ -64,7 +64,7 @@ function Keyboard(parmsKbd)
|
|||
{
|
||||
Component.call(this, "Keyboard", parmsKbd, Keyboard, Messages.KEYBOARD);
|
||||
|
||||
this.nDefaultModel = parmsKbd['model'];
|
||||
this.setModel(parmsKbd['model']);
|
||||
|
||||
this.fMobile = web.isMobile();
|
||||
this.fMSIE = web.isUserAgent("MSIE");
|
||||
|
|
@ -148,6 +148,11 @@ function Keyboard(parmsKbd)
|
|||
|
||||
Component.subclass(Keyboard);
|
||||
|
||||
/*
|
||||
* Supported keyboard models (the first entry is the default if the specified model isn't recognized)
|
||||
*/
|
||||
Keyboard.MODELS = ["US83", "US84", "US101"];
|
||||
|
||||
/**
|
||||
* Alphanumeric and other common (printable) ASCII codes.
|
||||
*
|
||||
|
|
@ -197,6 +202,7 @@ Keyboard.KEYCODE = {
|
|||
/* 0x13 */ PAUSE: 19, // PAUSE/BREAK
|
||||
/* 0x14 */ CAPS_LOCK: 20,
|
||||
/* 0x1B */ ESC: 27,
|
||||
/* 0x20 */ SPACE: 32,
|
||||
/* 0x21 */ PGUP: 33,
|
||||
/* 0x22 */ PGDN: 34,
|
||||
/* 0x23 */ END: 35,
|
||||
|
|
@ -339,6 +345,7 @@ Keyboard.SIMCODE = {
|
|||
ALT: Keyboard.KEYCODE.ALT + Keyboard.KEYCODE.ONDOWN,
|
||||
CAPS_LOCK: Keyboard.KEYCODE.CAPS_LOCK + Keyboard.KEYCODE.ONDOWN,
|
||||
ESC: Keyboard.KEYCODE.ESC + Keyboard.KEYCODE.ONDOWN,
|
||||
SPACE: Keyboard.KEYCODE.SPACE + Keyboard.KEYCODE.ONDOWN,
|
||||
F1: Keyboard.KEYCODE.F1 + Keyboard.KEYCODE.ONDOWN,
|
||||
F2: Keyboard.KEYCODE.F2 + Keyboard.KEYCODE.ONDOWN,
|
||||
F3: Keyboard.KEYCODE.F3 + Keyboard.KEYCODE.ONDOWN,
|
||||
|
|
@ -673,7 +680,7 @@ Keyboard.SOFTCODES = {
|
|||
/* 54 */ 'right-shift': Keyboard.SIMCODE.RSHIFT, // formerly "rshift"
|
||||
/* 55 */ 'prtsc': Keyboard.SIMCODE.PRTSC, // unshifted '*'; becomes dedicated 'Print Screen' key on 101-key keyboards
|
||||
/* 56 */ 'alt': Keyboard.SIMCODE.ALT,
|
||||
/* 57 */ 'space': Keyboard.ASCII[' '],
|
||||
/* 57 */ 'space': Keyboard.SIMCODE.SPACE,
|
||||
/* 58 */ 'caps-lock': Keyboard.SIMCODE.CAPS_LOCK,
|
||||
/* 59 */ 'f1': Keyboard.SIMCODE.F1,
|
||||
/* 60 */ 'f2': Keyboard.SIMCODE.F2,
|
||||
|
|
@ -858,7 +865,7 @@ Keyboard.SIMCODES[Keyboard.ASCII['?']] = Keyboard.SCANCODE.SLASH | (K
|
|||
Keyboard.SIMCODES[Keyboard.SIMCODE.RSHIFT] = Keyboard.SCANCODE.RSHIFT;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.PRTSC] = Keyboard.SCANCODE.PRTSC;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.ALT] = Keyboard.SCANCODE.ALT;
|
||||
Keyboard.SIMCODES[Keyboard.ASCII[' ']] = Keyboard.SCANCODE.SPACE;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.SPACE] = Keyboard.SCANCODE.SPACE;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.CAPS_LOCK] = Keyboard.SCANCODE.CAPS_LOCK;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.F1] = Keyboard.SCANCODE.F1;
|
||||
Keyboard.SIMCODES[Keyboard.SIMCODE.F2] = Keyboard.SCANCODE.F2;
|
||||
|
|
@ -1150,13 +1157,26 @@ Keyboard.prototype.notifyEscape = function(fDisabled, fAllDown)
|
|||
};
|
||||
|
||||
/**
|
||||
* setModel(nModel)
|
||||
* setModel(sModel)
|
||||
*
|
||||
* This breaks a model string (eg, "US83") into two parts: modelCountry (eg, "US") and modelKeys (eg, 83).
|
||||
* If the model string isn't recognized, we use Keyboard.MODELS[0] (ie, the first entry in the model array).
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {number} nModel
|
||||
* @param {string|undefined} sModel
|
||||
*/
|
||||
Keyboard.prototype.setModel = function(nModel)
|
||||
Keyboard.prototype.setModel = function(sModel)
|
||||
{
|
||||
var iModel = 0;
|
||||
this.model = null;
|
||||
if (sModel) {
|
||||
this.model = sModel.toUpperCase();
|
||||
iModel = Keyboard.MODELS.indexOf(this.model);
|
||||
if (iModel < 0) iModel = 0;
|
||||
}
|
||||
sModel = Keyboard.MODELS[iModel];
|
||||
this.modelCountry = sModel.substr(0, 2);
|
||||
this.modelKeys = parseInt(sModel.substr(2), 10);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1383,7 +1403,22 @@ Keyboard.prototype.powerDown = function(fSave, fShutdown)
|
|||
*/
|
||||
Keyboard.prototype.reset = function()
|
||||
{
|
||||
this.setModel(this.nDefaultModel);
|
||||
/*
|
||||
* If no keyboard model was specified, our initial setModel() call will select the "US83" keyboard as the
|
||||
* default, but now that the ChipSet is initialized, we can pick a better default, based on the ChipSet model.
|
||||
*/
|
||||
if (!this.model && this.chipset) {
|
||||
switch(this.chipset.model) {
|
||||
case ChipSet.MODEL_5150:
|
||||
case ChipSet.MODEL_5160:
|
||||
this.setModel(Keyboard.MODELS[0]);
|
||||
break;
|
||||
case ChipSet.MODEL_5170:
|
||||
default:
|
||||
this.setModel(Keyboard.MODELS[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.initState();
|
||||
|
||||
|
|
@ -1881,7 +1916,7 @@ Keyboard.prototype.updateActiveKey = function(key, msTimer)
|
|||
this.printMessage((msTimer? '\n' : "") + "updateActiveKey(" + key.simCode + (msTimer? "," + msTimer + "ms" : "") + "): " + (key.fDown? "down" : "up"), true);
|
||||
}
|
||||
|
||||
this.keySimulate(key.simCode, key.fDown);
|
||||
if (!this.keySimulate(key.simCode, key.fDown)) return;
|
||||
|
||||
if (!key.nRepeat) return;
|
||||
|
||||
|
|
@ -2173,6 +2208,14 @@ Keyboard.prototype.keySimulate = function(simCode, fDown)
|
|||
|
||||
var abScanCodes = [];
|
||||
var bCode = wCode & 0xff;
|
||||
|
||||
/*
|
||||
* TODO: Update the following restrictions to address 84-key and 101-key keyboards limitations.
|
||||
*/
|
||||
if (bCode > 83 && this.modelKeys == 83) {
|
||||
return false;
|
||||
}
|
||||
|
||||
abScanCodes.push(bCode | (fDown? 0 : Keyboard.SCANCODE.BREAK));
|
||||
|
||||
var fAlpha = (simCode >= Keyboard.ASCII.A && simCode <= Keyboard.ASCII.Z || simCode >= Keyboard.ASCII.a && simCode <= Keyboard.ASCII.z);
|
||||
|
|
|
|||
|
|
@ -343,12 +343,23 @@ SerialPort.prototype.setBinding = function(sHTMLType, sBinding, control)
|
|||
|
||||
switch (sBinding) {
|
||||
case SerialPort.sIOBuffer:
|
||||
/*
|
||||
* TODO: Figure out how to make this control activate the soft keyboard on iOS; since
|
||||
* this control has the "readonly" attribute by default, iOS refuses to activate the
|
||||
* keyboard, and adding the "contenteditable" attribute doesn't override that behavior.
|
||||
*
|
||||
* Removing the "readonly" attribute works, but then every key press results in double
|
||||
* characters; presumably that could be overcome by processing all keys in the onKeyDown()
|
||||
* handler instead, but that would require keyCode mapping tables, because down events
|
||||
* are not the same as press events.
|
||||
*/
|
||||
this.bindings[sBinding] = this.controlIOBuffer = control;
|
||||
|
||||
/*
|
||||
* By establishing an onkeypress handler here, we make it possible for DOS commands like
|
||||
* "CTTY COM1" to more or less work (use "CTTY CON" to restore control to the DOS console).
|
||||
*/
|
||||
control.onkeydown = function onKeyDownSerial(event) {
|
||||
control.onkeydown = function onKeyDown(event) {
|
||||
/*
|
||||
* This is required in addition to onkeypress, because it's the only way to prevent
|
||||
* BACKSPACE (keyCode 8) from being interpreted by the browser as a "Back" operation;
|
||||
|
|
@ -369,18 +380,28 @@ SerialPort.prototype.setBinding = function(sHTMLType, sBinding, control)
|
|||
}
|
||||
return true;
|
||||
};
|
||||
control.onkeypress = function onKeyPressSerial(event) {
|
||||
control.onkeypress = function onKeyPress(event) {
|
||||
/*
|
||||
* Browser-independent keyCode extraction (refer to keyPress() and the other key
|
||||
* event handlers in keyboard.js).
|
||||
*
|
||||
* The additional check for SPACE (keyCode 0x20) and subsequent preventDefault() call
|
||||
* prevents SPACE from bubbling up to the document event handlers, where its default
|
||||
* behavior is typically to scroll the entire page -- a real nuisance.
|
||||
* Browser-independent keyCode extraction; refer to keyPress() and the other key event
|
||||
* handlers in keyboard.js.
|
||||
*/
|
||||
event = event || window.event;
|
||||
var keyCode = event.which || event.keyCode;
|
||||
serial.sendRBR([keyCode]);
|
||||
/*
|
||||
* This additional check for SPACE (keyCode 0x20) and subsequent preventDefault()
|
||||
* prevents SPACE from bubbling up to the document event handlers, where the default
|
||||
* behavior is typically to scroll the entire page -- a real nuisance.
|
||||
*
|
||||
* Keyboard.onKeyPress() has a similar issue, but it seems to be limited to Safari on iOS,
|
||||
* first noticed on iOS 9.1. The problem there is that Safari's default SPACE behavior
|
||||
* occurs BEFORE the onkeypress handler is called, so we would have to call preventDefault()
|
||||
* in the onkeydown handler, but then the onkeypress handler would no longer be called.
|
||||
*
|
||||
* So, to resolve the Keyboard.onKeyPress() issue, we now define SPACE as an ONDOWN key,
|
||||
* so that onKeyDown() will process the SPACE key immediately and automatically invoke
|
||||
* preventDefault().
|
||||
*/
|
||||
if (keyCode == 0x20) {
|
||||
if (event.preventDefault) event.preventDefault();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ var X86 = {
|
|||
* Priority: Instruction exception, TRAP, NMI, Processor Extension Segment Overrun, and finally INTR.
|
||||
*
|
||||
* All exceptions can also occur in real-mode, except where noted. A GP_FAULT in real-mode can be triggered
|
||||
* by "any memory reference instruction that attempts to reference [a] 16-bit word at offset 0FFFFH".
|
||||
* by "any memory reference instruction that attempts to reference [a] 16-bit word at offset 0xFFFF".
|
||||
*
|
||||
* Interrupts beyond 0x10 (up through 0x1F) are reserved for future exceptions.
|
||||
*
|
||||
|
|
@ -137,11 +137,11 @@ var X86 = {
|
|||
DF: 0x0400, // bit 10: Direction flag
|
||||
OF: 0x0800, // bit 11: Overflow flag
|
||||
IOPL: {
|
||||
MASK: 0x3000, // bits 12-13: I/O Privilege Level (always set on 8086/80186, clear on 80286 reset)
|
||||
MASK: 0x3000, // bits 12-13: I/O Privilege Level (always set on 8086/80186; clear on 80286 reset)
|
||||
SHIFT: 12
|
||||
},
|
||||
NT: 0x4000, // bit 14: Nested Task flag (always set on 8086/80186, clear on 80286 reset)
|
||||
BIT15: 0x8000, // bit 15: reserved (always set on 8086/80186, clear otherwise)
|
||||
NT: 0x4000, // bit 14: Nested Task flag (always set on 8086/80186; clear on 80286 reset)
|
||||
BIT15: 0x8000, // bit 15: reserved (always set on 8086/80186; clear otherwise)
|
||||
RF: 0x10000, // bit 16: Resume Flag (temporarily disables debug exceptions; 80386 only)
|
||||
VM: 0x20000 // bit 17: Virtual 8086 Mode (80386 only)
|
||||
},
|
||||
|
|
@ -461,7 +461,7 @@ var X86 = {
|
|||
SS: 0x36, // opSS()
|
||||
DS: 0x3E, // opDS()
|
||||
PUSHSP: 0x54, // opPUSHSP()
|
||||
PUSHA: 0x60, // opPUHSA() (80186 and up)
|
||||
PUSHA: 0x60, // opPUSHA() (80186 and up)
|
||||
POPA: 0x61, // opPOPA() (80186 and up)
|
||||
BOUND: 0x62, // opBOUND() (80186 and up)
|
||||
ARPL: 0x63, // opARPL() (80286 and up)
|
||||
|
|
@ -519,12 +519,12 @@ var X86 = {
|
|||
UD2: 0x0B0F // UD2 (invalid opcode "guaranteed" to generate UD_FAULT on all post-8086 processors)
|
||||
},
|
||||
/*
|
||||
* Floating Point Unit (FPU), aka Numeric Data Processor (NDP), aka Numeric Processor Extension (NPX) definitions
|
||||
* Floating Point Unit (FPU), aka Numeric Data Processor (NDP), aka Numeric Processor Extension (NPX), aka Coprocessor definitions
|
||||
*/
|
||||
FPU: {
|
||||
MODEL_8087: 8087,
|
||||
MODEL_80287: 80287,
|
||||
MODEL_80287XL: 80387, // internally, the 80287XL was an 80387SX, so in general, we treat this as MODEL_80387
|
||||
MODEL_80287XL: 80387, // internally, the 80287XL was an 80387SX, so generally, we treat this as MODEL_80387
|
||||
MODEL_80387: 80387,
|
||||
CONTROL: { // FPU Control Word
|
||||
IM: 0x0001, // bit 0: Invalid Operation Mask
|
||||
|
|
@ -534,18 +534,18 @@ var X86 = {
|
|||
UM: 0x0010, // bit 4: Underflow Mask
|
||||
PM: 0x0020, // bit 5: Precision Mask
|
||||
EXC: 0x003F, // all of the above exceptions
|
||||
// bit 6: unused
|
||||
IEM: 0x0080, // bit 7: Interrupt Enable Mask (0 enables interrupts, 1 masks them; 8087 only)
|
||||
PC: 0x0300, // bits 8-9: Precision Control
|
||||
RC: 0x0C00, // bits 10-11: Rounding Control
|
||||
RC_NEAR: 0x0000,
|
||||
RC_DOWN: 0x0400,
|
||||
RC_UP: 0x0800,
|
||||
RC_CHOP: 0x0C00,
|
||||
RC: { // bits 10-11: Rounding Control
|
||||
NEAR: 0x0000,
|
||||
DOWN: 0x0400,
|
||||
UP: 0x0800,
|
||||
CHOP: 0x0C00,
|
||||
MASK: 0x0C00
|
||||
},
|
||||
IC: 0x1000, // bit 12: Infinity Control (0 for Projective, 1 for Affine)
|
||||
// bits 13-15: unused
|
||||
INIT: 0x03BF, // X86.FPU.CONTROL.IM | X86.FPU.CONTROL.DM | X86.FPU.CONTROL.ZM | X86.FPU.CONTROL.OM | X86.FPU.CONTROL.UM | X86.FPU.CONTROL.PM | X86.FPU.CONTROL.IEM | X86.FPU.CONTROL.PC
|
||||
UNUSED: 0xE040
|
||||
UNUSED: 0xE040, // bits 6,13-15: unused
|
||||
INIT: 0x03BF // X86.FPU.CONTROL.IM | X86.FPU.CONTROL.DM | X86.FPU.CONTROL.ZM | X86.FPU.CONTROL.OM | X86.FPU.CONTROL.UM | X86.FPU.CONTROL.PM | X86.FPU.CONTROL.IEM | X86.FPU.CONTROL.PC
|
||||
},
|
||||
STATUS: { // FPU Status Word
|
||||
IE: 0x0001, // bit 0: Invalid Operation
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ if (NODE) {
|
|||
*
|
||||
* FPU Coprocessor Trivia
|
||||
*
|
||||
* Microsoft C libraries executed software interrupts in the range 0x34-0x3B immediately after
|
||||
* Microsoft C 4.00 libraries executed software interrupts in the range 0x34-0x3B immediately after
|
||||
* FPU operations, to assist with floating-point emulation when no coprocessor was present, since
|
||||
* processors prior to the 80286 had no mechanism for generating a fault when an unsupported FPU
|
||||
* instruction was executed.
|
||||
|
|
@ -68,7 +68,7 @@ if (NODE) {
|
|||
* In short, INT 0x34 through INT 0x3B was used after ESC opcodes 0xD8 through 0xDF, INT 0x3C was
|
||||
* used for FPU instructions containing a segment override, and INT 0x3D was used for FWAIT.
|
||||
*
|
||||
* A sample piece of code is available in x86ops.js, because it also highlights the Microsoft C
|
||||
* A sample piece of code is available in x86ops.js, because it also highlights the Microsoft C 4.00
|
||||
* library's dependency on the 8086/8088 behavior of "PUSH SP" (see the opPUSHSP_8086() function).
|
||||
*/
|
||||
|
||||
|
|
@ -276,6 +276,8 @@ X86FPU.prototype.restore = function(data)
|
|||
* us whenever an I/O operation that resets the coprocessor is performed. Only 80487 coprocessors and higher will
|
||||
* also clear the "exception" registers, but the 80487 is currently beyond my planned level of support.
|
||||
*
|
||||
* TODO: Add support for X86.FPU.CONTROL.PC (Precision Control) and X86.FPU.CONTROL.IC (Infinity Control)
|
||||
*
|
||||
* @this {X86FPU}
|
||||
*/
|
||||
X86FPU.prototype.resetFPU = function()
|
||||
|
|
@ -287,8 +289,8 @@ X86FPU.prototype.resetFPU = function()
|
|||
this.iST = 0; // the ST bits for regStatus are actually stored here
|
||||
if (DEBUG) {
|
||||
/*
|
||||
* All the registers were tagged "unused" above, which is all that would normally happen,
|
||||
* but debugging is a little easier if we also zero everything, too.
|
||||
* All the registers were tagged "unused" above, which is all that would normally happen, but debugging is
|
||||
* a little easier if we zero all the registers as well.
|
||||
*/
|
||||
for (var iReg = 0; iReg < this.regStack.length; iReg++) {
|
||||
this.regStack[iReg] = 0.0;
|
||||
|
|
@ -315,7 +317,7 @@ X86FPU.prototype.isModel = function(model)
|
|||
/**
|
||||
* isAtLeastModel(model)
|
||||
*
|
||||
* If the current model is greater than or equal to the specified model, then it's assumed the
|
||||
* If the current model is greater than or equal to the specified model, then it's assumed that the
|
||||
* current operation is supported, and we return true.
|
||||
*
|
||||
* @this {X86FPU}
|
||||
|
|
@ -334,9 +336,9 @@ X86FPU.prototype.isAtLeastModel = function(model)
|
|||
* to a "temp-real" (REAL80) and back again losslessly, otherwise a bug in either getTRFromLR() or getLRFromTR()
|
||||
* might exist. That test code can be resurrected from the repo; this code is being retained for future tests.
|
||||
*
|
||||
* NOTE: If either min or max is a value containing 32 or more bits AND bit 31 is set AND it has passed
|
||||
* through some bit-wise operation(s), then that value may end up being negative, so you may end up with an
|
||||
* inverted (or empty) range or other unexpected results.
|
||||
* NOTE: If either min or max is a value containing 32 or more significant bits AND bit 31 is set AND it has passed
|
||||
* through some bit-wise operation(s), then that value may end up being negative, so you may end up with an inverted
|
||||
* range, or a range that's smaller or larger than intended.
|
||||
*
|
||||
* @this {X86FPU}
|
||||
* @param {number} min (inclusive)
|
||||
|
|
@ -712,16 +714,16 @@ X86FPU.prototype.roundInteger = function(operand, max)
|
|||
{
|
||||
if (operand == null) return null;
|
||||
|
||||
var rc = (this.regControl & X86.FPU.CONTROL.RC), result;
|
||||
var rc = (this.regControl & X86.FPU.CONTROL.RC.MASK), result;
|
||||
|
||||
if (rc == X86.FPU.CONTROL.RC_NEAR) {
|
||||
if (rc == X86.FPU.CONTROL.RC.NEAR) {
|
||||
result = Math.round(operand);
|
||||
if (result - operand === 0.5 && (result % 2)) result--;
|
||||
}
|
||||
else if (rc == X86.FPU.CONTROL.RC_DOWN || rc == X86.FPU.CONTROL.RC_CHOP && operand > 0) {
|
||||
else if (rc == X86.FPU.CONTROL.RC.DOWN || rc == X86.FPU.CONTROL.RC.CHOP && operand > 0) {
|
||||
result = Math.floor(operand);
|
||||
}
|
||||
else { // X86.FPU.CONTROL.RC_UP or X86.FPU.CONTROL.RC_CHOP && operand <= 0
|
||||
else { // X86.FPU.CONTROL.RC.UP or X86.FPU.CONTROL.RC.CHOP && operand <= 0
|
||||
result = Math.ceil(operand);
|
||||
}
|
||||
|
||||
|
|
@ -1417,6 +1419,8 @@ X86FPU.prototype.saveEnv = function(addr)
|
|||
/**
|
||||
* opFPU(bOpcode, bModRM, dst, src)
|
||||
*
|
||||
* This is called by the CPU's ESC opcode handlers, after each instruction has been fully decoded.
|
||||
*
|
||||
* @this {X86FPU}
|
||||
* @param {number} bOpcode (0xD8-0xDF)
|
||||
* @param {number} bModRM
|
||||
|
|
@ -1485,6 +1489,23 @@ X86FPU.prototype.opFPU = function(bOpcode, bModRM, dst, src)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* opWAIT()
|
||||
*
|
||||
* This is called by the CPU's WAIT opcode handler, giving us the opportunity to synchronize the FPU with the CPU,
|
||||
* charge an appropriate number of cycles, and return true. In this context, it's considered an FWAIT instruction,
|
||||
* but technically, it's the same opcode.
|
||||
*
|
||||
* If we choose to do nothing, then we must return false, so that the CPU can charge a default number of cycles.
|
||||
*
|
||||
* @this {X86FPU}
|
||||
* @return {boolean} true if implemented, false if not
|
||||
*/
|
||||
X86FPU.prototype.opWAIT = function()
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
if (DEBUGGER) {
|
||||
/**
|
||||
* readFPUStack(i)
|
||||
|
|
|
|||
|
|
@ -2600,8 +2600,9 @@ X86.opCALLF = function()
|
|||
*/
|
||||
X86.opWAIT = function()
|
||||
{
|
||||
this.printMessage("WAIT not implemented");
|
||||
this.nStepCycles--;
|
||||
if (!this.fpu || !this.fpu.opWAIT()) {
|
||||
this.nStepCycles -= 3; // X86FPU.opWAIT() is required to charge some number of cycles if it returns true
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue