Space Invaders works on the desktop now
This commit is contained in:
parent
bc7ec763ca
commit
f09189c121
9 changed files with 269 additions and 116 deletions
|
|
@ -6,7 +6,8 @@ description: >
|
|||
PCjs: The Original IBM PC in a Browser.
|
||||
Classic computer simulations in JavaScript.
|
||||
Includes an archive of historical PC software and publications.
|
||||
Additional computer simulations in JavaScript include the 6502-based Ohio Scientific Challenger 1P.
|
||||
Additional computer simulations in JavaScript include the 6502-based Ohio Scientific Challenger 1P and 8080-based
|
||||
machines, including arcade machines such as Space Invaders.
|
||||
baseurl: "" # "/pcjs" when using http://jeffpar.github.io or "" when using http://www.pcjs.org
|
||||
url: "http://www.pcjs.org" # "http://jeffpar.github.io" or "http://www.pcjs.org"
|
||||
twitter_username: jeffpar
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
</menu>
|
||||
</video>
|
||||
<chipset id="chipset" model="SI1978"/>
|
||||
<keyboard id="keyboard"/>
|
||||
<panel ref="/devices/pc8080/panel/left.xml"/>
|
||||
<debugger id="debugger" commands="s 8086"/>
|
||||
</machine>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ function kd(a,b,c){var d=a.F,e=a.Lb,f=d.Sa.Z,g=d.Sa.Aa;if(!c){if(!(d.Sa.type&512
|
|||
d.oa(h+g)));c&&d.jb(h+0,f);d.Za|=8;return!0}m.save=function(){return[this.Z,this.Aa,this.Ta,this.wb,this.id,this.lc,this.Lb,this.Gc,this.Xb,this.Oc,this.Ba,this.ba,this.R,this.type,this.Zb]};m.restore=function(a){"number"==typeof a?this.load(a):(this.Z=a[0],this.Aa=a[1],this.Ta=a[2],this.wb=a[3],this.id=a[4],this.lc=a[5],this.Lb=a[6],this.Gc=a[7],this.Xb=a[8],this.Oc=a[9]||2,this.Ba=a[10]||65535,this.ba=a[11]||2,this.R=a[12]||65535,this.type=a[13]||this.wb&7936,this.Zb=a[14]||(this.Ta>>>0)+1)};
|
||||
function ed(a,b,c,d){void 0===c&&(c=!!(a.F.Za&1));a.cd=!1;if(c)if(a.load=a.tg,a.Wi=a.fm,a.nc=a.Ci,a.oc=a.Ei,void 0===d&&(d=!!(a.F.ca&131072)),d)a.load=a.V,a.nc=a.ea,a.oc=a.qa,a.Lb=a.Gc=3,a.ba=a.Oc=2,a.R=a.Ba=65535,a.Ta=65535,a.Zb=a.Ta+1,a.Oc=a.ba,a.Xb=-1,a.cf=!1;else{if(!(a.Z&-4))a.nc=a.og,a.oc=a.pg;else if(a.type&4096){6144==(a.type&6656)&&(a.nc=a.og);if(a.type&2048||!(a.type&512))a.oc=a.pg;1024==(a.type&3072)&&(a.nc==a.Ci&&(a.nc=a.Ik),a.oc==a.Ei&&(a.oc=a.Jk),a.cd=!0);b&&6>a.id&&a.Z&-4&&-1!==a.Xb&&
|
||||
(c=a.Xb+5,d=a.F.Qa(c),d&1||a.F.qc(c,d|1))}b&&(a.Lb=a.Z&3,a.Gc=(a.wb&24576)>>13,80386>a.F.ja||!(a.ext&64)?(a.ba=2,a.R=65535):(a.ba=4,a.R=-1),a.Oc=a.ba,a.Ba=a.R)}else a.load=a.lh,a.Wi=a.gm,a.nc=a.Di,a.oc=a.Fi,a.Lb=a.Gc=0,a.Xb=-1,a.cf=!1}
|
||||
function Ad(a){this.ja=a.model||8088;var b=a.stepping;this.Uc=this.ja+(b?ca(b,16):0);b=0;switch(this.ja){default:b=4772727;break;case 80286:b=6E6;break;case 80386:b=16E6}Lc.call(this,a,b);this.Yf=61442;this.Cc=1792;this.Wf=28672;this.Dd=4;this.ra=255;this.B=80286<=this.ja?xb:wb;this.X=Bd;this.bg=Cd;this.gg=Dd;this.hg=Ed;if(80186<=this.ja&&(this.X=Bd.slice(),this.bg=Cd.slice(),this.gg=Dd.slice(),this.ra=31,this.X[15]=Fd,this.X[96]=Gd,this.X[97]=Hd,this.X[98]=Id,this.X[99]=Fd,this.X[100]=Fd,this.X[101]=
|
||||
function Ad(a){this.ja=+a.model||8088;var b=a.stepping;this.Uc=this.ja+(b?ca(b,16):0);b=0;switch(this.ja){default:b=4772727;break;case 80286:b=6E6;break;case 80386:b=16E6}Lc.call(this,a,b);this.Yf=61442;this.Cc=1792;this.Wf=28672;this.Dd=4;this.ra=255;this.B=80286<=this.ja?xb:wb;this.X=Bd;this.bg=Cd;this.gg=Dd;this.hg=Ed;if(80186<=this.ja&&(this.X=Bd.slice(),this.bg=Cd.slice(),this.gg=Dd.slice(),this.ra=31,this.X[15]=Fd,this.X[96]=Gd,this.X[97]=Hd,this.X[98]=Id,this.X[99]=Fd,this.X[100]=Fd,this.X[101]=
|
||||
Fd,this.X[102]=Fd,this.X[103]=Fd,this.X[104]=Jd,this.X[105]=Kd,this.X[106]=Ld,this.X[107]=Md,this.X[108]=Nd,this.X[109]=Od,this.X[110]=Pd,this.X[111]=Qd,this.X[192]=Rd,this.X[193]=Sd,this.X[200]=Td,this.X[201]=Ud,this.X[241]=Yd,this.bg[7]=Zd,this.gg[7]=Zd,80286<=this.ja)){this.Yf=2;this.Cc|=28672;this.Dd=0;this.X[15]=$d;this.tc=ae.slice();for(a=0;a<this.tc.length;a++)this.tc[a]||(this.tc[a]=ge);this.X[84]=he;this.X[99]=ie;if(80386<=this.ja){var c;this.Wf=0;this.Cc|=196608;this.X[100]=je;this.X[101]=
|
||||
ke;this.X[102]=le;this.X[103]=me;for(c in M)this.tc[+c]=M[c];80546<=this.Uc&&80562>=this.Uc&&(this.tc[166]=ne,this.tc[167]=oe)}}this.Id=[];this.le=[];this.ne=0;Oc(this);this.la.Wd=this.la.Mi=!1;this.Pg=0;this.ld=this.sa=[];this.La=this.Sb=this.Fa=this.Gd=this.jd=this.Hb=this.Db=0;pe(this)}db(Ad,Lc);function qe(a,b,c,d){Gc((d?a.ld:a.sa)[b>>>a.La],c);d&&Ub(a)}
|
||||
function re(a){var b;if(a.sa===a.ld){a.sa=Array(a.Gd);a.me=new B(null,0,0,5,null,a);Mb(a.me,a.ha);for(b=0;b<a.Gd;b++)a.sa[b]=a.me;a.kd=new B;a.ag=Array(512);a.oe=0}else for(var c=0;c<a.Hd.length;c++){b=a.Hd[c];var d=a.sa[b];512>a.oe&&(a.ag[a.oe++]=d);a.sa[b]=a.me}a.Hd=[]}function Ub(a){a.Za&-2147483648&&re(a)}
|
||||
|
|
@ -461,7 +461,7 @@ function vm(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Em(a,g,!0);a.bh&&h==X["`"]&&
|
|||
function Dm(a,b,c){var d=!1;xm(a,b,!0,c);var e=Y[b]||Y[b+1E3];if(void 0!==e){14==e&&40==(a.xc&40)&&(e=83);var d=[],f=e&255;if(83<f&&83==a.ra)return!1;d.push(f|(c?0:128));for(b=65<=b&&90>=b||97<=b&&122>=b;e>>>=8;){var g=0,h=e&255;224==f||225==f?d.push(f|(c?0:128)):(42==h?a.C&3||a.C&512&&b||(g=h):29==h?a.C&12||(g=h):56==h?a.C&48||(g=h):d.push(f|(c?0:128)),g&&(c?d.unshift(g):d.push(g|128)))}for(c=0;c<d.length;c++)e=a,f=d[c],e.A&&(20>e.A.length?(A(e)&&y(e,"scan code "+t(f)+" buffered"),e.A.push(f),1==
|
||||
e.A.length&&e.N&&Wl(e.N,f)):(20==e.A.length&&e.A.push(255),y(e,"scan code buffer overflow")));d=!0}return d}Qa(function(){for(var a=nb(document,"pcjs","keyboard"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new mm(d);mb(d,c)}});
|
||||
function Z(a,b,c,d,e){var f=this;this.qf=Ga("Gecko/");var g=["","moz","ms","webkit"];Ua.call(this,"Video",a,Z,262144);this.ja=a.model;var h=Fm[this.ja]||Fm.mda;this.Ua=h[0];this.Ed=a.memory||0;this.bg=a.switches;this.wa=a.mode;if(null==this.wa||null==Gm[this.wa])this.wa=h[1];this.kd=a.charCols;this.le=a.charRows;if(void 0===this.kd||void 0===this.le)this.kd=Gm[this.wa][0],this.le=Gm[this.wa][1];this.ra=a.screenWidth;this.Ea=a.screenHeight;this.Wf=a.scale;this.tn=12<=Math.round(this.ra/this.kd);this.ka=
|
||||
b;this.fa=c;this.V=(this.vk=d)||b||null;b=a.smoothing;(c=Ya.smoothing)&&(b="true"==c?!0:!1);if(null!=b)for(c=0;c<g.length;c++)if(d=(d=g[c])?d+"ImageSmoothingEnabled":"imageSmoothingEnabled",void 0!==this.fa[d]){this.fa[d]=b;break}this.gg=a.touchScreen;this.me=Hm;this.W=null;this.pi=a.autoLock;this.ob=this.ac=0;this.Oa=[];this.Ca=Array(this.Ua==dm?256:16);this.rb=!1;if(this.ia=e)if(this.ia.We=e.requestFullscreen||e.msRequestFullscreen||e.mozRequestFullScreen||e.webkitRequestFullscreen,this.ia.We){for(c=
|
||||
b;this.fa=c;this.V=(this.vk=d)||b||null;b=a.smoothing;(c=Ya.smoothing)&&(b="true"==c);if(null!=b)for(c=0;c<g.length;c++)if(d=(d=g[c])?d+"ImageSmoothingEnabled":"imageSmoothingEnabled",void 0!==this.fa[d]){this.fa[d]=b;break}this.gg=a.touchScreen;this.me=Hm;this.W=null;this.pi=a.autoLock;this.ob=this.ac=0;this.Oa=[];this.Ca=Array(this.Ua==dm?256:16);this.rb=!1;if(this.ia=e)if(this.ia.We=e.requestFullscreen||e.msRequestFullscreen||e.mozRequestFullScreen||e.webkitRequestFullscreen,this.ia.We){for(c=
|
||||
0;c<g.length;c++)if(d=g[c]+"fullscreenchange","on"+d in document){document.addEventListener(d,function(){Im(f,document.fullscreenElement||document.msFullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement?!0:!1)},!1);break}for(c=0;c<g.length;c++)if(d=g[c]+"fullscreenerror","on"+d in document){document.addEventListener(d,function(){Im(f,null)},!1);break}}this.V&&(this.V.onfocus=function(){return f.Gg(!0)},this.V.onblur=function(){return f.Gg(!1)},this.V.De=this.V.requestPointerLock||
|
||||
this.V.mozRequestPointerLock||this.V.webkitRequestPointerLock,this.V.sk=this.V.exitPointerLock||this.V.mozExitPointerLock||this.V.webkitExitPointerLock,this.V.De&&(e=function(){f.Vf(document.pointerLockElement===f.V||document.mozPointerLockElement===f.V||document.webkitPointerLockElement===f.V)},"onpointerlockchange"in document?document.addEventListener("pointerlockchange",e,!1):"onmozpointerlockchange"in document?document.addEventListener("mozpointerlockchange",e,!1):"onwebkitpointerlockchange"in
|
||||
document&&document.addEventListener("webkitpointerlockchange",e,!1)));if(a=a.fontROM)"json"!=ga(a)&&(a=xa()+"/api/v1/dump?file="+a+"&format=bytes"),va(a,null,!0,function(a,b,c){Jm(f,a,b,c)})}db(Z);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ function Ec(a,b,c){var d=a.A,e=a.sb,f=d.ia.ja,g=d.ia.ya;if(!c){if(!(d.ia.type&51
|
|||
v(d,d.fa(h+g)));c&&d.bb(h+0,f);d.Pa|=8;return!0}l.save=function(){return[this.ja,this.ya,this.Za,this.lb,this.id,this.Tf,this.sb,this.nc,this.hc,this.Nc,this.sa,this.U,this.N,this.type,this.C]};l.restore=function(a){"number"==typeof a?this.load(a):(this.ja=a[0],this.ya=a[1],this.Za=a[2],this.lb=a[3],this.id=a[4],this.Tf=a[5],this.sb=a[6],this.nc=a[7],this.hc=a[8],this.Nc=a[9]||2,this.sa=a[10]||65535,this.U=a[11]||2,this.N=a[12]||65535,this.type=a[13]||this.lb&7936,this.C=a[14]||(this.Za>>>0)+1)};
|
||||
function zc(a,b,c,d){void 0===c&&(c=!!(a.A.Pa&1));a.zd=!1;if(c)if(a.load=a.Cf,a.Wh=a.Tk,a.Qb=a.Ih,a.Rb=a.Kh,void 0===d&&(d=!!(a.A.X&131072)),d)a.load=a.L,a.Qb=a.I,a.Rb=a.K,a.sb=a.nc=3,a.U=a.Nc=2,a.N=a.sa=65535,a.Za=65535,a.C=a.Za+1,a.Nc=a.U,a.hc=-1,a.pe=!1;else{if(!(a.ja&-4))a.Qb=a.wf,a.Rb=a.xf;else if(a.type&4096){6144==(a.type&6656)&&(a.Qb=a.wf);if(a.type&2048||!(a.type&512))a.Rb=a.xf;1024==(a.type&3072)&&(a.Qb==a.Ih&&(a.Qb=a.zj),a.Rb==a.Kh&&(a.Rb=a.Aj),a.zd=!0);b&&6>a.id&&a.ja&-4&&-1!==a.hc&&(c=
|
||||
a.hc+5,d=a.A.Kb(c),d&1||a.A.Mc(c,d|1))}b&&(a.sb=a.ja&3,a.nc=(a.lb&24576)>>13,80386>a.A.ca||!(a.ext&64)?(a.U=2,a.N=65535):(a.U=4,a.N=-1),a.Nc=a.U,a.sa=a.N)}else a.load=a.Xh,a.Wh=a.Uk,a.Qb=a.Jh,a.Rb=a.Lh,a.sb=a.nc=0,a.hc=-1,a.pe=!1}
|
||||
function Qc(a){this.ca=a.model||8088;var b=a.stepping;this.pd=this.ca+(b?ca(b,16):0);b=0;switch(this.ca){default:b=4772727;break;case 80286:b=6E6;break;case 80386:b=16E6}hc.call(this,a,b);this.rh=61442;this.od=1792;this.qh=28672;this.ae=4;this.Da=255;this.B=80286<=this.ca?fb:eb;this.ma=Rc;this.uh=Sc;this.vh=Tc;this.wh=Uc;if(80186<=this.ca&&(this.ma=Rc.slice(),this.uh=Sc.slice(),this.vh=Tc.slice(),this.Da=31,this.ma[15]=Vc,this.ma[96]=Wc,this.ma[97]=Xc,this.ma[98]=Yc,this.ma[99]=Vc,this.ma[100]=Vc,
|
||||
function Qc(a){this.ca=+a.model||8088;var b=a.stepping;this.pd=this.ca+(b?ca(b,16):0);b=0;switch(this.ca){default:b=4772727;break;case 80286:b=6E6;break;case 80386:b=16E6}hc.call(this,a,b);this.rh=61442;this.od=1792;this.qh=28672;this.ae=4;this.Da=255;this.B=80286<=this.ca?fb:eb;this.ma=Rc;this.uh=Sc;this.vh=Tc;this.wh=Uc;if(80186<=this.ca&&(this.ma=Rc.slice(),this.uh=Sc.slice(),this.vh=Tc.slice(),this.Da=31,this.ma[15]=Vc,this.ma[96]=Wc,this.ma[97]=Xc,this.ma[98]=Yc,this.ma[99]=Vc,this.ma[100]=Vc,
|
||||
this.ma[101]=Vc,this.ma[102]=Vc,this.ma[103]=Vc,this.ma[104]=Zc,this.ma[105]=$c,this.ma[106]=ad,this.ma[107]=bd,this.ma[108]=cd,this.ma[109]=dd,this.ma[110]=ed,this.ma[111]=fd,this.ma[192]=gd,this.ma[193]=hd,this.ma[200]=id,this.ma[201]=jd,this.ma[241]=kd,this.uh[7]=ld,this.vh[7]=ld,80286<=this.ca)){this.rh=2;this.od|=28672;this.ae=0;this.ma[15]=md;this.Zc=nd.slice();for(a=0;a<this.Zc.length;a++)this.Zc[a]||(this.Zc[a]=od);this.ma[84]=pd;this.ma[99]=qd;if(80386<=this.ca){var c;this.qh=0;this.od|=
|
||||
196608;this.ma[100]=rd;this.ma[101]=td;this.ma[102]=ud;this.ma[103]=vd;for(c in B)this.Zc[+c]=B[c];80546<=this.pd&&80562>=this.pd&&(this.Zc[166]=wd,this.Zc[167]=xd)}}this.of=[];this.th=[];this.Vf=0;kc(this);this.da.Le=this.da.Hj=!1;this.yh=0;this.vc=this.S=[];this.ea=this.xb=this.pb=this.mf=this.Yd=this.Fa=this.oc=0;yd(this)}Qa(Qc,hc);
|
||||
function Bb(a){var b;if(a.S===a.vc){a.S=Array(a.mf);a.pf=new q(null,0,0,5,null,a);sb(a.pf,a.Ia);for(b=0;b<a.mf;b++)a.S[b]=a.pf;a.Zd=new q;a.sh=Array(512);a.qf=0}else for(var c=0;c<a.nf.length;c++){b=a.nf[c];var d=a.S[b];512>a.qf&&(a.sh[a.qf++]=d);a.S[b]=a.pf}a.nf=[]}
|
||||
|
|
@ -433,10 +433,10 @@ function vk(a,b,c){var d=!0,e=!1,f=!1,g=b.keyCode,h=Ek(a,g,!0);a.ig&&h==U["`"]&&
|
|||
function Dk(a,b,c){var d=!1;xk(a,b,!0,c);var e=X[b]||X[b+1E3];if(void 0!==e){14==e&&40==(a.bc&40)&&(e=83);var d=[],f=e&255;if(83<f&&83==a.Z)return!1;d.push(f|(c?0:128));for(b=65<=b&&90>=b||97<=b&&122>=b;e>>>=8;){var g=0,h=e&255;224==f||225==f?d.push(f|(c?0:128)):(42==h?a.C&3||a.C&512&&b||(g=h):29==h?a.C&12||(g=h):56==h?a.C&48||(g=h):d.push(f|(c?0:128)),g&&(c?d.unshift(g):d.push(g|128)))}for(c=0;c<d.length;c++)e=a,f=d[c],e.Pb&&(20>e.Pb.length?(e.Pb.push(f),1==e.Pb.length&&e.R&&Yj(e.R,f)):20==e.Pb.length&&
|
||||
e.Pb.push(255));d=!0}return d}Ea(function(){for(var a=Za(document,"pcjs","keyboard"),b=0;b<a.length;b++){var c=a[b],d=Wa(c),d=new nk(d);Ya(d,c)}});
|
||||
function Y(a,b,c,d,e){var f=this;this.$c=ya("Gecko/");var g=["","moz","ms","webkit"];Ia.call(this,"Video",a,Y);this.ca=a.model;var h=Fk[this.ca]||Fk.mda;this.Ra=h[0];this.Wc=a.memory||0;this.qd=a.switches;this.la=a.mode;if(null==this.la||null==Gk[this.la])this.la=h[1];this.Ob=a.charCols;this.wc=a.charRows;if(void 0===this.Ob||void 0===this.wc)this.Ob=Gk[this.la][0],this.wc=Gk[this.la][1];this.ea=a.screenWidth;this.pa=a.screenHeight;this.dd=a.scale;this.Zd=12<=Math.round(this.ea/this.Ob);this.Y=b;
|
||||
this.P=c;this.G=(this.ae=d)||b||null;b=a.smoothing;(c=La.smoothing)&&(b="true"==c?!0:!1);if(null!=b)for(c=0;c<g.length;c++)if(d=(d=g[c])?d+"ImageSmoothingEnabled":"imageSmoothingEnabled",void 0!==this.P[d]){this.P[d]=b;break}this.rd=a.touchScreen;this.xc=Hk;this.K=null;this.Yd=a.autoLock;this.cb=this.Fb=0;this.xa=[];this.oa=Array(this.Ra==ek?256:16);this.La=!1;if(this.W=e)if(this.W.ke=e.requestFullscreen||e.msRequestFullscreen||e.mozRequestFullScreen||e.webkitRequestFullscreen,this.W.ke){for(c=0;c<
|
||||
g.length;c++)if(d=g[c]+"fullscreenchange","on"+d in document){document.addEventListener(d,function(){Ik(f,document.fullscreenElement||document.msFullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement?!0:!1)},!1);break}for(c=0;c<g.length;c++)if(d=g[c]+"fullscreenerror","on"+d in document){document.addEventListener(d,function(){Ik(f,null)},!1);break}}this.G&&(this.G.onfocus=function(){return f.Nf(!0)},this.G.onblur=function(){return f.Nf(!1)},this.G.Pd=this.G.requestPointerLock||
|
||||
this.G.mozRequestPointerLock||this.G.webkitRequestPointerLock,this.G.pj=this.G.exitPointerLock||this.G.mozExitPointerLock||this.G.webkitExitPointerLock,this.G.Pd&&(e=function(){f.bf(document.pointerLockElement===f.G||document.mozPointerLockElement===f.G||document.webkitPointerLockElement===f.G)},"onpointerlockchange"in document?document.addEventListener("pointerlockchange",e,!1):"onmozpointerlockchange"in document?document.addEventListener("mozpointerlockchange",e,!1):"onwebkitpointerlockchange"in
|
||||
document&&document.addEventListener("webkitpointerlockchange",e,!1)));if(a=a.fontROM)"json"!=ga(a)&&(a=qa()+"/api/v1/dump?file="+a+"&format=bytes"),pa(a,null,!0,function(a,b,c){Jk(f,a,b,c)})}Qa(Y);
|
||||
this.P=c;this.G=(this.ae=d)||b||null;b=a.smoothing;(c=La.smoothing)&&(b="true"==c);if(null!=b)for(c=0;c<g.length;c++)if(d=(d=g[c])?d+"ImageSmoothingEnabled":"imageSmoothingEnabled",void 0!==this.P[d]){this.P[d]=b;break}this.rd=a.touchScreen;this.xc=Hk;this.K=null;this.Yd=a.autoLock;this.cb=this.Fb=0;this.xa=[];this.oa=Array(this.Ra==ek?256:16);this.La=!1;if(this.W=e)if(this.W.ke=e.requestFullscreen||e.msRequestFullscreen||e.mozRequestFullScreen||e.webkitRequestFullscreen,this.W.ke){for(c=0;c<g.length;c++)if(d=
|
||||
g[c]+"fullscreenchange","on"+d in document){document.addEventListener(d,function(){Ik(f,document.fullscreenElement||document.msFullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement?!0:!1)},!1);break}for(c=0;c<g.length;c++)if(d=g[c]+"fullscreenerror","on"+d in document){document.addEventListener(d,function(){Ik(f,null)},!1);break}}this.G&&(this.G.onfocus=function(){return f.Nf(!0)},this.G.onblur=function(){return f.Nf(!1)},this.G.Pd=this.G.requestPointerLock||this.G.mozRequestPointerLock||
|
||||
this.G.webkitRequestPointerLock,this.G.pj=this.G.exitPointerLock||this.G.mozExitPointerLock||this.G.webkitExitPointerLock,this.G.Pd&&(e=function(){f.bf(document.pointerLockElement===f.G||document.mozPointerLockElement===f.G||document.webkitPointerLockElement===f.G)},"onpointerlockchange"in document?document.addEventListener("pointerlockchange",e,!1):"onmozpointerlockchange"in document?document.addEventListener("mozpointerlockchange",e,!1):"onwebkitpointerlockchange"in document&&document.addEventListener("webkitpointerlockchange",
|
||||
e,!1)));if(a=a.fontROM)"json"!=ga(a)&&(a=qa()+"/api/v1/dump?file="+a+"&format=bytes"),pa(a,null,!0,function(a,b,c){Jk(f,a,b,c)})}Qa(Y);
|
||||
var ek=7,Fk={mda:[1,7],cga:[3,3],ega:[5,3],vga:[ek,3]},Kk={2:{Jf:15700,If:208,Of:85,Pf:96},3:{Jf:18432,If:364,Of:85,Pf:96},4:{Jf:21850,If:364,Of:85,Pf:96},7:{Jf:16700,If:480,Of:85,Pf:83}},Lk={6:[1,3,!0],7:[2,3,!0],8:[6,3,!0],9:[4,3,!0],10:[3,1,!0],11:[3,2,!0],0:[1,3,!1],1:[2,3,!1],2:[6,3,!1],3:[4,3,!1],4:[3,1,!1],5:[3,2,!1]},Gk=[,[40,25,1,0,3],,[80,25,1,0,3],[320,200,8,192],,[640,200,16,192],[80,25,1,0,1]];Gk[13]=[320,200,8];Gk[14]=[640,200,8];Gk[15]=[640,350,8];Gk[16]=[640,350,8];
|
||||
Gk[17]=[640,480,8];Gk[18]=[640,480,8];Gk[19]=[320,200,1];Gk[20]=[320,240,4];Gk[21]=[320,400,4];Gk[0]=Gk[1];Gk[2]=Gk[3];Gk[5]=Gk[4];
|
||||
var Mk=[[0,0,0,255],[127,192,127,255],[127,192,127,255],[127,255,127,255],[127,255,127,255]],Nk=[0,1,2,2,2,2,2,2,0,3,4,4,4,4,4,4],Ok=[[0,0,0,255],[0,0,170,255],[0,170,0,255],[0,170,170,255],[170,0,0,255],[170,0,170,255],[170,85,0,255],[170,170,170,255],[85,85,85,255],[85,85,255,255],[85,255,85,255],[85,255,255,255],[255,85,85,255],[255,85,255,255],[255,255,85,255],[255,255,255,255]],Pk=[2,4,6],Qk=[3,5,7],Rk=[0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63],Sk=[0,255,65280,65535,16711680,16711935,16776960,
|
||||
|
|
|
|||
|
|
@ -107,24 +107,24 @@ Component.subclass(ChipSet);
|
|||
|
||||
ChipSet.SI_1978 = {
|
||||
MODEL: 1978.1,
|
||||
STATUS0: {
|
||||
STATUS0: { // NOTE: STATUS0 not used by the SI_1978 ROMs; refer to STATUS1 instead
|
||||
PORT: 0,
|
||||
DIP4: 0x01, // self-test request at power up?
|
||||
ALWAYS_SET: 0x0E, // always set
|
||||
FIRE: 0x10, // 1 = fire
|
||||
LEFT: 0x20, // 1 = move left
|
||||
RIGHT: 0x40, // 1 = move right
|
||||
PORT7: 0x80 // some connection to (undocumented) port 7
|
||||
LEFT: 0x20, // 1 = left
|
||||
RIGHT: 0x40, // 1 = right
|
||||
PORT7: 0x80, // some connection to (undocumented) port 7
|
||||
ALWAYS_SET: 0x0E // always set
|
||||
},
|
||||
STATUS1: {
|
||||
PORT: 1,
|
||||
CREDIT: 0x01, // credit (coin slot)
|
||||
P2: 0x02, // 1 = 2P start
|
||||
P1: 0x04, // 1 = 1P start
|
||||
ALWAYS_SET: 0x08, // always set
|
||||
P1_FIRE: 0x10, // 1 = P1 fire (cocktail machines only?)
|
||||
P1_LEFT: 0x20, // 1 = P1 left (cocktail machines only?)
|
||||
P1_RIGHT: 0x40 // 1 = P1 right (cocktail machines only?)
|
||||
P1_FIRE: 0x10, // 1 = fire (P1 fire if cocktail machine?)
|
||||
P1_LEFT: 0x20, // 1 = left (P1 left if cocktail machine?)
|
||||
P1_RIGHT: 0x40, // 1 = right (P1 right if cocktail machine?)
|
||||
ALWAYS_SET: 0x08 // always set
|
||||
},
|
||||
STATUS2: {
|
||||
PORT: 2,
|
||||
|
|
@ -134,7 +134,8 @@ ChipSet.SI_1978 = {
|
|||
P2_FIRE: 0x10, // 1 = P2 fire (cocktail machines only?)
|
||||
P2_LEFT: 0x20, // 1 = P2 left (cocktail machines only?)
|
||||
P2_RIGHT: 0x40, // 1 = P2 right (cocktail machines only?)
|
||||
DIP7: 0x80 // 0 = display coin info on demo ("attract") screen
|
||||
DIP7: 0x80, // 0 = display coin info on demo ("attract") screen
|
||||
ALWAYS_SET: 0x00
|
||||
},
|
||||
SHIFT_RESULT: { // bits 0-7 of barrel shifter result
|
||||
PORT: 3
|
||||
|
|
@ -273,9 +274,9 @@ ChipSet.prototype.powerDown = function(fSave, fShutdown)
|
|||
*/
|
||||
ChipSet.prototype.reset = function()
|
||||
{
|
||||
this.bStatus0 = 0;
|
||||
this.bStatus1 = 0;
|
||||
this.bStatus2 = 0;
|
||||
this.bStatus0 = ChipSet.SI_1978.STATUS0.ALWAYS_SET;
|
||||
this.bStatus1 = ChipSet.SI_1978.STATUS1.ALWAYS_SET;
|
||||
this.bStatus2 = ChipSet.SI_1978.STATUS2.ALWAYS_SET;
|
||||
this.wShiftData = 0;
|
||||
this.bShiftCount = 0;
|
||||
this.bSound1 = this.bSound2 = 0;
|
||||
|
|
@ -351,6 +352,45 @@ ChipSet.prototype.stop = function()
|
|||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus0(bit, fSet)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} bit
|
||||
* @param {boolean} fSet
|
||||
*/
|
||||
ChipSet.prototype.updateStatus0 = function(bit, fSet)
|
||||
{
|
||||
this.bStatus0 &= ~bit;
|
||||
if (fSet) this.bStatus0 |= bit;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus1(bit, fSet)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} bit
|
||||
* @param {boolean} fSet
|
||||
*/
|
||||
ChipSet.prototype.updateStatus1 = function(bit, fSet)
|
||||
{
|
||||
this.bStatus1 &= ~bit;
|
||||
if (fSet) this.bStatus1 |= bit;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus2(bit, fSet)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} bit
|
||||
* @param {boolean} fSet
|
||||
*/
|
||||
ChipSet.prototype.updateStatus2 = function(bit, fSet)
|
||||
{
|
||||
this.bStatus2 &= ~bit;
|
||||
if (fSet) this.bStatus2 |= bit;
|
||||
};
|
||||
|
||||
/**
|
||||
* inSIStatus0(port, addrFrom)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,8 +37,7 @@ if (NODE) {
|
|||
var web = require("../../shared/lib/weblib");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var Messages = require("./messages");
|
||||
var State = require("./state");
|
||||
var CPU = require("./cpu");
|
||||
var ChipSet = require("./chipset");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +51,8 @@ function Keyboard(parmsKbd)
|
|||
{
|
||||
Component.call(this, "Keyboard", parmsKbd, Keyboard, Messages.KEYBOARD);
|
||||
|
||||
this.reset();
|
||||
|
||||
this.setReady();
|
||||
}
|
||||
|
||||
|
|
@ -122,6 +123,16 @@ Keyboard.KEYCODE = {
|
|||
/* 0x2E */ DEL: 46,
|
||||
/* 0x2E */ FF_PERIOD: 46,
|
||||
/* 0x2F */ FF_SLASH: 47,
|
||||
/* 0x30 */ ZERO: 48,
|
||||
/* 0x31 */ ONE: 49,
|
||||
/* 0x32 */ TWO: 50,
|
||||
/* 0x33 */ THREE: 51,
|
||||
/* 0x34 */ FOUR: 52,
|
||||
/* 0x35 */ FIVE: 53,
|
||||
/* 0x36 */ SIX: 54,
|
||||
/* 0x37 */ SEVEN: 55,
|
||||
/* 0x38 */ EIGHT: 56,
|
||||
/* 0x39 */ NINE: 57,
|
||||
/* 0x3B */ FF_SEMI: 59,
|
||||
/* 0x3D */ FF_EQUALS: 61,
|
||||
/* 0x5B */ CMD: 91, // aka WIN
|
||||
|
|
@ -210,6 +221,62 @@ Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.RBRACK] = Keyboard.ASCII[']']; // 2
|
|||
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.QUOTE] = Keyboard.ASCII["'"]; // 222 -> 39
|
||||
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.FF_DASH] = Keyboard.ASCII['-'];
|
||||
|
||||
/**
|
||||
* Maps SOFTCODE (string) to KEYCODE (number).
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
Keyboard.SOFTCODES = {
|
||||
'1p': Keyboard.KEYCODE.ONE,
|
||||
'2p': Keyboard.KEYCODE.TWO,
|
||||
'coin': Keyboard.KEYCODE.FIVE,
|
||||
'left': Keyboard.KEYCODE.LEFT,
|
||||
'right': Keyboard.KEYCODE.RIGHT,
|
||||
'fire': Keyboard.KEYCODE.SPACE
|
||||
};
|
||||
|
||||
/**
|
||||
* Alternate keyCode mappings (to support the popular WASD directional mappings)
|
||||
*
|
||||
* TODO: ES6 computed property name support may now be in all mainstream browsers, allowing us to use
|
||||
* a simple object literal for this and all other object initializations.
|
||||
*/
|
||||
Keyboard.ALTCODES = {};
|
||||
Keyboard.ALTCODES[Keyboard.ASCII.A] = Keyboard.KEYCODE.LEFT;
|
||||
Keyboard.ALTCODES[Keyboard.ASCII.D] = Keyboard.KEYCODE.RIGHT;
|
||||
Keyboard.ALTCODES[Keyboard.ASCII.L] = Keyboard.KEYCODE.SPACE;
|
||||
|
||||
/**
|
||||
* getSoftCode(keyCode)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @return {string|null}
|
||||
*/
|
||||
Keyboard.prototype.getSoftCode = function(keyCode)
|
||||
{
|
||||
keyCode = Keyboard.ALTCODES[keyCode] || keyCode;
|
||||
for (var sSoftCode in Keyboard.SOFTCODES) {
|
||||
if (Keyboard.SOFTCODES[sSoftCode] === keyCode) {
|
||||
return sSoftCode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* reset()
|
||||
*
|
||||
* @this {Keyboard}
|
||||
*/
|
||||
Keyboard.prototype.reset = function()
|
||||
{
|
||||
/*
|
||||
* As SOFTCODE keyDown events are encountered, a corresponding property is set to true in
|
||||
* keysPressed, and as SOFTCODE keyUp events are encountered, the property is set to false.
|
||||
*/
|
||||
this.keysPressed = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* setBinding(sHTMLType, sBinding, control, sValue)
|
||||
*
|
||||
|
|
@ -257,68 +324,24 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
control.onkeydown = function onKeyDown(event) {
|
||||
return kbd.onKeyDown(event, true);
|
||||
};
|
||||
control.onkeypress = function onKeyPressKbd(event) {
|
||||
return kbd.onKeyPress(event);
|
||||
};
|
||||
control.onkeyup = function onKeyUp(event) {
|
||||
return kbd.onKeyDown(event, false);
|
||||
};
|
||||
return true;
|
||||
|
||||
case "caps-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickCapsLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleCapsLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
case "num-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickNumLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleNumLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
case "scroll-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickScrollLock(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleScrollLock();
|
||||
};
|
||||
return true;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Maintain support for older button codes; eg, map button code "ctrl-c" to CLICKCODE "CTRL_C"
|
||||
*/
|
||||
var sCode = sBinding.toUpperCase().replace(/-/g, '_');
|
||||
if (Keyboard.CLICKCODES[sCode] !== undefined && sHTMLType == "button") {
|
||||
if (Keyboard.SOFTCODES[sBinding] !== undefined) {
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function(kbd, sKey, simCode) {
|
||||
return function onClickKeyboard(event) {
|
||||
if (!COMPILED && kbd.messageEnabled()) kbd.printMessage(sKey + " clicked", Messages.KEYS);
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
kbd.updateShiftState(simCode, true); // future-proofing if/when any LOCK keys are added to CLICKCODES
|
||||
kbd.addActiveKey(simCode, true);
|
||||
};
|
||||
}(this, sCode, Keyboard.CLICKCODES[sCode]);
|
||||
return true;
|
||||
}
|
||||
else if (Keyboard.SOFTCODES[sBinding] !== undefined) {
|
||||
this.cSoftCodes++;
|
||||
this.bindings[id] = control;
|
||||
var fnDown = function(kbd, sKey, simCode) {
|
||||
var fnDown = function(kbd, sSoftCode) {
|
||||
return function onMouseOrTouchDownKeyboard(event) {
|
||||
kbd.addActiveKey(simCode);
|
||||
kbd.onSoftKeyDown(sSoftCode, true);
|
||||
};
|
||||
}(this, sBinding, Keyboard.SOFTCODES[sBinding]);
|
||||
var fnUp = function (kbd, sKey, simCode) {
|
||||
}(this, sBinding);
|
||||
var fnUp = function (kbd, sSoftCode) {
|
||||
return function onMouseOrTouchUpKeyboard(event) {
|
||||
kbd.removeActiveKey(simCode);
|
||||
kbd.onSoftKeyDown(sSoftCode, false);
|
||||
};
|
||||
}(this, sBinding, Keyboard.SOFTCODES[sBinding]);
|
||||
}(this, sBinding);
|
||||
if ('ontouchstart' in window) {
|
||||
control.ontouchstart = fnDown;
|
||||
control.ontouchend = fnUp;
|
||||
|
|
@ -328,19 +351,92 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
else if (sValue) {
|
||||
/*
|
||||
* Instead of just having a dedicated "test" control, we now treat any unrecognized control with
|
||||
* a data value as a test control. The only caveat is that such controls must have binding IDs that
|
||||
* do not conflict with predefined controls (which, of course, is the only way you can get here).
|
||||
*/
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickTest(event) {
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.injectKeys(sValue);
|
||||
};
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* initBus(cmp, bus, cpu, dbg)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {Computer} cmp
|
||||
* @param {Bus} bus
|
||||
* @param {CPUState} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
{
|
||||
this.dbg = dbg; // NOTE: The "dbg" property must be set for the message functions to work
|
||||
this.chipset = cmp.getMachineComponent("ChipSet");
|
||||
};
|
||||
|
||||
/**
|
||||
* onKeyDown(event, fDown)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {Object} event
|
||||
* @param {boolean} fDown is true for a keyDown event, false for a keyUp event
|
||||
* @return {boolean} true to pass the event along, false to consume it
|
||||
*/
|
||||
Keyboard.prototype.onKeyDown = function(event, fDown)
|
||||
{
|
||||
var fPass = true;
|
||||
var keyCode = event.keyCode;
|
||||
var sSoftCode = this.getSoftCode(keyCode);
|
||||
|
||||
if (sSoftCode) {
|
||||
fPass = this.onSoftKeyDown(sSoftCode, fDown);
|
||||
}
|
||||
|
||||
if (!fPass) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
|
||||
this.printMessage("onKey" + (fDown? "Down" : "Up") + "(" + keyCode + "): " + (fPass? "true" : "false"), true);
|
||||
}
|
||||
|
||||
return fPass;
|
||||
};
|
||||
|
||||
/**
|
||||
* onSoftKeyDown(sSoftCode, fDown)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {string} sSoftCode
|
||||
* @param {boolean} fDown is true for a down event, false for an up event
|
||||
* @return {boolean} true to pass the event along, false to consume it
|
||||
*/
|
||||
Keyboard.prototype.onSoftKeyDown = function(sSoftCode, fDown)
|
||||
{
|
||||
this.keysPressed[sSoftCode] = fDown;
|
||||
|
||||
if (this.chipset) {
|
||||
switch(sSoftCode) {
|
||||
case '1p':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.P1, fDown);
|
||||
break;
|
||||
|
||||
case '2p':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.P2, fDown);
|
||||
break;
|
||||
|
||||
case 'coin':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.CREDIT, fDown);
|
||||
break;
|
||||
|
||||
case 'left':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.P1_LEFT, fDown);
|
||||
break;
|
||||
|
||||
case 'right':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.P1_RIGHT, fDown);
|
||||
break;
|
||||
|
||||
case 'fire':
|
||||
this.chipset.updateStatus1(ChipSet.SI_1978.STATUS1.P1_FIRE, fDown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@ Video.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.nPixelsPerCell = (16 / this.nBitsPerPixel)|0;
|
||||
this.initCache();
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have an associated keyboard, then ensure that the keyboard will be notified whenever the canvas
|
||||
* gets focus and receives input.
|
||||
*/
|
||||
this.kbd = cmp.getMachineComponent("Keyboard");
|
||||
if (this.kbd && this.canvasScreen) {
|
||||
this.kbd.setBinding(this.textareaScreen? "textarea" : "canvas", "kbd", this.inputScreen);
|
||||
}
|
||||
|
||||
this.setReady();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -566,6 +566,11 @@ Keyboard.KEYSTATES[Keyboard.SIMCODE.SCROLL_LOCK] = Keyboard.STATE.SCROLL_LOCK;
|
|||
/**
|
||||
* Maps CLICKCODE (string) to SIMCODE (number).
|
||||
*
|
||||
* NOTE: Unlike SOFTCODES, CLICKCODES are upper-case and use underscores instead of dashes, so that this
|
||||
* and other components can reference them using "dot" property syntax; using upper-case merely adheres to
|
||||
* our convention for constants. setBinding() will automatically convert any incoming CLICKCODE bindings
|
||||
* that use lower-case and dashes to upper-case and underscores before performing property lookup.
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
Keyboard.CLICKCODES = {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ function Video(parmsVideo, canvas, context, textarea, container)
|
|||
*/
|
||||
var fSmoothing = parmsVideo['smoothing'];
|
||||
var sSmoothing = Component.parmsURL['smoothing'];
|
||||
if (sSmoothing) fSmoothing = (sSmoothing == "true")? true : false;
|
||||
if (sSmoothing) fSmoothing = (sSmoothing == "true");
|
||||
if (fSmoothing != null) {
|
||||
for (i = 0; i < asWebPrefixes.length; i++) {
|
||||
sEvent = asWebPrefixes[i];
|
||||
|
|
@ -4560,8 +4560,8 @@ Video.prototype.removeCursor = function()
|
|||
/*
|
||||
* If we're using an off-screen buffer in text mode, then we need to keep it in sync with "reality".
|
||||
*/
|
||||
if (this.contextScreenBuffer) {
|
||||
this.updateChar(col, row, data, this.contextScreenBuffer);
|
||||
if (this.contextBuffer) {
|
||||
this.updateChar(col, row, data, this.contextBuffer);
|
||||
}
|
||||
/*
|
||||
* While updating the on-screen canvas directly could open us up to potential subpixel artifacts again,
|
||||
|
|
@ -4856,11 +4856,11 @@ Video.prototype.setDimensions = function()
|
|||
}
|
||||
|
||||
/*
|
||||
* In text modes, we have the option of setting all the *ScreenBuffer variables to null instead of
|
||||
* In text modes, we have the option of setting all the *Buffer variables to null instead of
|
||||
* allocating them, because updateChar(), as currently written, is capable of writing characters to
|
||||
* either an off-screen or on-screen context.
|
||||
*
|
||||
* this.imageScreenBuffer = this.canvasScreenBuffer = this.contextScreenBuffer = null;
|
||||
* this.imageBuffer = this.canvasBuffer = this.contextBuffer = null;
|
||||
*/
|
||||
this.cxBuffer = this.cyBuffer = 0;
|
||||
if (font) {
|
||||
|
|
@ -4888,11 +4888,11 @@ Video.prototype.setDimensions = function()
|
|||
/*
|
||||
* Allocate the off-screen buffers
|
||||
*/
|
||||
this.imageScreenBuffer = this.contextScreen.createImageData(this.cxBuffer, this.cyBuffer);
|
||||
this.canvasScreenBuffer = document.createElement("canvas");
|
||||
this.canvasScreenBuffer.width = this.cxBuffer;
|
||||
this.canvasScreenBuffer.height = this.cyBuffer;
|
||||
this.contextScreenBuffer = this.canvasScreenBuffer.getContext("2d");
|
||||
this.imageBuffer = this.contextScreen.createImageData(this.cxBuffer, this.cyBuffer);
|
||||
this.canvasBuffer = document.createElement("canvas");
|
||||
this.canvasBuffer.width = this.cxBuffer;
|
||||
this.canvasBuffer.height = this.cyBuffer;
|
||||
this.contextBuffer = this.canvasBuffer.getContext("2d");
|
||||
|
||||
/*
|
||||
* Since cxCell and cyCell were originally defined in terms of cxScreen/nCols and cyScreen/nRows, you might think
|
||||
|
|
@ -5676,7 +5676,7 @@ Video.prototype.updateScreenText = function(addrScreen, addrScreenLimit, iCell,
|
|||
if (!this.fCellCacheValid || data !== this.aCellCache[iCell]) {
|
||||
var col = iCell % this.nCols;
|
||||
var row = (iCell / this.nCols)|0;
|
||||
this.updateChar(col, row, data, this.contextScreenBuffer);
|
||||
this.updateChar(col, row, data, this.contextBuffer);
|
||||
this.aCellCache[iCell] = data;
|
||||
cUpdated++;
|
||||
}
|
||||
|
|
@ -5686,8 +5686,8 @@ Video.prototype.updateScreenText = function(addrScreen, addrScreenLimit, iCell,
|
|||
|
||||
this.fCellCacheValid = true;
|
||||
|
||||
if (cUpdated && this.contextScreenBuffer) {
|
||||
this.contextScreen.drawImage(this.canvasScreenBuffer, 0, 0, this.cxBuffer, this.cyBuffer, this.xScreenOffset, this.yScreenOffset, this.cxScreenOffset, this.cyScreenOffset);
|
||||
if (cUpdated && this.contextBuffer) {
|
||||
this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.cxBuffer, this.cyBuffer, this.xScreenOffset, this.yScreenOffset, this.cxScreenOffset, this.cyScreenOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -5725,7 +5725,7 @@ Video.prototype.updateScreenGraphicsCGA = function(addrScreen, addrScreenLimit)
|
|||
if (x < xDirty) xDirty = x;
|
||||
for (var iPixel = 0; iPixel < nPixelsPerCell; iPixel++) {
|
||||
var bPixel = (wPixels & (wMask >>= nPixelShift)) >> (nShift -= nPixelShift);
|
||||
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]);
|
||||
this.setPixel(this.imageBuffer, x++, y, aPixelColors[bPixel]);
|
||||
}
|
||||
if (x > xMaxDirty) xMaxDirty = x;
|
||||
if (y < yDirty) yDirty = y;
|
||||
|
|
@ -5748,30 +5748,30 @@ Video.prototype.updateScreenGraphicsCGA = function(addrScreen, addrScreenLimit)
|
|||
this.fCellCacheValid = true;
|
||||
|
||||
/*
|
||||
* Instead of blasting the ENTIRE imageScreenBuffer into contextScreenBuffer, and then blasting the ENTIRE
|
||||
* canvasScreenBuffer onto contextScreen, even for the smallest change, let's try to be a bit smarter about
|
||||
* Instead of blasting the ENTIRE imageBuffer into contextBuffer, and then blasting the ENTIRE
|
||||
* canvasBuffer onto contextScreen, even for the smallest change, let's try to be a bit smarter about
|
||||
* the update (well, to the extent that the canvas APIs permit).
|
||||
*/
|
||||
if (xDirty < this.nCols) {
|
||||
var cxDirty = xMaxDirty - xDirty;
|
||||
var cyDirty = yMaxDirty - yDirty;
|
||||
// this.contextScreenBuffer.putImageData(this.imageScreenBuffer, 0, 0);
|
||||
this.contextScreenBuffer.putImageData(this.imageScreenBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
// this.contextBuffer.putImageData(this.imageBuffer, 0, 0);
|
||||
this.contextBuffer.putImageData(this.imageBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
/*
|
||||
* While ideally I would draw only the dirty portion of canvasScreenBuffer, there usually isn't a 1-1 pixel mapping
|
||||
* between canvasScreenBuffer and contextScreen. In fact, the WHOLE POINT of the canvasScreenBuffer is to leverage
|
||||
* While ideally I would draw only the dirty portion of canvasBuffer, there usually isn't a 1-1 pixel mapping
|
||||
* between canvasBuffer and contextScreen. In fact, the WHOLE POINT of the canvasBuffer is to leverage
|
||||
* drawImage()'s scaling ability; for example, a CGA graphics mode might be 640x200, whereas the canvas representing
|
||||
* the screen might be 960x400. In those situations, if we draw interior rectangles, we often end up with subpixel
|
||||
* artifacts along the edges of those rectangles. So it appears I must continue to redraw the entire canvasScreenBuffer
|
||||
* artifacts along the edges of those rectangles. So it appears I must continue to redraw the entire canvasBuffer
|
||||
* on every change.
|
||||
*
|
||||
var xScreen = (((xDirty * this.cxScreen) / this.nCols) | 0);
|
||||
var yScreen = (((yDirty * this.cyScreen) / this.nRows) | 0);
|
||||
var cxScreen = (((cxDirty * this.cxScreen) / this.nCols) | 0);
|
||||
var cyScreen = (((cyDirty * this.cyScreen) / this.nRows) | 0);
|
||||
this.contextScreen.drawImage(this.canvasScreenBuffer, xDirty, yDirty, cxDirty, cyDirty, xScreen, yScreen, cxScreen, cyScreen);
|
||||
this.contextScreen.drawImage(this.canvasBuffer, xDirty, yDirty, cxDirty, cyDirty, xScreen, yScreen, cxScreen, cyScreen);
|
||||
*/
|
||||
this.contextScreen.drawImage(this.canvasScreenBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -5863,7 +5863,7 @@ Video.prototype.updateScreenGraphicsEGA = function(addrBuffer, addrScreen, addrS
|
|||
* index, which is what this code requires.
|
||||
*/
|
||||
var bPixel = Video.aEGADWToByte[dwPixel] || 0;
|
||||
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]);
|
||||
this.setPixel(this.imageBuffer, x++, y, aPixelColors[bPixel]);
|
||||
data <<= 1;
|
||||
}
|
||||
if (x > xMaxDirty) xMaxDirty = x;
|
||||
|
|
@ -5888,8 +5888,8 @@ Video.prototype.updateScreenGraphicsEGA = function(addrBuffer, addrScreen, addrS
|
|||
if (xDirty < this.nCols) {
|
||||
var cxDirty = xMaxDirty - xDirty;
|
||||
var cyDirty = yMaxDirty - yDirty;
|
||||
this.contextScreenBuffer.putImageData(this.imageScreenBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
this.contextScreen.drawImage(this.canvasScreenBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
this.contextBuffer.putImageData(this.imageBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -5957,7 +5957,7 @@ Video.prototype.updateScreenGraphicsVGA = function(addrBuffer, addrScreen, addrS
|
|||
if (nPixels) {
|
||||
if (x < xDirty) xDirty = x;
|
||||
for (iPixel = 0; iPixel < nPixels; iPixel++) {
|
||||
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[data & 0xff]);
|
||||
this.setPixel(this.imageBuffer, x++, y, aPixelColors[data & 0xff]);
|
||||
data >>= 8;
|
||||
}
|
||||
if (x > xMaxDirty) xMaxDirty = x;
|
||||
|
|
@ -5984,8 +5984,8 @@ Video.prototype.updateScreenGraphicsVGA = function(addrBuffer, addrScreen, addrS
|
|||
if (xDirty < this.nCols) {
|
||||
var cxDirty = xMaxDirty - xDirty;
|
||||
var cyDirty = yMaxDirty - yDirty;
|
||||
this.contextScreenBuffer.putImageData(this.imageScreenBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
this.contextScreen.drawImage(this.canvasScreenBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
this.contextBuffer.putImageData(this.imageBuffer, 0, 0, xDirty, yDirty, cxDirty, cyDirty);
|
||||
this.contextScreen.drawImage(this.canvasBuffer, 0, 0, this.nCols, this.nRows, 0, 0, this.cxScreen, this.cyScreen);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue