| // Variable label!! | // Variable label!! | ||||
| } else if (tokens[0][tokens[0].length - 1] === ':'){ | } else if (tokens[0][tokens[0].length - 1] === ':'){ | ||||
| // Jump label!! | // Jump label!! | ||||
| } else if (tokens[0].length === 3){ | |||||
| } else if (tokens[0].length === 3){ | |||||
| let StoreSingleOp = (code)=>{ | |||||
| if (tokens.length === 1){ | |||||
| op.push(code); | |||||
| this.__PC += 1; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| }; | |||||
| let StoreBranchOp = (code) => { | |||||
| if (tokens.length === 2){ | |||||
| if (token[1][0] === '$' && (tokens[1].length === 3 || tokens[1].length === 5)){ | |||||
| let v = parseInt(token[1].substr(1), 16); | |||||
| if (isNaN(v)) | |||||
| return false; | |||||
| 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; | |||||
| op.push(code); | |||||
| op.push((v >= 0) ? v : v + 255); | |||||
| this.__PC += 2; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| }; | |||||
| let StoreOp = (codes, mint, maxt) => { | |||||
| if (tokens.length >= mint && tokens.length <= maxt){ | |||||
| let mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null); | |||||
| let modea = true; | |||||
| switch(mv[0]){ | |||||
| case "i": | |||||
| modea = codes[0] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[0]); | |||||
| op.push(mv[1]); | |||||
| this.__PC += 2; | |||||
| } break; | |||||
| case "z": | |||||
| modea = codes[1] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[1]); | |||||
| op.push(mv[1]); | |||||
| this.__PC += 2; | |||||
| } break; | |||||
| case "zX": | |||||
| modea = codes[2] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[2]); | |||||
| op.push(mv[1]); | |||||
| this.__PC += 2; | |||||
| } break; | |||||
| case "a": | |||||
| modea = codes[3] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[3]); | |||||
| op.push(mv[1] & 0x000000FF); | |||||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } break; | |||||
| case "aX": | |||||
| modea = codes[4] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[4]); | |||||
| op.push(mv[1] & 0x000000FF); | |||||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } break; | |||||
| case "aY": | |||||
| modea = codes[5] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[5]); | |||||
| op.push(mv[1] & 0x000000FF); | |||||
| op.push((mv[1] & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } break; | |||||
| case "nX": | |||||
| modea = codes[6] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[6]); | |||||
| op.push(mv[1]); | |||||
| this.__PC += 2; | |||||
| } break; | |||||
| case "nY": | |||||
| modea = codes[7] !== null; | |||||
| if (modea){ | |||||
| op.push(codes[7]); | |||||
| op.push(mv[1]); | |||||
| this.__PC += 2; | |||||
| } break; | |||||
| } | |||||
| if (modea === false) | |||||
| throw new Error("Op-code does not support implied mode on program address " + toHexString(this.__PC)); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| }; | |||||
| let procFailed = false; | let procFailed = false; | ||||
| let mv = null; | let mv = null; | ||||
| // Possible op code. | // Possible op code. | ||||
| switch(tokens[0].toLowerCase()){ | switch(tokens[0].toLowerCase()){ | ||||
| // --- ADC | // --- ADC | ||||
| case 'adc': | case 'adc': | ||||
| procFailed = StoreOp([0x69, 0x65, 0x75, 0x6D, 0x7D, 0x79, 0x61, 0x71], 2, 3); | |||||
| /* | |||||
| if (tokens.length >= 2 && tokens.length <= 3){ | if (tokens.length >= 2 && tokens.length <= 3){ | ||||
| mv = addrModeVal(tokens[1]); | |||||
| mv = addrModeVal(tokens[1], (tokens.length === 3) ? tokens[2].toUpperCase(), null); | |||||
| this.__PC += 2; | this.__PC += 2; | ||||
| switch(mv[0]){ | switch(mv[0]){ | ||||
| case "i": | case "i": | ||||
| break; | break; | ||||
| } | } | ||||
| } else { procFailed = true; } | } else { procFailed = true; } | ||||
| */ | |||||
| break; | break; | ||||
| // --- AND | // --- AND | ||||
| case 'and': | case 'and': | ||||
| procFailed = StoreOp([0x29, 0x25, 0x35, 0x2D, 0x3D, 0x39, 0x21, 0x31], 2, 3); | |||||
| break; | break; | ||||
| // --- ASL | // --- ASL | ||||
| case 'asl': | case 'asl': | ||||
| if (tokens.length === 2){ | |||||
| if (tokens[1].toUpperCase() === 'A'){ | |||||
| op.push(0x0A); | |||||
| this.__PC += 1; | |||||
| break; | |||||
| } | |||||
| } | |||||
| procFailed = StoreOp([null, 0x06, 0x16, 0x0E, 0x1E, null, null, null], 2, 3); | |||||
| break; | break; | ||||
| // --- BCC | // --- BCC | ||||
| case 'bcc': | case 'bcc': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0x90); break; | |||||
| // --- BCS | // --- BCS | ||||
| case 'bcs': | case 'bcs': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0xB0); break; | |||||
| // --- BEQ | // --- BEQ | ||||
| case 'beq': | case 'beq': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0xF0); break; | |||||
| // --- BIT | |||||
| case 'bit': | case 'bit': | ||||
| break; | |||||
| procFailed = StoreOp([null, 0x24, null, 0x2C, null, null, null, null], 2, 2); break; | |||||
| // --- BMI | |||||
| case 'bmi': | case 'bmi': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0x30); break; | |||||
| // --- BNE | |||||
| case 'bne': | case 'bne': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0xD0); break; | |||||
| // --- BPL | |||||
| case 'bpl': | case 'bpl': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0x10); break; | |||||
| // --- BRK | // --- BRK | ||||
| case 'brk': | case 'brk': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x00); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x00); break; | |||||
| // --- BVC | |||||
| case 'bvc': | case 'bvc': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0x50); break; | |||||
| // --- BVS | |||||
| case 'bvs': | case 'bvs': | ||||
| break; | |||||
| procFailed = StoreBranchOp(0x70); break; | |||||
| // --- CLC | // --- CLC | ||||
| case 'clc': | case 'clc': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x18); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x18); break; | |||||
| // --- CLD | // --- CLD | ||||
| case 'cld': | case 'cld': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xD8); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xD8); break; | |||||
| // --- CLI | // --- CLI | ||||
| case 'cli': | case 'cli': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x58); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x58); break; | |||||
| // --- CLV | // --- CLV | ||||
| case 'clv': | case 'clv': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xB8); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xB8); break; | |||||
| // --- CMP | |||||
| case 'cmp': | case 'cmp': | ||||
| break; | |||||
| procFailed = StoreOp([0xC9, 0xC5, 0xD5, 0xCD, 0xDD, 0xD9, 0xC1, 0xD1], 2, 3); break; | |||||
| // --- CPX | |||||
| case 'cpx': | case 'cpx': | ||||
| break; | |||||
| procFailed = StoreOp([0xE0, 0xE4, null, 0xEC, null, null, null, null], 2, 2); break; | |||||
| // --- CPY | |||||
| case 'cpy': | case 'cpy': | ||||
| break; | |||||
| procFailed = StoreOp([0xC0, 0xC4, null, 0xCC, null, null, null, null], 2, 2); break; | |||||
| // --- DEC | |||||
| case 'dec': | case 'dec': | ||||
| break; | |||||
| procFailed = StoreOp([null, 0xC6, 0xD6, 0xCE, 0xDE, null, null, null], 2, 3); break; | |||||
| // --- DEX | // --- DEX | ||||
| case 'dex': | case 'dex': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xCA); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xCA); break; | |||||
| // --- DEY | // --- DEY | ||||
| case 'dey': | case 'dey': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x88); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x88); break; | |||||
| // --- EOR | |||||
| case 'eor': | case 'eor': | ||||
| break; | |||||
| procFailed = StoreOp([0x49, 0x45, 0x55, 0x4D, 0x5D, 0x59, 0x41, 0x51], 2, 3); break; | |||||
| // --- INC | |||||
| case 'inc': | case 'inc': | ||||
| break; | |||||
| procFailed = StoreOp([null, 0xE6, 0xF6, 0xEE, 0xFE, null, null, null], 2, 3); break; | |||||
| // --- INX | // --- INX | ||||
| case 'inx': | case 'inx': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xE8); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xE8); break; | |||||
| // --- INY | // --- INY | ||||
| case 'iny': | case 'iny': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xC8); | |||||
| this.__PC += 1 | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xC8); break; | |||||
| // --- JMP | |||||
| case 'jmp': | case 'jmp': | ||||
| break; | break; | ||||
| // --- JSR | |||||
| case 'jsr': | case 'jsr': | ||||
| break; | break; | ||||
| // --- LDA | |||||
| case 'lda': | case 'lda': | ||||
| break; | break; | ||||
| // --- LDX | |||||
| case 'ldx': | case 'ldx': | ||||
| break; | break; | ||||
| // --- LDY | |||||
| case 'ldy': | case 'ldy': | ||||
| break; | break; | ||||
| // --- LSR | |||||
| case 'lsr': | case 'lsr': | ||||
| break; | break; | ||||
| // --- NOP | // --- NOP | ||||
| case 'nop': | case 'nop': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xEA); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xEA); break; | |||||
| // --- ORA | |||||
| case 'ora': | case 'ora': | ||||
| break; | break; | ||||
| // --- PHA | |||||
| case 'pha': | case 'pha': | ||||
| break; | break; | ||||
| // --- PHP | |||||
| case 'php': | case 'php': | ||||
| break; | break; | ||||
| // --- PLA | |||||
| case 'pla': | case 'pla': | ||||
| break; | break; | ||||
| // --- PLP | |||||
| case 'plp': | case 'plp': | ||||
| break; | break; | ||||
| // --- ROL | |||||
| case 'rol': | case 'rol': | ||||
| break; | break; | ||||
| // --- ROR | |||||
| case 'ror': | case 'ror': | ||||
| break; | break; | ||||
| // --- RTI | |||||
| case 'rti': | case 'rti': | ||||
| break; | break; | ||||
| // --- RTS | |||||
| case 'rts': | case 'rts': | ||||
| break; | break; | ||||
| // --- SBC | |||||
| case 'sbc': | case 'sbc': | ||||
| break; | break; | ||||
| // --- SEC | // --- SEC | ||||
| case 'sec': | case 'sec': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x38); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x38); break; | |||||
| // --- SED | // --- SED | ||||
| case 'sed': | case 'sed': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xF8); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xF8); break; | |||||
| // --- SEI | // --- SEI | ||||
| case 'sei': | case 'sei': | ||||
| op.push(0x78); | |||||
| this.__PC += 1; | |||||
| procFailed = StoreSingleOp(0x78); break; | |||||
| break; | break; | ||||
| // --- STA | |||||
| case 'sta': | case 'sta': | ||||
| break; | break; | ||||
| // --- STX | |||||
| case 'stx': | case 'stx': | ||||
| break; | break; | ||||
| // --- STY | |||||
| case 'sty': | case 'sty': | ||||
| break; | break; | ||||
| // --- TAX | // --- TAX | ||||
| case 'tax': | case 'tax': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xAA); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xAA); break; | |||||
| // --- TAY | // --- TAY | ||||
| case 'tay': | case 'tay': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0xA8); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0xA8); break; | |||||
| // --- TSX | // --- TSX | ||||
| case 'tsx': | case 'tsx': | ||||
| break; | break; | ||||
| // --- TXA | // --- TXA | ||||
| case 'txa': | case 'txa': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x8A); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x8A); break; | |||||
| // --- TXS | // --- TXS | ||||
| case 'txs': | case 'txs': | ||||
| break; | break; | ||||
| // --- TYA | // --- TYA | ||||
| case 'tya': | case 'tya': | ||||
| if (tokens.length === 1){ | |||||
| op.push(0x98); | |||||
| this.__PC += 1; | |||||
| } else { procFailed = true; } | |||||
| break; | |||||
| procFailed = StoreSingleOp(0x98); break; | |||||
| // --- --- | // --- --- | ||||
| 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)); |