|
|
@@ -4,7 +4,7 @@ |
|
|
|
|
|
|
|
var Memory = require('src/memory'); |
|
|
|
|
|
|
|
class MOS6502{ |
|
|
|
class CPU{ |
|
|
|
constructor(){ |
|
|
|
// Registers |
|
|
|
this.__PC = 0; // Program Counter (16 bit) |
|
|
@@ -35,7 +35,12 @@ class MOS6502{ |
|
|
|
this.__irq = (q === true); |
|
|
|
} |
|
|
|
|
|
|
|
CLK(){ |
|
|
|
reset(){ |
|
|
|
// TODO: Read memory address $FFFC - FFFD to find PC start location. |
|
|
|
// TODO: Reset status registers that get changed on a reset. |
|
|
|
} |
|
|
|
|
|
|
|
clk(){ |
|
|
|
if (this.__clkfn === null){ |
|
|
|
this.__clkfn = (function(){ |
|
|
|
// TODO: All the work!! |
|
|
@@ -44,7 +49,7 @@ class MOS6502{ |
|
|
|
return this.__clkfn; |
|
|
|
} |
|
|
|
|
|
|
|
Memory(mem){ |
|
|
|
memory(mem){ |
|
|
|
if (!(mem instanceof Memory)) |
|
|
|
throw new ValueError("Expected Memory instance object."); |
|
|
|
this.__mem = mem; |
|
|
@@ -52,4 +57,180 @@ class MOS6502{ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
module.exports = MOS6502; |
|
|
|
|
|
|
|
// --------------------------------------------------------------------- |
|
|
|
// --------------------------------------------------------------------- |
|
|
|
|
|
|
|
function toHexString(v, l){ |
|
|
|
l = (typeof(l) === 'number' && (l === 8 || l === 16)) ? l : 8; |
|
|
|
var r = v.toString(16); |
|
|
|
if (r.length < 2) |
|
|
|
r = "0" + r; |
|
|
|
if (l === 16 && r.length < 4) |
|
|
|
r = ((r.length === 2) ? "00" : "0") + r; |
|
|
|
return r; |
|
|
|
} |
|
|
|
|
|
|
|
class Assembler{ |
|
|
|
constructor(initpc){ |
|
|
|
// Labels that hold variable values. |
|
|
|
this.__varlabels = {}; |
|
|
|
// Labels that hold jump/branch locations. |
|
|
|
this.__jmplabels = {}; |
|
|
|
// Program counter to track where in the code/memory a |
|
|
|
// operation is located. |
|
|
|
this.__PC = (initpc >= 0) ? initpc : 0; |
|
|
|
} |
|
|
|
|
|
|
|
compile(src){ |
|
|
|
var op = []; |
|
|
|
src.split("\n").forEach((line)=>{ |
|
|
|
line = line.trim(); |
|
|
|
if (line[0] !== ";"){ // Skip comment lines. |
|
|
|
line = line.split(";")[0].trim(); // Take out any trailing comments. |
|
|
|
var tokens = line.split(/\s+/); |
|
|
|
|
|
|
|
if (tokens[0] === 'define'){ |
|
|
|
// Variable label!! |
|
|
|
} else if (tokens[0][tokens[0].length - 1] === ':'){ |
|
|
|
// Jump label!! |
|
|
|
} else if (tokens[0].length === 3){ |
|
|
|
// Possible op code. |
|
|
|
switch(tokens[0].toLowerCase()){ |
|
|
|
case 'adc': |
|
|
|
break; |
|
|
|
case 'and': |
|
|
|
break; |
|
|
|
case 'asl': |
|
|
|
break; |
|
|
|
case 'bcc': |
|
|
|
break; |
|
|
|
case 'bcs': |
|
|
|
break; |
|
|
|
case 'beq': |
|
|
|
break; |
|
|
|
case 'bit': |
|
|
|
break; |
|
|
|
case 'bmi': |
|
|
|
break; |
|
|
|
case 'bne': |
|
|
|
break; |
|
|
|
case 'bpl': |
|
|
|
break; |
|
|
|
case 'brk': |
|
|
|
break; |
|
|
|
case 'bvc': |
|
|
|
break; |
|
|
|
case 'bvs': |
|
|
|
break; |
|
|
|
case 'clc': |
|
|
|
break; |
|
|
|
case 'cld': |
|
|
|
break; |
|
|
|
case 'cli': |
|
|
|
break; |
|
|
|
case 'clv': |
|
|
|
break; |
|
|
|
case 'cmp': |
|
|
|
break; |
|
|
|
case 'cpx': |
|
|
|
break; |
|
|
|
case 'cpy': |
|
|
|
break; |
|
|
|
case 'dec': |
|
|
|
break; |
|
|
|
case 'dex': |
|
|
|
break; |
|
|
|
case 'dey': |
|
|
|
break; |
|
|
|
case 'eor': |
|
|
|
break; |
|
|
|
case 'inc': |
|
|
|
break; |
|
|
|
case 'inx': |
|
|
|
break; |
|
|
|
case 'iny': |
|
|
|
break; |
|
|
|
case 'jmp': |
|
|
|
break; |
|
|
|
case 'jsr': |
|
|
|
break; |
|
|
|
case 'lda': |
|
|
|
break; |
|
|
|
case 'ldx': |
|
|
|
break; |
|
|
|
case 'ldy': |
|
|
|
break; |
|
|
|
case 'lsr': |
|
|
|
break; |
|
|
|
case 'nop': |
|
|
|
break; |
|
|
|
case 'ora': |
|
|
|
break; |
|
|
|
case 'pha': |
|
|
|
break; |
|
|
|
case 'php': |
|
|
|
break; |
|
|
|
case 'pla': |
|
|
|
break; |
|
|
|
case 'plp': |
|
|
|
break; |
|
|
|
case 'rol': |
|
|
|
break; |
|
|
|
case 'ror': |
|
|
|
break; |
|
|
|
case 'rti': |
|
|
|
break; |
|
|
|
case 'rts': |
|
|
|
break; |
|
|
|
case 'sbc': |
|
|
|
break; |
|
|
|
case 'sec': |
|
|
|
break; |
|
|
|
case 'sed': |
|
|
|
break; |
|
|
|
case 'sei': |
|
|
|
break; |
|
|
|
case 'sta': |
|
|
|
break; |
|
|
|
case 'stx': |
|
|
|
break; |
|
|
|
case 'sty': |
|
|
|
break; |
|
|
|
case 'tax': |
|
|
|
break; |
|
|
|
case 'tay': |
|
|
|
break; |
|
|
|
case 'tsx': |
|
|
|
break; |
|
|
|
case 'txa': |
|
|
|
break; |
|
|
|
case 'txs': |
|
|
|
break; |
|
|
|
case 'tya': |
|
|
|
break; |
|
|
|
default: |
|
|
|
throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
throw new Error("Failed to compile line '" + line + "' at program address " + toHexString(this.__PC)); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
return new Uint8Array(op); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------- |
|
|
|
// --------------------------------------------------------------------- |
|
|
|
|
|
|
|
module.exports = { |
|
|
|
CPU: CPU, |
|
|
|
Assembler: Assembler |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|