forked from sent/waves
1229 lines
48 KiB
JavaScript
1229 lines
48 KiB
JavaScript
define(function() {
|
|
return {
|
|
VECTOR_INT: 0xFFFE,
|
|
VECTOR_RESET: 0xFFFC,
|
|
VECTOR_NMI: 0xFFFA,
|
|
|
|
clock: null,
|
|
printedTo: null,
|
|
|
|
curOp: [],
|
|
curCycle: null,
|
|
reg: null,
|
|
halted: null,
|
|
signalled: null,
|
|
util: {
|
|
setFlag: function(flag, cond) {
|
|
if (cond) {
|
|
this.reg.P |= flag;
|
|
} else {
|
|
this.reg.P &= (255 - flag);
|
|
}
|
|
},
|
|
setNZ: function(val) {
|
|
if (val & 128) {
|
|
this.reg.P |= this.flags.N;
|
|
} else {
|
|
this.reg.P &= (255 - this.flags.N);
|
|
}
|
|
|
|
if (val == 0) {
|
|
this.reg.P |= this.flags.Z;
|
|
} else {
|
|
this.reg.P &= (255 - this.flags.Z);
|
|
}
|
|
},
|
|
branch: function(flag, val) {
|
|
if ((this.reg.P & flag) == val) {
|
|
this.reg.PC = this.reg.addr;
|
|
if (!this.reg.tmp4) {
|
|
this.reg.tmp4 = 1;
|
|
return false;
|
|
} else if ((this.reg.addr & 0xFF00) != (this.reg.tmp1 & 0xFF00)) {
|
|
if (this.reg.tmp4 == 1) {
|
|
this.reg.tmp4 = 2;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
push: function(val) {
|
|
this.owner.MMU.w(this.reg.S + 0x0100, val);
|
|
this.reg.S = (this.reg.S - 1) & 0x00FF;
|
|
},
|
|
pop: function() {
|
|
this.reg.S = (this.reg.S + 1) & 0x00FF;
|
|
return this.owner.MMU.r(this.reg.S + 0x0100);
|
|
},
|
|
interrupt: function(vector, brk_flag, reset_flag) {
|
|
// This gets a bit messy, handling all the int types:
|
|
// BRK changes PC, and sets the B flag
|
|
// RESET doesn't push PC, and doesn't set I
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = reset_flag ? 3 : 2;
|
|
if (!brk_flag) {
|
|
// Rewind the changes made in previous cycles
|
|
this.reg.PC = (this.reg.PC - 2) & 0xFFFF;
|
|
}
|
|
if (!reset_flag) {
|
|
this.util.push.call(this, this.reg.PC >> 8);
|
|
}
|
|
return false;
|
|
case 2:
|
|
this.reg.tmp4 = 3;
|
|
if (!reset_flag) {
|
|
this.util.push.call(this, this.reg.PC & 255);
|
|
}
|
|
return false;
|
|
case 3:
|
|
this.reg.tmp4 = 4;
|
|
if (reset_flag) {
|
|
return false;
|
|
}
|
|
if (brk_flag) {
|
|
this.reg.P |= this.flags.B;
|
|
} else {
|
|
this.reg.P &= (255 - this.flags.B);
|
|
}
|
|
this.util.push.call(this, this.reg.P);
|
|
if (reset_flag) {
|
|
this.reg.P &= (255 - this.flags.I);
|
|
} else {
|
|
this.reg.P |= this.flags.I;
|
|
}
|
|
return false;
|
|
case 4:
|
|
this.reg.tmp4 = 5;
|
|
this.reg.addr = this.owner.MMU.r(vector);
|
|
return false;
|
|
case 5:
|
|
this.reg.addr += (this.owner.MMU.r(vector + 1) << 8);
|
|
this.reg.PC = this.reg.addr;
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
ops: {
|
|
ADC: function() {
|
|
var res = this.reg.operand + this.reg.A + ((this.reg.P & this.flags.C) ? 1 : 0);
|
|
if (this.reg.P & this.flags.D) {
|
|
this.util.setFlag.call(this, this.flags.Z, (res & 255) == 0);
|
|
if ((this.reg.operand & 15) + (this.reg.A & 15) + ((this.reg.P & this.flags.C) ? 1 : 0) > 9) {
|
|
res += 6;
|
|
}
|
|
this.util.setFlag.call(this, this.flags.N, res & 128);
|
|
this.util.setFlag.call(this, this.flags.V,
|
|
(!((this.reg.A ^ this.reg.operand) & 128)) &&
|
|
((this.reg.A ^ res) & 128)
|
|
);
|
|
if (res > 0x99) {
|
|
res += 0x60;
|
|
}
|
|
this.util.setFlag.call(this, this.flags.C, res > 0x99);
|
|
} else {
|
|
this.util.setNZ.call(this, res & 255);
|
|
this.util.setFlag.call(this, this.flags.V,
|
|
(!((this.reg.A ^ this.reg.operand) & 128)) &&
|
|
((this.reg.A ^ res) & 128)
|
|
);
|
|
this.util.setFlag.call(this, this.flags.C, res > 255);
|
|
}
|
|
|
|
this.reg.A = res & 255;
|
|
return true;
|
|
},
|
|
AHX: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
ALR: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
ANC: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
AND: function() {
|
|
this.reg.A = (this.reg.A & this.reg.operand) & 255;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
ARR: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
ASL: function() {
|
|
this.reg.writeflag = true;
|
|
this.util.setFlag.call(this, this.flags.C, this.reg.operand & 128);
|
|
this.reg.operand = (this.reg.operand << 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
AXS: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
BCC: function() {
|
|
return this.util.branch.call(this, this.flags.C, 0);
|
|
},
|
|
BCS: function() {
|
|
return this.util.branch.call(this, this.flags.C, this.flags.C);
|
|
},
|
|
BEQ: function() {
|
|
return this.util.branch.call(this, this.flags.Z, this.flags.Z);
|
|
},
|
|
BIT: function() {
|
|
this.util.setFlag.call(this, this.flags.N, this.reg.operand & 128);
|
|
this.util.setFlag.call(this, this.flags.V, this.reg.operand & 64);
|
|
this.util.setFlag.call(this, this.flags.Z, (this.reg.operand & this.reg.A) == 0);
|
|
return true;
|
|
},
|
|
BMI: function() {
|
|
return this.util.branch.call(this, this.flags.N, this.flags.N);
|
|
},
|
|
BNE: function() {
|
|
return this.util.branch.call(this, this.flags.Z, 0);
|
|
},
|
|
BPL: function() {
|
|
return this.util.branch.call(this, this.flags.N, 0);
|
|
},
|
|
BRK: function() {
|
|
return this.util.interrupt.call(this, this.VECTOR_INT, true);
|
|
},
|
|
BVC: function() {
|
|
return this.util.branch.call(this, this.flags.V, 0);
|
|
},
|
|
BVS: function() {
|
|
return this.util.branch.call(this, this.flags.V, this.flags.V);
|
|
},
|
|
CLC: function() {
|
|
this.reg.P &= (255 - this.flags.C);
|
|
return true;
|
|
},
|
|
CLD: function() {
|
|
this.reg.P &= (255 - this.flags.D);
|
|
return true;
|
|
},
|
|
CLI: function() {
|
|
this.reg.P &= (255 - this.flags.I);
|
|
return true;
|
|
},
|
|
CLV: function() {
|
|
this.reg.P &= (255 - this.flags.V);
|
|
return true;
|
|
},
|
|
CMP: function() {
|
|
var res = (this.reg.A - this.reg.operand) & 511;
|
|
this.util.setFlag.call(this, this.flags.C, res < 256);
|
|
this.util.setNZ.call(this, res & 255);
|
|
return true;
|
|
},
|
|
CPX: function() {
|
|
var res = (this.reg.X - this.reg.operand) & 511;
|
|
this.util.setFlag.call(this, this.flags.C, res < 256);
|
|
this.util.setNZ.call(this, res & 255);
|
|
return true;
|
|
},
|
|
CPY: function() {
|
|
var res = (this.reg.Y - this.reg.operand) & 511;
|
|
this.util.setFlag.call(this, this.flags.C, res < 256);
|
|
this.util.setNZ.call(this, res & 255);
|
|
return true;
|
|
},
|
|
DCP: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
DEC: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.operand = (this.reg.operand - 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
DEX: function() {
|
|
this.reg.X = (this.reg.X - 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.X);
|
|
return true;
|
|
},
|
|
DEY: function() {
|
|
this.reg.Y = (this.reg.Y - 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.Y);
|
|
return true;
|
|
},
|
|
EOR: function() {
|
|
this.reg.A = (this.reg.A ^ this.reg.operand) & 255;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
HLT: function() {
|
|
this.halted = true;
|
|
return true;
|
|
},
|
|
INC: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.operand = (this.reg.operand + 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
INT: function() {
|
|
return this.util.interrupt.call(this, this.VECTOR_INT);
|
|
},
|
|
INX: function() {
|
|
this.reg.X = (this.reg.X + 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.X);
|
|
return true;
|
|
},
|
|
INY: function() {
|
|
this.reg.Y = (this.reg.Y + 1) & 255;
|
|
this.util.setNZ.call(this, this.reg.Y);
|
|
return true;
|
|
},
|
|
ISC: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
JMP: function() {
|
|
this.reg.PC = this.reg.addr;
|
|
return true;
|
|
},
|
|
JSR: function() {
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
this.reg.tmp3 = (this.reg.PC - 1) & 0xFFFF;
|
|
this.util.push.call(this, this.reg.tmp3 >> 8);
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = 2;
|
|
this.util.push.call(this, this.reg.tmp3 & 255);
|
|
return false;
|
|
case 2:
|
|
this.reg.PC = this.reg.addr;
|
|
}
|
|
return true;
|
|
},
|
|
LAS: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
LAX: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
LDA: function() {
|
|
this.reg.A = this.reg.operand;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
LDX: function() {
|
|
this.reg.X = this.reg.operand;
|
|
this.util.setNZ.call(this, this.reg.X);
|
|
return true;
|
|
},
|
|
LDY: function() {
|
|
this.reg.Y = this.reg.operand;
|
|
this.util.setNZ.call(this, this.reg.Y);
|
|
return true;
|
|
},
|
|
LSR: function() {
|
|
this.reg.writeflag = true;
|
|
this.util.setFlag.call(this, this.flags.C, this.reg.operand & 1);
|
|
this.reg.operand >>= 1;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
NMI: function() {
|
|
return this.util.interrupt.call(this, this.VECTOR_NMI);
|
|
},
|
|
NOP: function() {
|
|
// lol
|
|
return true;
|
|
},
|
|
ORA: function() {
|
|
this.reg.A = (this.reg.A | this.reg.operand) & 255;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
PHA: function() {
|
|
if (!this.reg.tmp3) {
|
|
this.reg.tmp3 = 1;
|
|
return false;
|
|
}
|
|
this.util.push.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
PHP: function() {
|
|
if (!this.reg.tmp3) {
|
|
this.reg.tmp3 = 1;
|
|
return false;
|
|
}
|
|
this.util.push.call(this, this.reg.P);
|
|
return true;
|
|
},
|
|
PLA: function() {
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = 2;
|
|
return false;
|
|
case 2:
|
|
this.reg.A = this.util.pop.call(this);
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
}
|
|
return true;
|
|
},
|
|
PLP: function() {
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = 2;
|
|
return false;
|
|
case 2:
|
|
this.reg.P = this.util.pop.call(this);
|
|
}
|
|
return true;
|
|
},
|
|
RLA: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
ROL: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.operand <<= 1;
|
|
if (this.reg.P & this.flags.C) {
|
|
this.reg.operand |= 1;
|
|
}
|
|
this.util.setFlag.call(this, this.flags.C, this.reg.operand & 256);
|
|
this.reg.operand &= 255;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
ROR: function() {
|
|
this.reg.writeflag = true;
|
|
if (this.reg.P & this.flags.C) {
|
|
this.reg.operand |= 256;
|
|
}
|
|
this.util.setFlag.call(this, this.flags.C, this.reg.operand & 1);
|
|
this.reg.operand >>= 1;
|
|
this.util.setNZ.call(this, this.reg.operand);
|
|
return true;
|
|
},
|
|
RRA: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
RST: function() {
|
|
return this.util.interrupt.call(this, this.VECTOR_RESET, false, true);
|
|
},
|
|
RTI: function() {
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = 2;
|
|
return false;
|
|
case 2:
|
|
this.reg.tmp4 = 3;
|
|
this.reg.P = this.util.pop.call(this);
|
|
return false;
|
|
case 3:
|
|
this.reg.tmp4 = 4;
|
|
this.reg.addr = this.util.pop.call(this);
|
|
return false;
|
|
case 4:
|
|
this.reg.addr += (this.util.pop.call(this) << 8);
|
|
this.reg.PC = this.reg.addr;
|
|
}
|
|
return true;
|
|
},
|
|
RTS: function() {
|
|
switch (this.reg.tmp4) {
|
|
case null:
|
|
this.reg.tmp4 = 1;
|
|
return false;
|
|
case 1:
|
|
this.reg.tmp4 = 2;
|
|
return false;
|
|
case 2:
|
|
this.reg.tmp4 = 3;
|
|
this.reg.addr = this.util.pop.call(this);
|
|
return false;
|
|
case 3:
|
|
this.reg.tmp4 = 4;
|
|
this.reg.addr += (this.util.pop.call(this) << 8);
|
|
return false;
|
|
case 4:
|
|
this.reg.PC = (this.reg.addr + 1) & 0xFFFF;
|
|
}
|
|
return true;
|
|
},
|
|
SAX: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
SBC: function() {
|
|
var res = this.reg.A - this.reg.operand - ((this.reg.P & this.flags.C) ? 0 : 1);
|
|
this.util.setNZ.call(this, res & 255);
|
|
this.util.setFlag.call(this, this.flags.V,
|
|
((this.reg.A ^ this.reg.operand) & 128) &&
|
|
((this.reg.A ^ res) & 128)
|
|
);
|
|
if (this.reg.P & this.flags.D) {
|
|
if ((this.reg.A & 15) - ((this.reg.P & this.flags.C) ? 0 : 1) < (this.reg.operand & 15)) {
|
|
res -= 6;
|
|
}
|
|
if (res > 0x99) {
|
|
res -= 0x60;
|
|
}
|
|
}
|
|
this.util.setFlag.call(this, this.flags.C, !(res & 256));
|
|
this.reg.A = res & 255;
|
|
return true;
|
|
},
|
|
SEC: function() {
|
|
this.reg.P |= this.flags.C;
|
|
return true;
|
|
},
|
|
SED: function() {
|
|
this.reg.P |= this.flags.D;
|
|
return true;
|
|
},
|
|
SEI: function() {
|
|
this.reg.P |= this.flags.I;
|
|
return true;
|
|
},
|
|
SHX: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
SHY: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
SLO: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
SRE: function() {
|
|
this.reg.writeflag = true;
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
STA: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.writeonly = true;
|
|
this.reg.operand = this.reg.A;
|
|
return true;
|
|
},
|
|
STX: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.writeonly = true;
|
|
this.reg.operand = this.reg.X;
|
|
return true;
|
|
},
|
|
STY: function() {
|
|
this.reg.writeflag = true;
|
|
this.reg.writeonly = true;
|
|
this.reg.operand = this.reg.Y;
|
|
return true;
|
|
},
|
|
TAS: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
},
|
|
TAX: function() {
|
|
this.reg.X = this.reg.A;
|
|
this.util.setNZ.call(this, this.reg.X);
|
|
return true;
|
|
},
|
|
TAY: function() {
|
|
this.reg.Y = this.reg.A;
|
|
this.util.setNZ.call(this, this.reg.Y);
|
|
return true;
|
|
},
|
|
TSX: function() {
|
|
this.reg.X = this.reg.S;
|
|
this.util.setNZ.call(this, this.reg.X);
|
|
return true;
|
|
},
|
|
TXA: function() {
|
|
this.reg.A = this.reg.X;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
TXS: function() {
|
|
this.reg.S = this.reg.X;
|
|
return true;
|
|
},
|
|
TYA: function() {
|
|
this.reg.A = this.reg.Y;
|
|
this.util.setNZ.call(this, this.reg.A);
|
|
return true;
|
|
},
|
|
XAA: function() {
|
|
// TODO: Undocumented
|
|
return true;
|
|
}
|
|
},
|
|
addr: {
|
|
imp: function() {
|
|
// Nothing to do except suck up 1 cycle
|
|
return true;
|
|
},
|
|
imp_w: function() {
|
|
return true;
|
|
},
|
|
acc: function() {
|
|
this.reg.operand = this.reg.A;
|
|
return true;
|
|
},
|
|
acc_w: function() {
|
|
this.reg.A = this.reg.operand;
|
|
return true;
|
|
},
|
|
imm: function() {
|
|
if (this.curOp.length == 1) {
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.operand = this.curOp[1];
|
|
}
|
|
return true;
|
|
},
|
|
imm_w: function() {
|
|
return true;
|
|
},
|
|
z: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.addr = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
z_w: function() {
|
|
if (!this.reg.writeonly && this.curCycle < 5) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
zx: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
if (this.reg.addr === null) {
|
|
this.reg.tmp1 += this.reg.X;
|
|
this.reg.addr = this.reg.tmp1 & 0xFF;
|
|
return false;
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
zx_w: function() {
|
|
if (!this.reg.writeonly && this.curCycle < 6) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
zy: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
if (this.reg.addr === null) {
|
|
this.reg.tmp1 += this.reg.Y;
|
|
this.reg.addr = this.reg.tmp1 & 0xFF;
|
|
return false;
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
zy_w: function() {
|
|
if (!this.reg.writeonly && this.curCycle < 6) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
abs: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.addr = (this.curOp[2] << 8) + this.reg.tmp1;
|
|
if (
|
|
this.map[this.curOp[0]][0] == 'JMP' ||
|
|
this.map[this.curOp[0]][0] == 'JSR'
|
|
) {
|
|
// Operand not required
|
|
return true;
|
|
}
|
|
return false;
|
|
case 3:
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
abs_w: function() {
|
|
if (!this.reg.writeonly && this.curCycle < 6) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
abx: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp2 = (this.curOp[2] << 8) + this.reg.tmp1;
|
|
return false;
|
|
case 3:
|
|
if (this.reg.addr === null) {
|
|
this.reg.addr = (this.reg.tmp2 + this.reg.X) & 0xFFFF;
|
|
if ((this.reg.tmp2 & 0xFF00) != (this.reg.addr & 0xFF00)) {
|
|
// Page boundary, add a cycle
|
|
return false;
|
|
}
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
abx_w: function() {
|
|
if (this.curCycle < (this.reg.writeonly ? 5 : 7)) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
aby: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp2 = (this.curOp[2] << 8) + this.reg.tmp1;
|
|
return false;
|
|
case 3:
|
|
if (this.reg.addr === null) {
|
|
this.reg.addr = (this.reg.tmp2 + this.reg.Y) & 0xFFFF;
|
|
if ((this.reg.tmp2 & 0xFF00) != (this.reg.addr & 0xFF00)) {
|
|
// Page boundary, add a cycle
|
|
return false;
|
|
}
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
aby_w: function() {
|
|
if (this.curCycle < (this.reg.writeonly ? 5 : 7)) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
ind: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp2 = (this.curOp[2] << 8) + this.reg.tmp1;
|
|
return false;
|
|
case 3:
|
|
if (this.reg.tmp3 === null) {
|
|
this.reg.tmp3 = this.owner.MMU.r(this.reg.tmp2);
|
|
return false;
|
|
}
|
|
if (this.reg.addr === null) {
|
|
this.reg.addr = (this.owner.MMU.r(this.reg.tmp2 + 1) << 8) + this.reg.tmp3;
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
ind_w: function() {
|
|
// No such thing as a write here
|
|
return true;
|
|
},
|
|
rel: function() {
|
|
if (this.curOp.length == 1) {
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.reg.PC;
|
|
return false;
|
|
}
|
|
|
|
this.reg.operand = this.curOp[1];
|
|
this.reg.addr = (this.curOp[1] & 128)
|
|
? -(256 - this.curOp[1])
|
|
: this.curOp[1];
|
|
this.reg.addr += this.reg.tmp1;
|
|
return true;
|
|
},
|
|
rel_w: function() {
|
|
// No such thing as a write here
|
|
return true;
|
|
},
|
|
izx: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
if (this.reg.tmp2 === null) {
|
|
// Redundant fetch
|
|
this.reg.tmp2 = this.owner.MMU.r(this.reg.tmp1);
|
|
this.reg.tmp1 = (this.reg.tmp1 + this.reg.X) & 0xFF;
|
|
return false;
|
|
}
|
|
if (this.reg.tmp3 === null) {
|
|
this.reg.tmp3 = this.owner.MMU.r(this.reg.tmp1);
|
|
return false;
|
|
}
|
|
if (this.reg.addr === null) {
|
|
this.reg.addr = (this.owner.MMU.r((this.reg.tmp1 + 1) & 0xFF) << 8) + this.reg.tmp3;
|
|
return false;
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
izx_w: function() {
|
|
if (this.curCycle < (this.reg.writeonly ? 6 : 8)) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
},
|
|
izy: function() {
|
|
switch (this.curOp.length) {
|
|
case 1:
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.reg.tmp1 = this.curOp[1];
|
|
return false;
|
|
case 2:
|
|
if (this.reg.tmp2 === null) {
|
|
this.reg.tmp2 = this.owner.MMU.r(this.reg.tmp1);
|
|
return false;
|
|
}
|
|
if (this.reg.tmp3 === null) {
|
|
this.reg.tmp3 = (this.owner.MMU.r((this.reg.tmp1 + 1) & 0xFF) << 8) + this.reg.tmp2;
|
|
return false;
|
|
}
|
|
if (this.reg.addr === null) {
|
|
this.reg.addr = (this.reg.tmp3 + this.reg.Y) & 0xFFFF;
|
|
if ((this.reg.tmp3 & 0xFF00) != (this.reg.addr & 0xFF00)) {
|
|
// Page boundary crossed
|
|
return false;
|
|
}
|
|
}
|
|
if (this.reg.operand === null) {
|
|
this.reg.operand = this.owner.MMU.r(this.reg.addr);
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
izy_w: function() {
|
|
if (this.curCycle < (this.reg.writeonly ? 6 : 8)) {
|
|
return false;
|
|
}
|
|
this.owner.MMU.w(this.reg.addr, this.reg.operand);
|
|
return true;
|
|
}
|
|
},
|
|
disasmHandlers: {
|
|
imp: function(op) {
|
|
return '';
|
|
},
|
|
acc: function(op) {
|
|
return 'a';
|
|
},
|
|
imm: function(op) {
|
|
return '#$' + this.pad(op[1], '0', 2);
|
|
},
|
|
z: function(op) {
|
|
return '$' + this.pad(op[1], '0', 2);
|
|
},
|
|
zx: function(op) {
|
|
return '$' + this.pad(op[1], '0', 2) + ',x';
|
|
},
|
|
zy: function(op) {
|
|
return '$' + this.pad(op[1], '0', 2) + ',y';
|
|
},
|
|
abs: function(op) {
|
|
return '$' + this.pad(op[1] + (op[2] << 8), '000', 4);
|
|
},
|
|
abx: function(op) {
|
|
return '$' + this.pad(op[1] + (op[2] << 8), '000', 4) + ',x';
|
|
},
|
|
aby: function(op) {
|
|
return '$' + this.pad(op[1] + (op[2] << 8), '000', 4) + ',y';
|
|
},
|
|
ind: function(op) {
|
|
return '($' + this.pad(op[1] + (op[2] << 8), '000', 4) + ')';
|
|
},
|
|
rel: function(op) {
|
|
if (this.reg.addr) {
|
|
return '$' + this.pad(this.reg.addr, '000', 4);
|
|
} else {
|
|
if (op[1] & 128) {
|
|
return '-' + (((~op[1]) + 1) & 127);
|
|
} else {
|
|
return '+' + op[1];
|
|
}
|
|
}
|
|
},
|
|
izy: function(op) {
|
|
return '($' + this.pad(op[1], '0', 2) + '),Y';
|
|
},
|
|
izx: function(op) {
|
|
return '($' + this.pad(op[1], '0', 2) + ',X)';
|
|
}
|
|
},
|
|
map: [
|
|
['BRK','imp',1,7],['ORA','izx',2,6],['HLT','imp',1,2],['SLO','izx',2,8],
|
|
['NOP','z', 2,3],['ORA','z', 2,3],['ASL','z', 2,5],['SLO','z', 2,5],
|
|
['PHP','imp',1,3],['ORA','imm',2,2],['ASL','acc',1,2],['ANC','imm',2,2],
|
|
['NOP','abs',3,4],['ORA','abs',3,4],['ASL','abs',3,6],['SLO','abs',3,6],
|
|
|
|
['BPL','rel',2,2],['ORA','izy',2,5],['HLT','imp',1,2],['SLO','izy',2,8],
|
|
['NOP','zx', 2,4],['ORA','zx', 2,4],['ASL','zx', 2,6],['SLO','zx', 2,6],
|
|
['CLC','imp',1,2],['ORA','aby',3,4],['NOP','imp',1,2],['SLO','aby',3,7],
|
|
['NOP','abx',3,4],['ORA','abx',3,4],['ASL','abx',3,7],['SLO','abx',3,7],
|
|
|
|
['JSR','abs',3,6],['AND','izx',2,6],['HLT','imp',1,2],['RLA','izx',2,8],
|
|
['BIT','z' ,2,3],['AND','z' ,2,3],['ROL','z', 2,5],['RLA','z', 2,5],
|
|
['PLP','imp',1,4],['AND','imm',2,2],['ROL','acc',1,2],['ANC','imm',2,2],
|
|
['BIT','abs',3,4],['AND','abs',3,4],['ROL','abs',3,6],['RLA','abs',3,6],
|
|
|
|
['BMI','rel',2,2],['AND','izy',2,5],['HLT','imp',1,2],['RLA','izy',2,8],
|
|
['NOP','zx', 2,4],['AND','zx', 2,4],['ROL','zx', 2,6],['RLA','zx', 2,6],
|
|
['SEC','imp',1,2],['AND','aby',3,4],['NOP','imp',1,2],['RLA','aby',3,7],
|
|
['NOP','abx',3,4],['AND','abx',3,4],['ROL','abx',3,7],['RLA','abx',3,7],
|
|
|
|
['RTI','imp',1,6],['EOR','izx',2,6],['HLT','imp',1,2],['SRE','izx',2,8],
|
|
['NOP','z', 2,3],['EOR','z', 2,3],['LSR','z', 2,5],['SRE','z', 2,5],
|
|
['PHA','imp',1,3],['EOR','imm',2,2],['LSR','acc',1,2],['ALR','imm',2,2],
|
|
['JMP','abs',3,3],['EOR','abs',3,4],['LSR','abs',3,6],['SRE','abs',3,6],
|
|
|
|
['BVC','rel',2,2],['EOR','izy',2,5],['HLT','imp',1,2],['SRE','izy',2,8],
|
|
['NOP','zx', 2,4],['EOR','zx', 2,4],['LSR','zx', 2,6],['SRE','zx', 2,6],
|
|
['CLI','imp',1,2],['EOR','aby',3,4],['NOP','imp',1,2],['SRE','aby',3,7],
|
|
['NOP','abx',3,4],['EOR','abx',3,4],['LSR','abx',3,7],['SRE','abx',3,7],
|
|
|
|
['RTS','imp',1,6],['ADC','izx',2,6],['HLT','imp',1,2],['RRA','izx',2,8],
|
|
['NOP','z', 2,3],['ADC','z', 2,3],['ROR','z', 2,5],['RRA','z', 2,5],
|
|
['PLA','imp',1,4],['ADC','imm',2,2],['ROR','acc',1,2],['ARR','imm',2,2],
|
|
['JMP','ind',3,5],['ADC','abs',3,4],['ROR','abs',3,6],['RRA','abs',3,6],
|
|
|
|
['BVS','rel',2,2],['ADC','izy',2,5],['HLT','imp',1,2],['RRA','izy',2,8],
|
|
['NOP','zx', 2,4],['ADC','zx', 2,4],['ROR','zx', 2,6],['RRA','zx', 2,6],
|
|
['SEI','imp',1,2],['ADC','aby',3,4],['NOP','imp',1,2],['RRA','aby',3,7],
|
|
['NOP','abx',3,4],['ADC','abx',3,4],['ROR','abx',3,7],['RRA','abx',3,7],
|
|
|
|
['NOP','imm',2,2],['STA','izx',2,6],['NOP','imm',2,2],['SAX','izx',2,6],
|
|
['STY','z', 2,3],['STA','z', 2,3],['STX','z', 2,3],['SAX','z', 2,3],
|
|
['DEY','imp',1,2],['NOP','imm',2,2],['TXA','imp',1,2],['XAA','imm',2,2],
|
|
['STY','abs',3,4],['STA','abs',3,4],['STX','abs',3,4],['SAX','abs',3,4],
|
|
|
|
['BCC','rel',2,2],['STA','izy',2,6],['HLT','imp',1,2],['AHX','izy',2,6],
|
|
['STY','zx', 2,4],['STA','zx', 2,4],['STX','zy', 2,4],['SAX','zy', 2,4],
|
|
['TYA','imp',1,2],['STA','aby',3,5],['TXS','imp',1,2],['TAS','aby',3,5],
|
|
['SHY','abx',3,5],['STA','abx',3,5],['SHX','abx',3,5],['AHX','abx',3,5],
|
|
|
|
['LDY','imm',2,2],['LDA','izx',2,6],['LDX','imm',2,2],['LAX','izx',2,6],
|
|
['LDY','z', 2,3],['LDA','z', 2,3],['LDX','z', 2,3],['LAX','z', 2,3],
|
|
['TAY','imp',1,2],['LDA','imm',2,2],['TAX','imp',1,2],['LAX','imm',2,2],
|
|
['LDY','abs',3,4],['LDA','abs',3,4],['LDX','abs',3,4],['LAX','abs',3,4],
|
|
|
|
['BCS','rel',2,2],['LDA','izy',2,5],['HLT','imp',1,2],['LAX','izy',2,5],
|
|
['LDY','zx', 2,4],['LDA','zx', 2,4],['LDX','zy', 2,4],['LAX','zy', 2,4],
|
|
['CLV','imp',1,2],['LDA','aby',3,4],['TSX','imp',1,2],['LAS','aby',3,4],
|
|
['LDY','abx',3,4],['LDA','abx',3,4],['LDX','aby',3,4],['LAX','aby',3,4],
|
|
|
|
['CPY','imm',2,2],['CMP','izx',2,6],['NOP','imm',2,2],['DCP','izx',2,8],
|
|
['CPY','z', 2,3],['CMP','z', 2,3],['DEC','z', 2,5],['DCP','z', 2,5],
|
|
['INY','imp',1,2],['CMP','imm',2,2],['DEX','imp',1,2],['AXS','imm',2,2],
|
|
['CPY','abs',3,4],['CMP','abs',3,4],['DEC','abs',3,6],['DCP','abs',3,6],
|
|
|
|
['BNE','rel',2,2],['CMP','izy',2,5],['HLT','imp',1,2],['DCP','izy',2,8],
|
|
['NOP','zx', 2,4],['CMP','zx', 2,4],['DEC','zx', 2,6],['DCP','zx', 2,6],
|
|
['CLD','imp',1,2],['CMP','aby',3,4],['NOP','imp',1,2],['DCP','aby',3,7],
|
|
['NOP','abx',3,4],['CMP','abx',3,4],['DEC','abx',3,7],['DCP','abx',3,7],
|
|
|
|
['CPX','imm',2,2],['SBC','izx',2,6],['NOP','imm',1,2],['ISC','izx',2,8],
|
|
['CPX','z', 2,3],['SBC','z', 2,3],['INC','z', 2,5],['ISC','z', 2,5],
|
|
['INX','imp',1,2],['SBC','imm',2,2],['NOP','imp',1,2],['SBC','imm',2,2],
|
|
['CPX','abs',3,4],['SBC','abs',3,4],['INC','abs',3,6],['ISC','abs',3,6],
|
|
|
|
['BEQ','rel',2,2],['SBC','izy',2,5],['HLT','imp',1,2],['ISC','izy',2,8],
|
|
['NOP','zx', 2,4],['SBC','zx', 2,4],['INC','zx', 2,6],['ISC','zx', 2,6],
|
|
['SED','imp',1,2],['SBC','aby',3,4],['NOP','imp',1,2],['ISC','aby',3,7],
|
|
['NOP','abx',3,4],['SBC','abx',3,4],['INC','abx',3,7],['ISC','abx',3,7],
|
|
|
|
['INT','imp',1,7],['RST','imp',1,6],['NMI','imp',1,7]
|
|
],
|
|
flags: {
|
|
N: 128,
|
|
V: 64,
|
|
B: 16,
|
|
D: 8,
|
|
I: 4,
|
|
Z: 2,
|
|
C: 1
|
|
},
|
|
interruptSignals: {
|
|
'INT': 256,
|
|
'RST': 257,
|
|
'NMI': 258
|
|
},
|
|
step: function() {
|
|
this.clock++;
|
|
|
|
var op; // [opcode, addr, size, time]
|
|
if (this.halted) {
|
|
return;
|
|
}
|
|
if (this.owner.MMU.busLock) {
|
|
if (this.owner.game.debug) {
|
|
console.log('BUS LOCK: ' + this.owner.MMU.busLock);
|
|
}
|
|
this.owner.MMU.busLock--;
|
|
return;
|
|
}
|
|
if (this.clock == 1) {
|
|
this.signal('RST');
|
|
}
|
|
|
|
this.curCycle++;
|
|
if (this.curOp.length == 0) {
|
|
this.reg.origPC = this.reg.PC;
|
|
if (this.signalled && !(this.reg.P & this.flags.I)) {
|
|
this.curOp.push(this.signalled);
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
this.signalled = null;
|
|
} else {
|
|
this.curOp.push(this.owner.MMU.r(this.reg.PC));
|
|
this.reg.PC = (this.reg.PC + 1) & 0xFFFF;
|
|
}
|
|
} else {
|
|
op = this.map[this.curOp[0]];
|
|
if (this.addr[op[1]].call(this)) {
|
|
if (!this.reg.operated) {
|
|
this.reg.operated = this.ops[op[0]].call(this);
|
|
}
|
|
if (this.reg.operated) {
|
|
if (this.owner.game.debug && !this.reg.printed) {
|
|
if (this.clock > this.printedTo) {
|
|
this.reg.printed = true;
|
|
console.log(this.debugString());
|
|
this.printedTo = this.clock;
|
|
}
|
|
}
|
|
if (this.reg.writeflag) {
|
|
if (this.addr[op[1] + '_w'].call(this)) {
|
|
this.resetOp();
|
|
}
|
|
} else {
|
|
this.resetOp();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
disasm: function(pc, len) {
|
|
len = len || 64;
|
|
var i = 0, j, op = [], prevPC;
|
|
|
|
do {
|
|
prevPC = pc;
|
|
op.length = 0;
|
|
op.push(this.owner.MMU.r(pc++));
|
|
|
|
for (j = 1; j < this.map[op[0]][2]; j++) {
|
|
op.push(this.owner.MMU.r(pc++));
|
|
}
|
|
|
|
i += op.length;
|
|
console.warn([
|
|
this.pad(prevPC, '000', 4),
|
|
this.map[op[0]][0],
|
|
this.disasmHandlers[this.map[op[0]][1]].call(this, op).toUpperCase()
|
|
].join(' '));
|
|
} while (i < len);
|
|
},
|
|
debugString: function() {
|
|
var i, opcodes = '',
|
|
operand = this.disasmHandlers[this.map[this.curOp[0]][1]].call(this, this.curOp).toUpperCase();
|
|
|
|
for (i = 0; i < this.curOp.length; i++) {
|
|
opcodes += this.pad(this.curOp[i], '0', 2, true);
|
|
opcodes += ' ';
|
|
}
|
|
while (opcodes.length < 12) {
|
|
opcodes += ' ';
|
|
}
|
|
while (operand.length < 10) {
|
|
operand += ' ';
|
|
}
|
|
|
|
return [
|
|
'.C:' + this.pad(this.reg.origPC, '000', 4),
|
|
' ' + opcodes,
|
|
this.map[this.curOp[0]][0], operand, '-',
|
|
"A:" + this.pad(this.reg.A, '0', 2, true),
|
|
"X:" + this.pad(this.reg.X, '0', 2, true),
|
|
"Y:" + this.pad(this.reg.Y, '0', 2, true),
|
|
"S:" + this.pad(this.reg.S, '0', 2),
|
|
(
|
|
((this.reg.P & this.flags.N) ? 'N' : '.') +
|
|
((this.reg.P & this.flags.V) ? 'V' : '.') +
|
|
'-' +
|
|
((this.reg.P & this.flags.B) ? 'B' : '.') +
|
|
((this.reg.P & this.flags.D) ? 'D' : '.') +
|
|
((this.reg.P & this.flags.I) ? 'I' : '.') +
|
|
((this.reg.P & this.flags.Z) ? 'Z' : '.') +
|
|
((this.reg.P & this.flags.C) ? 'C' : '.')
|
|
), ' ',
|
|
this.clock
|
|
].join(' ');
|
|
},
|
|
pad: function(val, padder, len, upper) {
|
|
return (padder + val.toString(16))[upper ? 'toUpperCase' : 'toLowerCase']().slice(-len);
|
|
},
|
|
signal: function(line) {
|
|
this.signalled = this.interruptSignals[line] || null;
|
|
},
|
|
getState: function() {
|
|
return {
|
|
clock: this.clock,
|
|
curOp: this.curOp.slice(0),
|
|
curCycle: 0 + this.curCycle,
|
|
reg: $.extend({}, this.reg)
|
|
};
|
|
},
|
|
setState: function(state) {
|
|
this.clock = state.clock;
|
|
this.curOp = state.curOp.slice(0);
|
|
this.curCycle = state.curCycle;
|
|
this.reg = $.extend({}, state.reg);
|
|
},
|
|
reset: function() {
|
|
this.reg = {
|
|
PC: 0,
|
|
A: 0,
|
|
X: 0,
|
|
Y: 0,
|
|
S: 0,
|
|
P: 0x20,
|
|
|
|
// Might be useful for intermediate addressing steps
|
|
operated: false,
|
|
writeflag: false,
|
|
writeonly: false,
|
|
printed: false,
|
|
operand: null,
|
|
origPC: null,
|
|
addr: null,
|
|
tmp1: null,
|
|
tmp2: null,
|
|
tmp3: null,
|
|
tmp4: null
|
|
};
|
|
this.clock = 0;
|
|
this.printedTo = 0;
|
|
this.halted = false;
|
|
this.resetOp();
|
|
},
|
|
resetOp: function() {
|
|
this.curOp.length = 0;
|
|
this.curCycle = 0;
|
|
this.reg.operated = false;
|
|
this.reg.writeflag = false;
|
|
this.reg.writeonly = false;
|
|
this.reg.printed = false;
|
|
this.reg.operand = null;
|
|
this.reg.origPC = null;
|
|
this.reg.addr = null;
|
|
this.reg.tmp1 = null;
|
|
this.reg.tmp2 = null;
|
|
this.reg.tmp3 = null;
|
|
this.reg.tmp4 = null;
|
|
},
|
|
init: function() {
|
|
this.reset();
|
|
}
|
|
};
|
|
});
|