for(_='tch(zm[qswizj[1]~r~):$--;)Qt=G&O)@40`q(2`@>>4]_q(38`@>>8]K[+w+64*(_+v)];T[E]&&T[E].maz/qP++]function(H(J())=,,parseInt(C"==C?[~<<4)255break;case ;for(},=e){D[D[e.which]]=:i=((38`@>>8)+1;iQq@{case (o=q15]=&&(P+=2) ==r[0]?){:lL.push({P:X,I:P})+((38`&l~)>>8),G&l~)==l[0]?:o=128+~,G(++l~,GOP={CLS:G224RET:G238JP:X=E-2,l6:716:(l6:176)CALL:X=E-4,l732:SEr748$48rSNEr764$144rLD:X=E-2,lro=2`+r~,6:22128r:3G21:9G41:8G51:4==l[0]&&(G85):7296$5160+((38`&r~)>>8),G&$2`10):32`7):2`101)ADDr7112$2128(r+4):2`+r~,G30)OR1AND2XOR3SUB5SHRo=1286SUBN7SHLo=12814RNDo=192~DRWo=208(+~SKPo=224158SKNPo=224161DW:l=~,o=l>>8,G&l}J=e){\\s/);)E++;C=""[\\w#\\[\\]]/);)C+=T[E++];return C?(OP[C]?(OP[C]G0),=o,=t):E++&&e&&(D[C]=P),1):0H=return C?"I5]:"[I]4]:"F9]:"B8]:"DT3]:C.maz/V.\\b/)?[2~,16)]:"#"==C[0]?[7.slice(1),16)]:C[0].maz/\\d/)?[7)]:D[C]?H(C=D[C]+""):[6]:~D={49:1,50:2,51:3,52:12,81:4,87:5,69:6,82:13S=0,b.onkeyup0b.onkeydown1b.insertBefore(Z=document.createElement("textarea"),a).value="L:LD I,0 DRW V0,V1,2 ADD V0,4 SE V0,64 JP L LD V0,0 ADD V1,2 JP L",(Z.onchange=T=Z.value.replace(/;.*/g,""),m=new Uint8Array(`96),P=512,L=[],I=E=0;J(1););i in L)J(P=L[i].I,E=L[i].P);P=510,S||(S=setInterval(N=9;NQjO=<<8|,614`0:j150:K=[]14:P=L[--E]}8192:L[E++]=P;case `96:P=`95&O12288:==(@ 16384:!=(@ 20480:==_ 24576:=&O28672:+=&O32768:j150:=_1:|=_2:&=_3:^=_4:_>-,+=_5:_<=,-=_6:1&,>>=17:<=_,=_-14:>>7,<<=1}36864:!=_ `960:I=`95&O45056:P=(`95@+q0]49152:=(*Math.random()|0)&(@53248:0,v=15&O;vQw=8;wQqI+v]&128>>w&&(&&(1),^=1)57344:j158:D[] 161:D[]||(P+=2)}614`:j7:=d21:d=30:I+>`95,I+=41:I=5*51:qI]=/100,qI+1]=/10%10,qI+2]=%100%1085I+i]=qi]101i]=qI+i]}}i=2048;iQc.fillRect(i%64*9,9*(i/64|0),9,9,c.fillStyle=K[i]?"#FFF":"#000");d--16))})()';g=/[-_`@GQ$~jqz]/.exec(_);)with(_.split(g))_=join(shift());eval(_)
OP = {
CLS: function() { // 00E0 - CLS
t = 0xE0
},
RET: function() { // 00EE - RET
t = 0xEE
},
JP: function() {
X = E - 2
l = H(J())
if ( l[0] == 6 ) { // 1NNN - JP addr
L.push( {P: X, I: P} )
}
else if ( l[0] == 7 ) {
o = 0x10 + ((l[1] & 0xF00) >> 8)
t = 0x0FF & l[1]
}
else { // BNNN - JP V0, addr
l = H(J()) // right
if ( l[0] == 6 ) {
L.push( {P: X, I: P} )
}
else {
o = 0xB0 + ((l[1] & 0xF00) >> 8)
t = 0x0FF & l[1]
}
}
},
CALL: function() { // 2NNN - CALL addr
X = E - 4
l = H(J())
if ( l[0] == 7 ) {
o = 0x20 + ((l[1] & 0xF00) >> 8)
t = 0x0FF & l[1]
}
else {
L.push( {P: X, I: P} )
}
},
SE: function() {
l = H(J())
r = H(J())
if ( r[0] == 7 ) { // 3XNN - SE Vx, byte
o = 0x30 + l[1]
t = r[1]
}
else { // 5XY0 - SE Vx, Vy
o = 0x30 + l[1]
t = r[1] << 4
}
},
SNE: function() {
l = H(J())
r = H(J())
if ( r[0] == 7 ) { // 4XNN - SNE Vx, byte
o = 0x40 + l[1]
t = r[1]
}
else { // 9XY0 - SNE Vx, Vy
o = 0x90 + l[1]
t = r[1] << 4
}
},
LD: function() {
X = E - 2
l = H(J())
r = H(J())
o = 0xF0 + r[1]
if ( r[0] == 6 ) {
L.push( {P: X, I: P} )
}
else if ( r[0] == 2 ) {
if ( l[0] == 2 ) { // 8XY0 - LD Vx, Vy
o = 0x80 + l[1]
t = r[1] << 4
}
else if ( l[0] == 3 ) { // FX15 - LD DT, Vx
t = 0x15
}
else if ( l[0] == 9 ) { // FX29 - LD F, Vx
t = 0x29
}
else if ( l[0] == 8 ) { // FX33 - LD B, Vx
t = 0x33
}
else if ( l[0] == 4 ) { // FX55 - LD [I], Vx
t = 0x55
}
}
else if ( r[0] == 7 ) {
if ( l[0] == 2) { // 6XNN - LD Vx, byte
o = 0x60 + l[1]
t = r[1]
}
else if ( l[0] == 5 ) { // ANNN - LD I, addr
o = 0xA0 + ((r[1] & 0xF00) >> 8)
t = 0x0FF & r[1]
}
else { // FX0A - LD Vx, K
o = 0xF0 + l[1]
t = 0x0A
}
}
else if ( r[0] == 3 ) { // FX07 - LD Vx, DT
o = 0xF0 + l[1]
t = 0x07
}
else { // FX65 - LD Vx, [I]
o = 0xF0 + l[1]
t = 0x65
}
},
ADD: function() {
l = H(J())
r = H(J())
if ( r[0] == 7 ) { // 7XNN - ADD Vx, byte
o = 0x70 + l[1]
t = r[1]
}
else if ( l[0] == 2 ) { // 8XY4 - ADD Vx, Vy
o = 0x80 + l[1]
t = (r[1] << 4) + 0x4
}
else { // FX1E - ADD I, Vx
o = 0xF0 + r[1]
t = 0x1E
}
},
OR: function() { // 8XY1 - OR Vx, Vy
o = 0x80 + H(J())[1]
t = (H(J())[1] << 4) + 0x01
},
AND: function() { // 8XY2 - AND Vx, Vy
o = 0x80 + H(J())[1]
t = (H(J())[1] << 4) + 0x02
},
XOR: function() { // 8XY3 - XOR Vx, Vy
o = 0x80 + H(J())[1]
t = (H(J())[1] << 4) + 0x03
},
SUB: function() { // 8XY5 - SUB Vx, Vy
o = 0x80 + H(J())[1]
t = (H(J())[1] << 4) + 0x05
},
SHR: function() { // 8X06 - SHR Vx
l = H(J())
o = 0x80 + l[1]
t = 0x06
},
SUBN: function() { // 8XY7 - SUBN Vx, Vy
o = 0x80 + H(J())[1]
t = (H(J())[1] << 4) + 0x07
},
SHL: function() { // 8X0E - SHL Vx
l = H(J())
o = 0x80 + l[1]
t = 0x0E
},
RND: function() { // CXNN - RND Vx, byte
l = H(J())
o = 0xC0 + l[1]
t = H(J())[1]
},
DRW: function() { // DXYN - DRW Vx, Vy, nibble
l = H(J())
o = 0xD0 + l[1]
t = (H(J())[1] << 4) + H(J())[1]
},
SKP: function() { // EX9E - SKP Vx
l = H(J())
o = 0xE0 + l[1]
t = 0x9E
},
SKNP: function() { // EXA1 - SKNP Vx
l = H(J())
o = 0xE0 + l[1]
t = 0xA1
},
DW: function() {
l = H(J())[1]
o = l >> 8
t = l & 0x00FF
}
}
J = function( e ) {
// skip whitespace
while ( T[E] && T[E].match( /\s/ ) ) E++
// read string
C = ''
while ( T[E] && T[E].match( /[\w#\[\]]/ ) ) C += T[E++]
return C ? (OP[C] ? (OP[C](o = t = 0), m[P++] = o, m[P++] = t) : E++ && e && (D[C] = P), 1) : 0
}
H = function() {
if ( !C ) return [1]
else if ( C == 'I' ) {
return [5]
}
else if ( C == '[I]' ) {
return [4]
}
else if ( C == 'F' ) {
return [9]
}
else if ( C == 'B' ) {
return [8]
}
else if ( C == 'DT' ) {
return [3]
}
else if ( C.match( /V.\b/ ) ) {
return [2, parseInt( C[1], 16 )]
}
else if ( C[0] == '#' ) {
return [7, parseInt( C.slice( 1 ), 16 )]
}
else if ( C[0].match( /\d/ ) ) {
return [7, parseInt( C )]
}
return D[C] ? H( C = D[C] + '' ) : [6]
}
D = {49:1,50:2,51:3,52:0xC,81:4,87:5,69:6,82:0xD} // & Label & Keys
S = 0
b.onkeyup = function( e ) {
D[D[e.which]] = 0
}
b.onkeydown = function( e ) {
D[D[e.which]] = 1
}
b.insertBefore( Z = document.createElement( 'textarea' ), a ).value = 'L:LD I,0 DRW V0,V1,2 ADD V0,4 SE V0,64 JP L LD V0,0 ADD V1,2 JP L'
;(Z.onchange = function() {
T = Z.value.replace( /;.*/g, '' )
m = new Uint8Array( 4096 ) // memory & register
P = 512
L = [] // Lazy & Stack
I = // Index Counter
E = 0// current Code Position
while ( J(1) ) {} // parse
for ( i in L ) J( P = L[i].I, E = L[i].P ) // handle lazy
P = 510
if ( !S ) S = setInterval( function() {
for ( N = 9; N--; ) {
O = m[P++] << 8 | m[P++]
switch ( O & 0xF000 ) {
case 0x0000:
switch ( O & 0x000F ) {
case 0x0000: // clear screen
K = []
break
case 0x000E: // returns from subroutine
P = L[--E]
break
}
break
case 0x2000: // call subroutine at NNN
L[E++] = P
case 0x1000: // jump to adress NNN
P = O & 0x0FFF
break
case 0x3000: // Skips the next instruction if VX equals NN.
if ( m[(O & 0x0F00) >> 8] == (O & 0x00FF) ) P += 2
break
case 0x4000: // Skips the next instruction if VX doesn't equal NN.
if ( m[(O & 0x0F00) >> 8] != (O & 0x00FF) ) P += 2
break
case 0x5000: // Skips the next instruction if VX equals VY.
if ( m[(O & 0x0F00) >> 8] == m[(O & 0x00F0 ) >> 4] ) P += 2
break
case 0x6000: // Sets VX to NN.
m[(O & 0x0F00) >> 8] = O & 0x00FF
break
case 0x7000: // Adds NN to VX.
m[(O & 0x0F00) >> 8] += O & 0x00FF
break
case 0x8000:
switch ( O & 0x000F ) {
case 0x0000: // Sets VX to the value of VY.
m[(O & 0x0F00) >> 8] = m[(O & 0x00F0) >> 4]
break
case 0x0001: // Sets VX to VX | VY.
m[(O & 0x0F00) >> 8] |= m[(O & 0x00F0) >> 4]
break
case 0x0002: // Sets VX to VX and VY.
m[(O & 0x0F00) >> 8] &= m[(O & 0x00F0) >> 4]
break
case 0x0003: // Sets VX to VX xor VY.
m[(O & 0x0F00) >> 8] ^= m[(O & 0x00F0) >> 4]
break
case 0x0004: // Adds VY to VX. VF is set to 1 when there's a carry, and to 0 when there isn't.
m[0xF] = m[(O & 0x00F0) >> 4] > 0xFF - m[(O & 0x0F00) >> 8]
m[(O & 0x0F00) >> 8] += m[(O & 0x00F0 ) >> 4]
break
case 0x0005: // VY is subtracted from VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
m[0xF] = m[(O & 0x00F0) >> 4] <= m[(O & 0x0F00) >> 8]
m[(O & 0x0F00) >> 8] -= m[(O & 0x00F0) >> 4]
break
case 0x0006: // Shifts VX right by one. VF is set to the value of the least significant bit of VX before the shift
m[0xF] = m[(O & 0x0F00) >> 8] & 0x1
m[(O & 0x0F00) >> 8] >>= 1
break
case 0x0007: // Sets VX to VY minus VX. VF is set to 0 when there's a borrow, and 1 when there isn't.
m[0xF] = m[(O & 0x0F00) >> 8] <= m[(O & 0x00F0) >> 4]
m[(O & 0x0F00) >> 8] = m[(O & 0x00F0) >> 4] - m[(O & 0x0F00) >> 8]
break
case 0x000E: // Shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift.
m[0xF] = m[(O & 0x0F00) >> 8] >> 7
m[(O & 0x0F00) >> 8] <<= 1
break
}
break
case 0x9000: // Skips the next instruction if VX doesn't equal VY.
if ( m[(O & 0x0F00) >> 8] != m[(O & 0x00F0) >> 4] ) P += 2
break
case 0xA000: // Sets I to the address NNN.
I = O & 0x0FFF
break
case 0xB000: // Jumps to the address NNN plus V0.
P = (O & 0x0FFF) + m[0]
break
case 0xC000: // Sets VX to a random number and NN.
m[(O & 0x0F00) >> 8] = (Math.random() * 0xFF | 0) & (O & 0x00FF)
break
case 0xD000:
m[0xF] = 0
for ( v = O & 0x000F; v--; ) {
for ( w = 8; w--; ) {
if ( (m[I + v] & ( 0x80 >> w )) ) {
if ( K[m[(O & 0x0F00) >> 8] + w + (m[(O & 0x00F0) >> 4] + v) * 64] ) m[0xF] = 1
K[m[(O & 0x0F00) >> 8] + w + (m[(O & 0x00F0) >> 4] + v) * 64] ^= 1
}
}
}
break
case 0xE000:
switch ( O & 0x00FF ) {
case 0x009E: // Skips the next instruction if the key stored in VX is pressed.
if ( D[m[(O & 0x0F00) >> 8]] ) P += 2
break
case 0x00A1: // Skips the next instruction if the key stored in VX isn't pressed.
if ( !D[m[(O & 0x0F00) >> 8]] ) P += 2
break
}
break
case 0xF000:
switch ( O & 0x00FF ) {
case 0x0007: // Sets VX to the value of the delay timer.
m[(O & 0x0F00) >> 8] = d
break
case 0x0015: // Sets the delay timer to