| var Memory = require('src/memory'); | var Memory = require('src/memory'); | ||||
| class MOS6502{ | |||||
| class CPU{ | |||||
| constructor(){ | constructor(){ | ||||
| // Registers | // Registers | ||||
| this.__PC = 0; // Program Counter (16 bit) | this.__PC = 0; // Program Counter (16 bit) | ||||
| this.__irq = (q === true); | 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){ | if (this.__clkfn === null){ | ||||
| this.__clkfn = (function(){ | this.__clkfn = (function(){ | ||||
| // TODO: All the work!! | // TODO: All the work!! | ||||
| return this.__clkfn; | return this.__clkfn; | ||||
| } | } | ||||
| Memory(mem){ | |||||
| memory(mem){ | |||||
| if (!(mem instanceof Memory)) | if (!(mem instanceof Memory)) | ||||
| throw new ValueError("Expected Memory instance object."); | throw new ValueError("Expected Memory instance object."); | ||||
| this.__mem = mem; | this.__mem = mem; | ||||
| } | } | ||||
| 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 | |||||
| }; | |||||