|
|
|
|
|
|
|
|
if (line === ""){return this;} |
|
|
if (line === ""){return this;} |
|
|
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. |
|
|
|
|
|
// 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); |
|
|
var tokens = tokenize(line); |
|
|
|
|
|
|
|
|
if (tokens[0].toLowerCase() === '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].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){ |
|
|
} else if (tokens[0].length === 3){ |
|
|
|
|
|
|
|
|
let StoreSingleOp = (code)=>{ |
|
|
let StoreSingleOp = (code)=>{ |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!isNaN(v)){ |
|
|
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(code); |
|
|
op.push((v >= 0) ? v : v + 255); |
|
|
op.push((v >= 0) ? v : v + 255); |
|
|
this.__PC += 2; |
|
|
this.__PC += 2; |
|
|
|
|
|
|
|
|
case 'tya': |
|
|
case 'tya': |
|
|
procFailed = StoreSingleOp(0x98); break; |
|
|
procFailed = StoreSingleOp(0x98); break; |
|
|
// --- --- |
|
|
// --- --- |
|
|
|
|
|
// EOL |
|
|
|
|
|
// --- --- |
|
|
default: |
|
|
default: |
|
|
throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); |
|
|
throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
this.__varlabels = {}; |
|
|
this.__varlabels = {}; |
|
|
this.__jmplabels = {}; |
|
|
this.__jmplabels = {}; |
|
|
this.__result = []; |
|
|
this.__result = []; |
|
|
|
|
|
return this; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|