| const BITM = require('../../utils/bitman.js'); | const BITM = require('../../utils/bitman.js'); | ||||
| var Memory = require('../../common/memory.js'); | var Memory = require('../../common/memory.js'); | ||||
| // mode = 0 - Immediate | |||||
| // mode = 1 - Zero Page | |||||
| // mode = 2 - Zero Page, X | |||||
| // mode = 3 - Zero Page, Y | |||||
| // mode = 4 - Absolute | |||||
| // mode = 5 - Absolute, X | |||||
| // mode = 6 - Absolute, Y | |||||
| // mode = 7 - Indirect, X | |||||
| // mode = 8 - Indirect, Y | |||||
| function ProcessOp(cpu, mode){ | |||||
| switch(cpu.__cycle){ | |||||
| case 0: | |||||
| cpu.__mem.address = cpu.__PC; | |||||
| PCUp(cpu, 1); | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return (mode === 0); | |||||
| case 1: | |||||
| switch(mode){ | |||||
| case 1: // Zero Page | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| case 2: // Zero Page, X | |||||
| case 3: // Zero Page, Y | |||||
| cpu.__opv = (cpu.__opv + ((mode === 2) ? cpu.__XR : cpu.__YR)) & 0xFF; break; | |||||
| case 4: // Absolute | |||||
| case 5: // Absolute, X | |||||
| case 6: // Absolute, Y | |||||
| cpu.__mem.address = cpu.__PC; | |||||
| PCUp(cpu, 1); | |||||
| cpu.__opv |= cpu.__mem.byte << 8; | |||||
| break; | |||||
| case 7: // Indirect, X | |||||
| cpu.__opv = (cpu.__opv + cpu.__XR) & 0xFF; break; | |||||
| case 8: // Indirect, Y | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| break; | |||||
| } break; | |||||
| case 2: | |||||
| switch(mode){ | |||||
| case 2: // Zero Page, X | |||||
| case 3: // Zero Page, Y | |||||
| case 4: // Absolute | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| case 5: // Absolute, X | |||||
| case 6: // Absolute, Y | |||||
| let s = (mode === 5) ? cpu.__XR : cpu.__YR; | |||||
| let l = (cpu.__opv & 0xFF) + s; | |||||
| cpu.__opv = (cpu.__opv & 0xFF00) | (l & 0xFF); | |||||
| if (l < 255){ | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| } | |||||
| break; | |||||
| case 7: // Indirect, X | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| break; | |||||
| case 8: // Indirect, Y | |||||
| cpu.__mem.address += 1; | |||||
| cpu.__opv |= cpu.__mem.byte << 8; | |||||
| break; | |||||
| } break; | |||||
| case 3: | |||||
| switch(mode){ | |||||
| case 5: // Absolute, X | |||||
| case 6: // Absolute, Y | |||||
| let h = (cpu.__opv >> 8) + 1; | |||||
| cpu.__mem.address = (cpu.__opv & 0xFF) | (h << 8); | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| case 7: // Indirect, X | |||||
| cpu.__mem.address += 1; | |||||
| cpu.__opv |= cpu.__mem.byte << 8; | |||||
| break; | |||||
| case 8: // Indirect, Y | |||||
| let l = (cpu.__opv & 0xFF) + cpu.__YR; | |||||
| cpu.__opv = (cpu.__opv & 0xFF00) | (l & 0xFF); | |||||
| if (l <= 255){ | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| } | |||||
| break; | |||||
| } break; | |||||
| case 4: | |||||
| if (mode === 8){ | |||||
| let h = (cpu.__opv >> 8) + 1; | |||||
| cpu.__opv = (cpu.__opv & 0x00FF) | (h << 8); | |||||
| } | |||||
| cpu.__mem.address = cpu.__opv; | |||||
| cpu.__opv = cpu.__mem.byte; | |||||
| return true; | |||||
| } | |||||
| cpu.__cycle += 1; | |||||
| return false; | |||||
| } | |||||
| function MATHC(cpu, m){ // To be used by both the ADC and SBC op codes. | |||||
| function ADC(cpu){ // To be used by both the ADC and SBC op codes. | |||||
| let pmode = [0x69, 0x65, 0x75, null, 0x6D, 0x7D, 0x79, 0x61, 0x71].indexOf(cpu.__op); | |||||
| if (ProcessOp(cpu, pmode) === true){ | |||||
| cpu.__op = -1; | |||||
| ALU(cpu, 0, cpu.__opv); | |||||
| } | |||||
| } | |||||
| /*function MATHC(cpu, m){ // To be used by both the ADC and SBC op codes. | |||||
| // m == 0 - Add | // m == 0 - Add | ||||
| // m == 1 - Subtract | // m == 1 - Subtract | ||||
| switch(cpu.__step){ | switch(cpu.__step){ | ||||
| cpu.__op = -1; break; | cpu.__op = -1; break; | ||||
| } | } | ||||
| cpu.__step += 1; | cpu.__step += 1; | ||||
| } | |||||
| }*/ | |||||
| function AND(cpu){ | function AND(cpu){ | ||||
| } | } | ||||
| function BRANCH(cpu){ | function BRANCH(cpu){ | ||||
| switch(cpu.__step){ | |||||
| switch(cpu.__cycle){ | |||||
| case 0: | case 0: | ||||
| let branch = false; | let branch = false; | ||||
| switch(cpu.__op){ | switch(cpu.__op){ | ||||
| if (branch === false) | if (branch === false) | ||||
| PCUp(cpu, 1); | PCUp(cpu, 1); | ||||
| case 1: | case 1: | ||||
| if (cpu.__step === 1){ | |||||
| if (cpu.__cycle === 1){ // TODO: Huh??? | |||||
| cpu.__mem.address = this.__PC; | cpu.__mem.address = this.__PC; | ||||
| let v = cpu.__mem.byte; | let v = cpu.__mem.byte; | ||||
| if (v > 128){ | if (v > 128){ | ||||
| } | } | ||||
| cpu.__op = -1; | cpu.__op = -1; | ||||
| } | } | ||||
| cpu.__step += 1; | |||||
| cpu.__cycle += 1; | |||||
| } | } | ||||
| function BRK(cpu){ | function BRK(cpu){ | ||||
| } | } | ||||
| function SBC(cpu){ | function SBC(cpu){ | ||||
| let pmode = [0xE9, 0xE5, 0xF5, null, 0xED, 0xFD, 0xF9, 0xE1, 0xF1].indexOf(cpu.__op); | |||||
| if (ProcessOp(cpu, pmode) === true){ | |||||
| cpu.__op = -1; | |||||
| ALU(cpu, 1, cpu.__opv); | |||||
| } | |||||
| } | } | ||||
| function STA(cpu){ | function STA(cpu){ | ||||
| cpu.__op = -1; | cpu.__op = -1; | ||||
| break; | break; | ||||
| case 0x48: // PHA | case 0x48: // PHA | ||||
| if (cpu.__step === 0){ | |||||
| if (cpu.__cycle === 0){ | |||||
| cpu.__mem.address = 0x0100 | cpu.__SP; | cpu.__mem.address = 0x0100 | cpu.__SP; | ||||
| } else if (cpu.__step === 1){ | |||||
| } else if (cpu.__cycle === 1){ | |||||
| cpu.__mem.byte = cpu.__AR; | cpu.__mem.byte = cpu.__AR; | ||||
| cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | ||||
| cpu.__op = -1; | cpu.__op = -1; | ||||
| } | } | ||||
| break; | break; | ||||
| case 0x68: // PLA | case 0x68: // PLA | ||||
| if (cpu.__step === 0){ | |||||
| if (cpu.__cycle === 0){ | |||||
| cpu.__mem.address = 0x0100 | cpu.__SP; | cpu.__mem.address = 0x0100 | cpu.__SP; | ||||
| } else if (cpu.__step === 1){ | |||||
| } else if (cpu.__cycle === 1){ | |||||
| cpu.__AR = cpu.__mem.byte; | cpu.__AR = cpu.__mem.byte; | ||||
| cpu.Z = (cpu.__AR === 0); | cpu.Z = (cpu.__AR === 0); | ||||
| cpu.N = BITM.isOn(cpu.__AR, 7); | cpu.N = BITM.isOn(cpu.__AR, 7); | ||||
| } | } | ||||
| break; | break; | ||||
| case 0x08: // PHP | case 0x08: // PHP | ||||
| if (cpu.__step === 0){ | |||||
| if (cpu.__cycle === 0){ | |||||
| cpu.__mem.address = 0x0100 | cpu.__SP; | cpu.__mem.address = 0x0100 | cpu.__SP; | ||||
| } else if (cpu.__step === 1){ | |||||
| } else if (cpu.__cycle === 1){ | |||||
| cpu.__mem.byte = cpu.__PR; | cpu.__mem.byte = cpu.__PR; | ||||
| cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | ||||
| cpu.__op = -1; | cpu.__op = -1; | ||||
| } | } | ||||
| break; | break; | ||||
| case 0x28: // PLP | case 0x28: // PLP | ||||
| if (cpu.__step === 0){ | |||||
| if (cpu.__cycle === 0){ | |||||
| cpu.__mem.address = 0x0100 | cpu.__SP; | cpu.__mem.address = 0x0100 | cpu.__SP; | ||||
| } else if (cpu.__step === 1){ | |||||
| } else if (cpu.__cycle === 1){ | |||||
| cpu.__SP = cpu.__mem.byte; | cpu.__SP = cpu.__mem.byte; | ||||
| } else if (cpu.__step === 2){ | |||||
| } else if (cpu.__cycle === 2){ | |||||
| cpu.__SP = (cpu.__SP === 255) ? 0 : cpu.__SP + 1; | cpu.__SP = (cpu.__SP === 255) ? 0 : cpu.__SP + 1; | ||||
| cpu.__op = -1; | cpu.__op = -1; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| cpu.__step += 1; | |||||
| cpu.__cycle += 1; | |||||
| } | } | ||||
| function STX(cpu){ | function STX(cpu){ | ||||
| this.__op = -1; | this.__op = -1; | ||||
| this.__opmem = 0; | this.__opmem = 0; | ||||
| this.__opv = 0; | this.__opv = 0; | ||||
| this.__step = 0; | |||||
| this.__cycle = 0; | |||||
| this.__pcc = 0; // Program Counter Carry. | this.__pcc = 0; // Program Counter Carry. | ||||
| // Memory module or controller. | // Memory module or controller. | ||||
| // TODO: Handle IRQ Interrupt. | // TODO: Handle IRQ Interrupt. | ||||
| } | } | ||||
| } else { | } else { | ||||
| this.__step = 0; | |||||
| this.__cycle = 0; | |||||
| this.__mem.address = this.__PC; | this.__mem.address = this.__PC; | ||||
| this.__op = this.__mem.byte; | this.__op = this.__mem.byte; | ||||
| PCUp(this, 1); | PCUp(this, 1); | ||||
| } else { | } else { | ||||
| switch(this.__op){ | switch(this.__op){ | ||||
| case 0x69: case 0x65: case 0x75: case 0x6D: case 0x7D: case 0x79: case 0x61: case 0x71: | case 0x69: case 0x65: case 0x75: case 0x6D: case 0x7D: case 0x79: case 0x61: case 0x71: | ||||
| MATHC(this, 0); break; | |||||
| ADC(this); break; | |||||
| case 0x29: case 0x25: case 0x35: case 0x2D: case 0x3D: case 0x39: case 0x21: case 0x31: | case 0x29: case 0x25: case 0x35: case 0x2D: case 0x3D: case 0x39: case 0x21: case 0x31: | ||||
| AND(this); break; | AND(this); break; | ||||
| case 0x0A: case 0x06: case 0x16: case 0x0E: case 0x1E: | case 0x0A: case 0x06: case 0x16: case 0x0E: case 0x1E: | ||||
| case 0x60: | case 0x60: | ||||
| RTS(this); break; | RTS(this); break; | ||||
| case 0xE9: case 0xE5: case 0xF5: case 0xED: case 0xFD: case 0xF9: case 0xE1: case 0xF1: | case 0xE9: case 0xE5: case 0xF5: case 0xED: case 0xFD: case 0xF9: case 0xE1: case 0xF1: | ||||
| MATHC(this, 1); break; | |||||
| SBC(this); break; | |||||
| case 0x85: case 0x95: case 0x8D: case 0x9D: case 0x99: case 0x81: case 0x91: | case 0x85: case 0x95: case 0x8D: case 0x9D: case 0x99: case 0x81: case 0x91: | ||||
| STA(this); break; | STA(this); break; | ||||
| case 0x9A: case 0xBA: case 0x48: case 0x68: case 0x08: case 0x28: | case 0x9A: case 0xBA: case 0x48: case 0x68: case 0x08: case 0x28: |