| @@ -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"); | |||
| // ------------------------------------------------------------- | |||
| }); | |||
| }); | |||