| 
				
			 | 
			
			 | 
			@@ -8,9 +8,23 @@ function ToHexString(v, l){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  return r; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			function GetStrings(s, rc){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  s = (typeof(s) === 'string') ? [s] : s; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  var m = s[0].match(/"((?:\\.|[^"\\])*)"/); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  if (m && m.length > 0){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    let i = s[0].indexOf(m[0]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (i > 0){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      s[0] = s[0].substr(0, i) + rc + s[0].substr(i + m[0].length); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      s.push(m[0]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return GetStrings(s, rc); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  return s; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			function Tokenize(l){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  var m = l.match(/([^()]+)|([()])/g); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  var ip = false; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  var ip = false;  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  var t = []; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  m.forEach((mi)=>{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (mi === "("){ | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -24,9 +38,15 @@ function Tokenize(l){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            t.push("+" + i); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        }); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        mi.split(/[\s,]+/).forEach((i)=>{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (i !== "") | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        var strs = GetStrings(mi, "*"); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        var stri = 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        strs[0].split(/[\s,]+/).forEach((i)=>{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (i === "*" && stri < strs.length){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            t.push(strs[stri].substr(1, strs[stri].length - 2)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            stri += 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          } else if (i !== ""){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            t.push(i); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        }); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -280,6 +300,35 @@ function StoreOp(data, cmp, codes, mint, maxt, zpm){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			}; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// -------------------------------------------------------------------------------------------- | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// -------------------------------------------------------------------------------------------- | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			function directive_DEFINE(data, cmp){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  // Variable label!! | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  StoreVarLabel(data, cmp.tokens[1], cmp.tokens[2]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			function directive_BYTES(data, cmp){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  // Compiler directive. Treat all proceeding tokens as values and store them raw. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  for(let i=1; i < cmp.tokens.length; i++){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    let v = Number.NaN; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (cmp.tokens[i].startsWith("$")){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      v = parseInt(cmp.tokens[i].substr(1), 16); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else if (cmp.tokens[i].startsWith("b")){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      v = parseInt(cmp.tokens[i].substr(1), 2); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      v = parseInt(cmp.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(data.PC)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmp.op.push(v); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    data.PC += 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// -------------------------------------------------------------------------------------------- | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// -------------------------------------------------------------------------------------------- | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -300,6 +349,12 @@ class Assembler{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Currently compiled code. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      result: [] | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    this.__directives = { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ".bytes":directive_BYTES, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ".byt":directive_BYTES, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ".define":directive_DEFINE, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      ".def":directive_DEFINE | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  get PC(){return this.__data.PC;} | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -336,7 +391,7 @@ class Assembler{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          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)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            throw new Error("Malformatted jump label at program address " + ToHexString(this.__data.PC)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          StoreJmpLabel(this.__data, lbl); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          line = s[1].trim(); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (line.length <= 0){return this;} // Nothing left to process. | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -344,64 +399,23 @@ class Assembler{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        // Finally... tokenize the main command. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        cmp.tokens = Tokenize(line); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (cmp.tokens[0].toLowerCase() === '.define'){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          // Variable label!! | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          StoreVarLabel(this.__data, cmp.tokens[1], cmp.tokens[2]);   | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } else if (cmp.tokens[0].toLowerCase() === '.bytes'){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          // Compiler directive. Treat all proceeding tokens as values and store them raw. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          for(let i=1; i < cmp.tokens.length; i++){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            let v = Number.NaN; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            if (cmp.tokens[i].startsWith("$")){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              v = parseInt(cmp.tokens[i].substr(1), 16); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            } else if (cmp.tokens[i].startsWith("b")){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              v = parseInt(cmp.tokens[i].substr(1), 2); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              v = parseInt(cmp.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)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            cmp.op.push(v); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            this.__data.PC += 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          }; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } else if (cmp.tokens[0].length === 3){  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        var directivesHandled = false; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (cmp.tokens[0].startsWith(".")){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          let d = cmp.tokens[0].toLowerCase(); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (d in this.__directives){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            this.__directives[d](this.__data, cmp); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            directivesHandled = true; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (!directivesHandled && cmp.tokens[0].length === 3){  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          let procFailed = false; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          let mv = null; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          // Possible op code. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          switch(cmp.tokens[0].toLowerCase()){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// --- ADC | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            case 'adc': | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              procFailed = StoreOp(this.__data, cmp, [0x69, 0x65, 0x75, 0x6D, 0x7D, 0x79, 0x61, 0x71], 2, 3); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              /* | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              if (tokens.length >= 2 && tokens.length <= 3){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                this.__PC += 2; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                switch(mv[0]){ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "i": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push(0x69); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push(mv[1]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "z": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "zX": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push((mv[0] === "z") ? 0x65 : 0x75); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push(mv[1]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "a": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "aX": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "aY": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push((mv[0] === "a") ? 0x6D : ((mv[0] === "aX") ? 0x7D : 0x79)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push(mv[1] & 0x000000FF); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push((mv[1] & 0x0000FF00) >> 8); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    this.__PC += 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "nX": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                  case "nY": | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push((mv[0] === "nX") ? 0x61 : 0x71); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    op.push(mv[1]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                    break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              } else { procFailed = true; } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              procFailed = StoreOp(this.__data, cmp, [0x69, 0x65, 0x75, 0x6D, 0x7D, 0x79, 0x61, 0x71], 2, 3); break; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// --- AND | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            case 'and': | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			              procFailed = StoreOp(this.__data, cmp, [0x29, 0x25, 0x35, 0x2D, 0x3D, 0x39, 0x21, 0x31], 2, 3);  | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -652,7 +666,8 @@ class Assembler{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (procFailed) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            throw new Error("Malformed op-code on program address " + ToHexString(this.__data.PC)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          throw new Error("Failed to compile line '" + line + "' at program address " + ToHexString(this.__data.PC)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			          if (!directivesHandled) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            throw new Error("Failed to compile line '" + line + "' at program address " + ToHexString(this.__data.PC)); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }); |