From b6984d348ec3b8ac5e18a5e7448c11f65f891fb3 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Mon, 5 Jan 2015 21:00:07 -0800 Subject: [PATCH] Revert to a more conservative approach when mapping key events to scan codes --- docs/pcjs/demos/pc-dbg.js | 2 +- docs/pcjs/demos/pc.js | 2 +- modules/pcjs/lib/disk.js | 92 +++++++++++++++++++--------------- modules/pcjs/lib/keyboard.js | 14 +++++- versions/pcjs/1.16.5/pc-dbg.js | 2 +- versions/pcjs/1.16.5/pc.js | 2 +- 6 files changed, 67 insertions(+), 47 deletions(-) diff --git a/docs/pcjs/demos/pc-dbg.js b/docs/pcjs/demos/pc-dbg.js index 7861ce92c..ae2e057b3 100644 --- a/docs/pcjs/demos/pc-dbg.js +++ b/docs/pcjs/demos/pc-dbg.js @@ -519,7 +519,7 @@ function Pj(a,b,c,d){if(S[b]){var e=Math.floor(b/1E3)&2;if(b=Jj[b]||0){!e||b&85| function Oj(a,b,c){if(S[b]&&a.T&&a.T.ma.nb){Jj[b]&&a.Rb.length&&0e||(e==a.Rb.length&&(d={},d.ye=b,d.Fb=a.Fb,Rj(a,b,!0),e++),0b.wd){if(!b.mg){Qj(a,b.ye);return}b.mg=!1;c=a.jo}else c=1==b.wd++?a.ko:a.lo;b.vm=setTimeout(function(a){return function(){Sj(a,b)}}(a),c)}}else Qj(a,b.ye,!0)}function Uj(a,b,c){var d=b;if(65<=b&&90>=b)!(a.Fb&515)==c&&(d=b+32);else if(97<=b&&122>=b)!!(a.Fb&515)==c&&(d=b-32);else if(!!(a.Fb&3)==c){if(a=R[b])d=a}else if(a=Ij[b])d=a;return d}k.Uh=function(a){this.xh=a;a||(this.Fb&=-256)}; -function Nj(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Uj(a,g,!0);a.Mk&&h==O["`"]&&(g=h=27);if(S[g+1E3])if(h+=1E3,2==b.location&&(h+=2E3),Pj(a,h,!1,c)){if(20==g||144==g||145==g)a.Vm||(c=e=!0);if(!(c||91!=g&&93!=g))for(var n=0;n=b||97<=b&&122>=b;d>>>=8;){var g=0,h=d&255;224==f||225==f?e.push(f|(c?0:128)):(42==h?a.Fb&3||a.Fb&512&&b||(g=h):29==h?a.Fb&12||(g=h):56==h?a.Fb&48||(g=h):e.push(f|(c?0:128)),g&&(c?e.unshift(g):e.push(g|128)))}for(c=0;cd.Xb.length?(d.ua()&&d.fb("scan code 0x"+q(f)+" buffered"),d.Xb.push(f),1==d.Xb.length&&d.oa&&zj(d.oa, f)):(20==d.Xb.length&&d.Xb.push(255),d.fb("scan code buffer overflow")))}}Ja(function(){for(var a=A(window.document,"pcjs","keyboard"),b=0;be||(e==a.Ib.length&&(d={},d.Xd=b,d.ub=a.ub,Wi(a,b,!0),e++),0b.ad){if(!b.Af){Vi(a,b.Xd);return}b.Af=!1;c=a.nn}else c=1==b.ad++?a.on:a.pn;b.Dl=setTimeout(function(a){return function(){Xi(a,b)}}(a),c)}}else Vi(a,b.Xd,!0)}function Zi(a,b,c){var d=b;if(65<=b&&90>=b)!(a.ub&515)==c&&(d=b+32);else if(97<=b&&122>=b)!!(a.ub&515)==c&&(d=b-32);else if(!!(a.ub&3)==c){if(a=S[b])d=a}else if(a=Ni[b])d=a;return d}k.ih=function(a){this.Lg=a;a||(this.ub&=-256)}; -function Si(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Zi(a,g,!0);a.Tj&&h==P["`"]&&(g=h=27);if(T[g+1E3])if(h+=1E3,2==b.location&&(h+=2E3),Ui(a,h,!1,c)){if(20==g||144==g||145==g)a.dm||(c=e=!0);if(!(c||91!=g&&93!=g))for(var m=0;m=b||97<=b&&122>=b;d>>>=8;){var g=0,h=d&255;224==f||225==f?e.push(f|(c?0:128)):(42==h?a.ub&3||a.ub&512&&b||(g=h):29==h?a.ub&12||(g=h):56==h?a.ub&48||(g=h):e.push(f|(c?0:128)),g&&(c?e.unshift(g):e.push(g|128)))}for(c=0;cd.Nb.length?(d.Nb.push(f),1==d.Nb.length&&d.la&&Fi(d.la,f)):(20==d.Nb.length&&d.Nb.push(255),d.hc("scan code buffer overflow")))}} za(function(){for(var a=y(window.document,"pcjs","keyboard"),b=0;b} data - * @property {number|null} pattern - * @property {number} iCylinder - * @property {number} iHead - * @property {number} iModify - * @property {number} cModify - * - * Every Sector object (once loaded and fully parsed) should have ALL of the following named properties: - * - * 'sector': sector number - * 'length': size of the sector, in bytes - * 'data': array of dwords - * 'pattern': dword pattern to use for empty or partial sectors (or null if sector still needs to be loaded) - * - * initSector() also sets the following properties, to help us quickly identify its location within aDiskData: - * - * iCylinder - * iHead - * - * In addition, we will maintain the following information on a per-sector basis, as sectors are modified: - * - * iModify: index of first modified dword in sector - * cModify: number of modified dwords in sector - * fDirty: true if sector is dirty, false if clean (or cleaning in progress) - * - * fDirty is used in conjunction with "demandrw" disks; it is set to true whenever the sector is modified, and is - * set to false whenever the sector has been sent to the server. If the server write succeeds and fDirty is still - * false, then the sector modifications are removed (cModify is set to zero). If the write succeeds but fDirty was - * set to true again in the meantime, then all the sector modifications (even those that were just written) remain - * in place (since we don't keep track of more than one modification range within a sector). And if the write failed, - * then fDirty is set back to true and again all modifications remain in place; the best we can do is schedule another - * write attempt. - * - * TODO: Perhaps we should also maintain a failure count and stop trying to write sectors that reach a certain - * threshold. Error-handling, as usual, is the thorniest problem. - */ - /** * Disk(controller, drive, mode) * @@ -269,6 +228,57 @@ function Disk(controller, drive, mode) this.setReady(); } +/** + * @class File + * @property {string} sPath + * @property {string} sName + * @property {number} bAttr + * @property {number} cbSize + * @property {Array.} apba + * @property {Disk} disk + */ + +/** + * @class Sector + * @property {number} sector + * @property {number} length + * @property {Array.} data + * @property {number|null} pattern + * @property {number} iCylinder + * @property {number} iHead + * @property {number} iModify + * @property {number} cModify + * + * Every Sector object (once loaded and fully parsed) should have ALL of the following named properties: + * + * 'sector': sector number + * 'length': size of the sector, in bytes + * 'data': array of dwords + * 'pattern': dword pattern to use for empty or partial sectors (or null if sector still needs to be loaded) + * + * initSector() also sets the following properties, to help us quickly identify its location within aDiskData: + * + * iCylinder + * iHead + * + * In addition, we will maintain the following information on a per-sector basis, as sectors are modified: + * + * iModify: index of first modified dword in sector + * cModify: number of modified dwords in sector + * fDirty: true if sector is dirty, false if clean (or cleaning in progress) + * + * fDirty is used in conjunction with "demandrw" disks; it is set to true whenever the sector is modified, and is + * set to false whenever the sector has been sent to the server. If the server write succeeds and fDirty is still + * false, then the sector modifications are removed (cModify is set to zero). If the write succeeds but fDirty was + * set to true again in the meantime, then all the sector modifications (even those that were just written) remain + * in place (since we don't keep track of more than one modification range within a sector). And if the write failed, + * then fDirty is set back to true and again all modifications remain in place; the best we can do is schedule another + * write attempt. + * + * TODO: Perhaps we should also maintain a failure count and stop trying to write sectors that reach a certain + * threshold. Error-handling, as usual, is the thorniest problem. + */ + /** * @class SectorInfo * @property {number} 0 contains iCylinder diff --git a/modules/pcjs/lib/keyboard.js b/modules/pcjs/lib/keyboard.js index 2bc53045e..f94894576 100644 --- a/modules/pcjs/lib/keyboard.js +++ b/modules/pcjs/lib/keyboard.js @@ -2033,12 +2033,22 @@ Keyboard.prototype.onKeyDown = function(event, fDown) */ if (Keyboard.SIMCODES[simCode] && (this.bitsState & (Keyboard.STATE.CTRLS | Keyboard.STATE.ALTS))) { fPass = false; + } else { + /* + * HACK: For all other keys (ie, keys not marked as ONDOWN, and non-CTRL/non-ALT combinations), we're + * going to ignore their down/up events; even though that prevents those keys from being repeated properly + * (ie, at the simulation's repeat rate rather than the browser's repeat rate), it's the safest thing to + * do when dealing with international keyboards, because our mapping tables are designed for US keyboards, + * and testing all the permutations of international keyboards and browsers is more work than I can take + * on now. TODO: Dig into this some day. + */ + fIgnore = true; } /* - * For now, we don't want to simulate any key sequence that has the CMD key associated with it. + * For now, we also don't want to simulate any key sequence that has the CMD key associated with it. */ - fIgnore = !!(this.bitsState & Keyboard.STATE.CMDS); + if (!!(this.bitsState & Keyboard.STATE.CMDS)) fIgnore = true; } if (!fPass) { diff --git a/versions/pcjs/1.16.5/pc-dbg.js b/versions/pcjs/1.16.5/pc-dbg.js index 7861ce92c..ae2e057b3 100644 --- a/versions/pcjs/1.16.5/pc-dbg.js +++ b/versions/pcjs/1.16.5/pc-dbg.js @@ -519,7 +519,7 @@ function Pj(a,b,c,d){if(S[b]){var e=Math.floor(b/1E3)&2;if(b=Jj[b]||0){!e||b&85| function Oj(a,b,c){if(S[b]&&a.T&&a.T.ma.nb){Jj[b]&&a.Rb.length&&0e||(e==a.Rb.length&&(d={},d.ye=b,d.Fb=a.Fb,Rj(a,b,!0),e++),0b.wd){if(!b.mg){Qj(a,b.ye);return}b.mg=!1;c=a.jo}else c=1==b.wd++?a.ko:a.lo;b.vm=setTimeout(function(a){return function(){Sj(a,b)}}(a),c)}}else Qj(a,b.ye,!0)}function Uj(a,b,c){var d=b;if(65<=b&&90>=b)!(a.Fb&515)==c&&(d=b+32);else if(97<=b&&122>=b)!!(a.Fb&515)==c&&(d=b-32);else if(!!(a.Fb&3)==c){if(a=R[b])d=a}else if(a=Ij[b])d=a;return d}k.Uh=function(a){this.xh=a;a||(this.Fb&=-256)}; -function Nj(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Uj(a,g,!0);a.Mk&&h==O["`"]&&(g=h=27);if(S[g+1E3])if(h+=1E3,2==b.location&&(h+=2E3),Pj(a,h,!1,c)){if(20==g||144==g||145==g)a.Vm||(c=e=!0);if(!(c||91!=g&&93!=g))for(var n=0;n=b||97<=b&&122>=b;d>>>=8;){var g=0,h=d&255;224==f||225==f?e.push(f|(c?0:128)):(42==h?a.Fb&3||a.Fb&512&&b||(g=h):29==h?a.Fb&12||(g=h):56==h?a.Fb&48||(g=h):e.push(f|(c?0:128)),g&&(c?e.unshift(g):e.push(g|128)))}for(c=0;cd.Xb.length?(d.ua()&&d.fb("scan code 0x"+q(f)+" buffered"),d.Xb.push(f),1==d.Xb.length&&d.oa&&zj(d.oa, f)):(20==d.Xb.length&&d.Xb.push(255),d.fb("scan code buffer overflow")))}}Ja(function(){for(var a=A(window.document,"pcjs","keyboard"),b=0;be||(e==a.Ib.length&&(d={},d.Xd=b,d.ub=a.ub,Wi(a,b,!0),e++),0b.ad){if(!b.Af){Vi(a,b.Xd);return}b.Af=!1;c=a.nn}else c=1==b.ad++?a.on:a.pn;b.Dl=setTimeout(function(a){return function(){Xi(a,b)}}(a),c)}}else Vi(a,b.Xd,!0)}function Zi(a,b,c){var d=b;if(65<=b&&90>=b)!(a.ub&515)==c&&(d=b+32);else if(97<=b&&122>=b)!!(a.ub&515)==c&&(d=b-32);else if(!!(a.ub&3)==c){if(a=S[b])d=a}else if(a=Ni[b])d=a;return d}k.ih=function(a){this.Lg=a;a||(this.ub&=-256)}; -function Si(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Zi(a,g,!0);a.Tj&&h==P["`"]&&(g=h=27);if(T[g+1E3])if(h+=1E3,2==b.location&&(h+=2E3),Ui(a,h,!1,c)){if(20==g||144==g||145==g)a.dm||(c=e=!0);if(!(c||91!=g&&93!=g))for(var m=0;m=b||97<=b&&122>=b;d>>>=8;){var g=0,h=d&255;224==f||225==f?e.push(f|(c?0:128)):(42==h?a.ub&3||a.ub&512&&b||(g=h):29==h?a.ub&12||(g=h):56==h?a.ub&48||(g=h):e.push(f|(c?0:128)),g&&(c?e.unshift(g):e.push(g|128)))}for(c=0;cd.Nb.length?(d.Nb.push(f),1==d.Nb.length&&d.la&&Fi(d.la,f)):(20==d.Nb.length&&d.Nb.push(255),d.hc("scan code buffer overflow")))}} za(function(){for(var a=y(window.document,"pcjs","keyboard"),b=0;b