Browse Source

Fixed some bugs with a dummy test file (to be removed and replaced with a mocha test).

master
Bryan Miller 5 years ago
parent
commit
28ed010e64
2 changed files with 52 additions and 34 deletions
  1. +16
    -0
      dummy.js
  2. +36
    -34
      src/MOS6502.js

+ 16
- 0
dummy.js View File

var mos6502 = require("./src/MOS6502.js");

var asm = new mos6502.Assembler();
var src = "DEFINE TOPNT $44\n";
src += "CLRMEM:\n";
src += "LDA #$00 ;Set up zero value\n";
src += "TAY ;Initialize index pointer\n";
src += "CLRM1:\n";
src += "STA (TOPNT),Y ;Clear memory location\n";
src += "INY ;Advance index pointer\n";
src += "DEX ;Decrement counter\n";
src += "BNE CLRM1 ;Not zero, continue checking\n";
src += "RTS ;Return\n"

var res = asm.compile(src);
console.log(res);

+ 36
- 34
src/MOS6502.js View File

* Emulate a basic 6502 (MOS) chip. * Emulate a basic 6502 (MOS) chip.
*/ */


var Memory = require('src/memory');
var Memory = require('./memory.js');


class CPU{ class CPU{
constructor(){ constructor(){
function tokenize(l){ function tokenize(l){
var m = l.match(/([^()]+)|([()])/g); var m = l.match(/([^()]+)|([()])/g);
var ip = false; var ip = false;
t = [];
var t = [];
m.forEach((mi)=>{ m.forEach((mi)=>{
if (mi === "("){ if (mi === "("){
ip = true; ip = true;
} else if (mi === ")"){
ip = false;
} else { } else {
if (ip){ if (ip){
mi.split(/[\s,]+/).forEach((i)=>{ mi.split(/[\s,]+/).forEach((i)=>{
} }
} }
}); });
return t;
} }


class Assembler{ class Assembler{
let lbl = tA.substr(1); let lbl = tA.substr(1);
if (lbl in this.__varlabels){ if (lbl in this.__varlabels){
if (this.__varlabels[lbl] < 256) if (this.__varlabels[lbl] < 256)
v = vlb[lbl];
v = this.__varlabels[lbl];
} }
} }
} }
var op = []; var op = [];
src.split("\n").forEach((line)=>{ src.split("\n").forEach((line)=>{
line = line.trim(); line = line.trim();
if (line === ""){return;}
if (line[0] !== ";"){ // Skip comment lines. if (line[0] !== ";"){ // Skip comment lines.
line = line.split(";")[0].trim(); // Take out any trailing comments. line = line.split(";")[0].trim(); // Take out any trailing comments.
var tokens = tokenize(line); var tokens = tokenize(line);


if (tokens[0] === 'define'){
if (tokens[0].toLowerCase() === 'define'){
// Variable label!! // Variable label!!
this.__StoreVarLabel(tokens[1], tokens[2]); this.__StoreVarLabel(tokens[1], tokens[2]);
} else if (tokens[0][tokens[0].length - 1] === ':'){ } else if (tokens[0][tokens[0].length - 1] === ':'){
// Jump labels! // Jump labels!
this.__StoreJmpLabel(tokens[0].substr(0, tokens[0].length - 1););
this.__StoreJmpLabel(tokens[0].substr(0, tokens[0].length - 1));
} else if (tokens[0].length === 3){ } else if (tokens[0].length === 3){


let StoreSingleOp = (code)=>{ let StoreSingleOp = (code)=>{
if (tokens.length === 1){ if (tokens.length === 1){
op.push(code); op.push(code);
this.__PC += 1; this.__PC += 1;
return true;
return false;
} }
return false;
return true;
}; };


let StoreBranchOp = (code) => { let StoreBranchOp = (code) => {
if (tokens.length === 2){ if (tokens.length === 2){
let v = Number.NaN; let v = Number.NaN;
if (token[1][0] === '$'){
if (tokens[1][0] === '$'){
if (tokens[1].length === 3 || tokens[1].length === 5){ if (tokens[1].length === 3 || tokens[1].length === 5){
v = parseInt(token[1].substr(1), 16); v = parseInt(token[1].substr(1), 16);
} }
op.push(code); op.push(code);
op.push((v >= 0) ? v : v + 255); op.push((v >= 0) ? v : v + 255);
this.__PC += 2; this.__PC += 2;
return false;
} }
} }
return false;
return true;
}; };


let StoreOp = (codes, mint, maxt) => { let StoreOp = (codes, mint, maxt) => {
if (tokens.length >= mint && tokens.length <= maxt){ if (tokens.length >= mint && tokens.length <= maxt){
let mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null);
let modea = true;
let mv = this.__AddrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase() : null);
let modena = true;
switch(mv[0]){ switch(mv[0]){
case "i": case "i":
modea = codes[0] !== null;
if (modea){
modena = codes[0] === null;
if (!modena){
op.push(codes[0]); op.push(codes[0]);
op.push(mv[1]); op.push(mv[1]);
this.__PC += 2; this.__PC += 2;
} break; } break;
case "z": case "z":
modea = codes[1] !== null;
if (modea){
modena = codes[1] === null;
if (!modena){
op.push(codes[1]); op.push(codes[1]);
op.push(mv[1]); op.push(mv[1]);
this.__PC += 2; this.__PC += 2;
} break; } break;
case "zX": case "zX":
modea = codes[2] !== null;
if (modea){
modena = codes[2] === null;
if (!modena){
op.push(codes[2]); op.push(codes[2]);
op.push(mv[1]); op.push(mv[1]);
this.__PC += 2; this.__PC += 2;
} break; } break;
case "a": case "a":
modea = codes[3] !== null;
if (modea){
modena = codes[3] === null;
if (!modena){
op.push(codes[3]); op.push(codes[3]);
op.push(mv[1] & 0x000000FF); op.push(mv[1] & 0x000000FF);
op.push((mv[1] & 0x0000FF00) >> 8); op.push((mv[1] & 0x0000FF00) >> 8);
this.__PC += 3; this.__PC += 3;
} break; } break;
case "aX": case "aX":
modea = codes[4] !== null;
if (modea){
modena = codes[4] === null;
if (!modena){
op.push(codes[4]); op.push(codes[4]);
op.push(mv[1] & 0x000000FF); op.push(mv[1] & 0x000000FF);
op.push((mv[1] & 0x0000FF00) >> 8); op.push((mv[1] & 0x0000FF00) >> 8);
this.__PC += 3; this.__PC += 3;
} break; } break;
case "aY": case "aY":
modea = codes[5] !== null;
if (modea){
modena = codes[5] === null;
if (!modena){
op.push(codes[5]); op.push(codes[5]);
op.push(mv[1] & 0x000000FF); op.push(mv[1] & 0x000000FF);
op.push((mv[1] & 0x0000FF00) >> 8); op.push((mv[1] & 0x0000FF00) >> 8);
this.__PC += 3; this.__PC += 3;
} break; } break;
case "nX": case "nX":
modea = codes[6] !== null;
if (modea){
modena = codes[6] === null;
if (!modena){
op.push(codes[6]); op.push(codes[6]);
op.push(mv[1]); op.push(mv[1]);
this.__PC += 2; this.__PC += 2;
} break; } break;
case "nY": case "nY":
modea = codes[7] !== null;
if (modea){
modena = codes[7] === null;
if (!modena){
op.push(codes[7]); op.push(codes[7]);
op.push(mv[1]); op.push(mv[1]);
this.__PC += 2; this.__PC += 2;
} break; } break;
} }
if (modea === false)
if (modena)
throw new Error("Op-code does not support implied mode on program address " + toHexString(this.__PC)); throw new Error("Op-code does not support implied mode on program address " + toHexString(this.__PC));
return true;
return false;
} }
return false;
return true;
}; };


let procFailed = false; let procFailed = false;
break; break;
// --- LDA // --- LDA
case 'lda': case 'lda':
procFailed = StoreOp([0xA9, 0xA5, 0xB5, 0xAD, 0xBD, 0xB9, 0xA1, 0xB1], 2, 3); break;
break;
procFailed = StoreOp([0xA9, 0xA5, 0xB5, 0xAD, 0xBD, 0xB9, 0xA1, 0xB1], 2, 3); break;
// --- LDX // --- LDX
case 'ldx': case 'ldx':
procFailed = StoreOp([0xA2, 0xA6, 0xB6, 0xAE, 0xBE, null, null, null], 2, 3); break; procFailed = StoreOp([0xA2, 0xA6, 0xB6, 0xAE, 0xBE, null, null, null], 2, 3); break;
break;
// --- LDY // --- LDY
case 'ldy': case 'ldy':
procFailed = StoreOp([0xA0, 0xA4, 0xB4, 0xAC, 0xBC, null, null, null], 2, 3); break; procFailed = StoreOp([0xA0, 0xA4, 0xB4, 0xAC, 0xBC, null, null, null], 2, 3); break;
break;
// --- LSR // --- LSR
case 'lsr': case 'lsr':
if (tokens.length === 2){ if (tokens.length === 2){

Loading…
Cancel
Save