@@ -268,14 +268,41 @@ class Assembler{ | |||
if (line === ""){return this;} | |||
if (line[0] !== ";"){ // Skip comment lines. | |||
line = line.split(";")[0].trim(); // Take out any trailing comments. | |||
// Checking for any jump labels! | |||
if (line.indexOf(":") >= 0){ | |||
let s = line.split(":"); | |||
let lbl = s[0].trim(); | |||
if (lbl.length <= 0) | |||
throw new Error("Malformatted jump label at program address " + toHexString(this.__PC)); | |||
this.__StoreJmpLabel(lbl); | |||
line = s[1].trim(); | |||
if (line.length <= 0){return this;} // Nothing left to process. | |||
} | |||
// Finally... tokenize the main command. | |||
var tokens = tokenize(line); | |||
if (tokens[0].toLowerCase() === 'define'){ | |||
if (tokens[0].toLowerCase() === '.define'){ | |||
// Variable label!! | |||
this.__StoreVarLabel(tokens[1], tokens[2]); | |||
} else if (tokens[0][tokens[0].length - 1] === ':'){ | |||
/*} else if (tokens[0][tokens[0].length - 1] === ':'){ | |||
// 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].toLowerCase() === '.bytes'){ | |||
// Compiler directive. Treat all proceeding tokens as values and store them raw. | |||
for(let i=1; i < tokens.length; i++){ | |||
let v = Number.NaN; | |||
if (tokens[i].startsWith("$")){ | |||
v = parseInt(tokens[i].substr(1), 16); | |||
} else if (tokens[i].startsWith("b")){ | |||
v = parseInt(tokens[i].substr(1), 2); | |||
} else { | |||
v = parseInt(tokens[i]); | |||
} | |||
if (isNaN(v) || v < 0 || v >= 256) | |||
throw new Error("Byte list value is malformed or out of bounds at program address " + toHexString(this.__PC)); | |||
op.push(v); | |||
this.__PC += 1; | |||
}; | |||
} else if (tokens[0].length === 3){ | |||
let StoreSingleOp = (code)=>{ | |||
@@ -301,9 +328,9 @@ class Assembler{ | |||
} | |||
if (!isNaN(v)){ | |||
if (v < this.__PC - 127 || v > this.__PC + 128) | |||
throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC)); | |||
v = v - this.__PC; | |||
if (v < (this.__PC+1) - 127 || v > (this.__PC+1) + 128) | |||
throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC + 1)); | |||
v = v - (this.__PC + 1); | |||
op.push(code); | |||
op.push((v >= 0) ? v : v + 255); | |||
this.__PC += 2; | |||
@@ -666,6 +693,8 @@ class Assembler{ | |||
case 'tya': | |||
procFailed = StoreSingleOp(0x98); break; | |||
// --- --- | |||
// EOL | |||
// --- --- | |||
default: | |||
throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); | |||
} | |||
@@ -691,6 +720,7 @@ class Assembler{ | |||
this.__varlabels = {}; | |||
this.__jmplabels = {}; | |||
this.__result = []; | |||
return this; | |||
} | |||
} | |||
@@ -22,8 +22,8 @@ describe("Testing MOS6502 Systems...", function(){ | |||
}); | |||
describe(".compile()", function(){ | |||
it("Variable definition", function(){ | |||
asm.compile("define TAG $44"); | |||
it(".define directive", function(){ | |||
asm.compile(".define TAG $44"); | |||
let vars = asm.variables; | |||
expect(vars).to.have.key('TAG'); | |||
expect(vars['TAG']).to.equal(0x44); | |||
@@ -37,6 +37,40 @@ describe("Testing MOS6502 Systems...", function(){ | |||
expect(jmp['loop']).to.equal(pc); | |||
}); | |||
it(".bytes directive", function(){ | |||
let res = asm.reset().compile(".BYTES $44, $55, $66, $77, b10110101, 128").result(); | |||
expect(res.length).to.equal(6); | |||
expect(res[0]).to.equal(0x44); | |||
expect(res[1]).to.equal(0x55); | |||
expect(res[2]).to.equal(0x66); | |||
expect(res[3]).to.equal(0x77); | |||
expect(res[4]).to.equal(parseInt('10110101', 2)); | |||
expect(res[5]).to.equal(128); | |||
}); | |||
it("Jump label before and after .byte directive", function(){ | |||
asm.reset(); | |||
let pc1 = asm.PC; | |||
asm.compile("bytes: .bytes $44, $55, $66, $77"); | |||
let pc2 = asm.PC; | |||
asm.compile("loop: BNE loop"); | |||
let jmp = asm.jumplabels; | |||
//expect(jmp).to.have.key('bytes'); | |||
expect(jmp['bytes']).to.equal(pc1); | |||
//expect(jmp).to.have.key('loop'); | |||
expect(jmp['loop']).to.equal(pc2); | |||
let res = asm.result(); | |||
expect(res.length).to.equal(6); | |||
expect(res[0]).to.equal(0x44); | |||
expect(res[1]).to.equal(0x55); | |||
expect(res[2]).to.equal(0x66); | |||
expect(res[3]).to.equal(0x77); | |||
expect(res[4]).to.equal(0xD0); | |||
expect(res[5]).to.equal(0xFE); | |||
}); | |||
it("ADC Immediate", function(){ | |||
asm.reset(); | |||
asm.compile("ADC #$44"); | |||
@@ -433,6 +467,8 @@ describe("Testing MOS6502 Systems...", function(){ | |||
it("STY Zero Page"); | |||
it("STY Zero Page, X"); | |||
it("STY Absolute"); | |||
// ------------------------------------------------------------- | |||
}); | |||
}); | |||