| @@ -4,8 +4,118 @@ | |||
| const BITM = require('../../utils/bitman.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 == 1 - Subtract | |||
| switch(cpu.__step){ | |||
| @@ -99,7 +209,7 @@ function MATHC(cpu, m){ // To be used by both the ADC and SBC op codes. | |||
| cpu.__op = -1; break; | |||
| } | |||
| cpu.__step += 1; | |||
| } | |||
| }*/ | |||
| function AND(cpu){ | |||
| @@ -114,7 +224,7 @@ function BIT(cpu){ | |||
| } | |||
| function BRANCH(cpu){ | |||
| switch(cpu.__step){ | |||
| switch(cpu.__cycle){ | |||
| case 0: | |||
| let branch = false; | |||
| switch(cpu.__op){ | |||
| @@ -138,7 +248,7 @@ function BRANCH(cpu){ | |||
| if (branch === false) | |||
| PCUp(cpu, 1); | |||
| case 1: | |||
| if (cpu.__step === 1){ | |||
| if (cpu.__cycle === 1){ // TODO: Huh??? | |||
| cpu.__mem.address = this.__PC; | |||
| let v = cpu.__mem.byte; | |||
| if (v > 128){ | |||
| @@ -149,7 +259,7 @@ function BRANCH(cpu){ | |||
| } | |||
| cpu.__op = -1; | |||
| } | |||
| cpu.__step += 1; | |||
| cpu.__cycle += 1; | |||
| } | |||
| function BRK(cpu){ | |||
| @@ -287,7 +397,11 @@ function RTS(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){ | |||
| @@ -305,18 +419,18 @@ function STACK(cpu){ | |||
| cpu.__op = -1; | |||
| break; | |||
| case 0x48: // PHA | |||
| if (cpu.__step === 0){ | |||
| if (cpu.__cycle === 0){ | |||
| cpu.__mem.address = 0x0100 | cpu.__SP; | |||
| } else if (cpu.__step === 1){ | |||
| } else if (cpu.__cycle === 1){ | |||
| cpu.__mem.byte = cpu.__AR; | |||
| cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | |||
| cpu.__op = -1; | |||
| } | |||
| break; | |||
| case 0x68: // PLA | |||
| if (cpu.__step === 0){ | |||
| if (cpu.__cycle === 0){ | |||
| cpu.__mem.address = 0x0100 | cpu.__SP; | |||
| } else if (cpu.__step === 1){ | |||
| } else if (cpu.__cycle === 1){ | |||
| cpu.__AR = cpu.__mem.byte; | |||
| cpu.Z = (cpu.__AR === 0); | |||
| cpu.N = BITM.isOn(cpu.__AR, 7); | |||
| @@ -326,26 +440,26 @@ function STACK(cpu){ | |||
| } | |||
| break; | |||
| case 0x08: // PHP | |||
| if (cpu.__step === 0){ | |||
| if (cpu.__cycle === 0){ | |||
| cpu.__mem.address = 0x0100 | cpu.__SP; | |||
| } else if (cpu.__step === 1){ | |||
| } else if (cpu.__cycle === 1){ | |||
| cpu.__mem.byte = cpu.__PR; | |||
| cpu.__SP = (cpu.__SP === 0) ? 255 : cpu.__SP - 1; | |||
| cpu.__op = -1; | |||
| } | |||
| break; | |||
| case 0x28: // PLP | |||
| if (cpu.__step === 0){ | |||
| if (cpu.__cycle === 0){ | |||
| cpu.__mem.address = 0x0100 | cpu.__SP; | |||
| } else if (cpu.__step === 1){ | |||
| } else if (cpu.__cycle === 1){ | |||
| 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.__op = -1; | |||
| } | |||
| break; | |||
| } | |||
| cpu.__step += 1; | |||
| cpu.__cycle += 1; | |||
| } | |||
| function STX(cpu){ | |||
| @@ -446,7 +560,7 @@ class CPU{ | |||
| this.__op = -1; | |||
| this.__opmem = 0; | |||
| this.__opv = 0; | |||
| this.__step = 0; | |||
| this.__cycle = 0; | |||
| this.__pcc = 0; // Program Counter Carry. | |||
| // Memory module or controller. | |||
| @@ -541,7 +655,7 @@ class CPU{ | |||
| // TODO: Handle IRQ Interrupt. | |||
| } | |||
| } else { | |||
| this.__step = 0; | |||
| this.__cycle = 0; | |||
| this.__mem.address = this.__PC; | |||
| this.__op = this.__mem.byte; | |||
| PCUp(this, 1); | |||
| @@ -549,7 +663,7 @@ class CPU{ | |||
| } else { | |||
| switch(this.__op){ | |||
| 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: | |||
| AND(this); break; | |||
| case 0x0A: case 0x06: case 0x16: case 0x0E: case 0x1E: | |||
| @@ -605,7 +719,7 @@ class CPU{ | |||
| case 0x60: | |||
| RTS(this); break; | |||
| 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: | |||
| STA(this); break; | |||
| case 0x9A: case 0xBA: case 0x48: case 0x68: case 0x08: case 0x28: | |||