diff --git a/src/cpu.c b/src/cpu.c index 3d1d8c4..9c39d64 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1,7 +1,7 @@ /* Fake6502 CPU emulator core v1.1 ******************* * (c)2011-2013 Mike Chambers * * * - * Modified by Gabriel Weingardt * + * Modified for 65c02 by Gabriel Weingardt * *****************************************************/ #include @@ -130,6 +130,10 @@ static void zp() { //zero-page ea = (uint16_t)read6502((uint16_t)pc++); } +static void izp() { // zero-page indirect (new 65c02 instruction) + +} + static void zpx() { //zero-page,X ea = ((uint16_t)read6502((uint16_t)pc++) + (uint16_t)x) & 0xFF; //zero-page wraparound } @@ -201,6 +205,16 @@ static void indy() { // (indirect),Y } } +// new 65c02 address mode +static void aii() { // absolute indexed indirect + uint16_t eahelp, eahelp2; + eahelp = ((uint16_t)read6502(pc) | ((uint16_t)read6502(pc+1) << 8)) + x; + eahelp2 = (eahelp & 0xFF00) | ((eahelp + 1) & 0x00FF); //replicate 6502 page-boundary wraparound bug + ea = (uint16_t)read6502(eahelp) | ((uint16_t)read6502(eahelp2) << 8); + pc += 2; +} + + static uint16_t getvalue() { if (addrtable[opcode] == acc) return((uint16_t)a); else return((uint16_t)read6502(ea)); @@ -336,6 +350,37 @@ static void bvs() { } } +static void bra() { // new 65c02 instruction + oldpc = pc; + pc += reladdr; + if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary + else clockticks6502++; +} + +static void bbr() { // new 65c02 instruction + uint8_t testval = 1; + for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1; + + if (!(a & testval)) { + oldpc = pc; + pc += reladdr; + if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary + else clockticks6502++; + } +} + +static void bbs() { // new 65c02 instruction + uint8_t testval = 1; + for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1; + + if (a & testval) { + oldpc = pc; + pc += reladdr; + if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary + else clockticks6502++; + } +} + static void clc() { clearcarry(); } @@ -522,9 +567,18 @@ static void pha() { } static void php() { - push8(status | FLAG_BREAK); + push8(status); } +static void phy() { // new 65c02 instruction + push8(y); +} + +static void phx() { // new 65c02 instruction + push8(x); +} + + static void pla() { a = pull8(); @@ -536,6 +590,21 @@ static void plp() { status = pull8() | FLAG_CONSTANT; } + +static void ply() { // new 65c02 instruction + y = pull8(); + + zerocalc(y); + signcalc(y); +} + +static void plx() { // new 65c02 instruction + a = pull8(); + + zerocalc(x); + signcalc(x); +} + static void rol() { value = getvalue(); result = (value << 1) | (status & FLAG_CARRY); @@ -608,6 +677,10 @@ static void sty() { putvalue(y); } +static void stz() { // new 65c02 instruction + putvalue(0); +} + static void tax() { x = a; @@ -647,44 +720,88 @@ static void tya() { signcalc(a); } -static void (*addrtable[256])() = { -/* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */ -/* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 0 */ -/* 1 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 1 */ -/* 2 */ abso, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 2 */ -/* 3 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 3 */ -/* 4 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, abso, /* 4 */ -/* 5 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 5 */ -/* 6 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, ind, abso, abso, abso, /* 6 */ -/* 7 */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* 7 */ -/* 8 */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* 8 */ -/* 9 */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* 9 */ -/* A */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* A */ -/* B */ rel, indy, imp, indy, zpx, zpx, zpy, zpy, imp, absy, imp, absy, absx, absx, absy, absy, /* B */ -/* C */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* C */ -/* D */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx, /* D */ -/* E */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, abso, /* E */ -/* F */ rel, indy, imp, indy, zpx, zpx, zpx, zpx, imp, absy, imp, absy, absx, absx, absx, absx /* F */ -}; +static void trb() { // new 65c02 instruction + value = getvalue(); + result = value & ~a; + + zerocalc(result); + putvalue(result); +} + +static void tsb() { // new 65c02 instruction + value = getvalue(); + result = value | a; + + zerocalc(result); + putvalue(result); +} + +static void rmb() { // new 65c02 instruction + uint8_t testval = 1; + for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1; + + value = getvalue(); + result = value & ~testval; + + putvalue(result); +} + +static void smb() { // new 65c02 instruction + uint8_t testval = 1; + for (int i = 0; i < ((opcode & 0b01110000) >> 4); i++) testval = testval << 1; + + value = getvalue(); + result = value | testval; + + putvalue(result); +} + +static void wai() { // new 65c02 instruction + // implement later +} + +static void stp() { // new 65c02 instruction + // implement later +} static void (*optable[256])() = { /* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */ -/* 0 */ brk, ora, nop, nop, nop, ora, asl, nop, php, ora, asl, nop, nop, ora, asl, nop, /* 0 */ -/* 1 */ bpl, ora, nop, nop, nop, ora, asl, nop, clc, ora, nop, nop, nop, ora, asl, nop, /* 1 */ -/* 2 */ jsr, and, nop, nop, bit, and, rol, nop, plp, and, rol, nop, bit, and, rol, nop, /* 2 */ -/* 3 */ bmi, and, nop, nop, nop, and, rol, nop, sec, and, nop, nop, nop, and, rol, nop, /* 3 */ -/* 4 */ rti, eor, nop, nop, nop, eor, lsr, nop, pha, eor, lsr, nop, jmp, eor, lsr, nop, /* 4 */ -/* 5 */ bvc, eor, nop, nop, nop, eor, lsr, nop, cli, eor, nop, nop, nop, eor, lsr, nop, /* 5 */ -/* 6 */ rts, adc, nop, nop, nop, adc, ror, nop, pla, adc, ror, nop, jmp, adc, ror, nop, /* 6 */ -/* 7 */ bvs, adc, nop, nop, nop, adc, ror, nop, sei, adc, nop, nop, nop, adc, ror, nop, /* 7 */ -/* 8 */ nop, sta, nop, nop, sty, sta, stx, nop, dey, nop, txa, nop, sty, sta, stx, nop, /* 8 */ -/* 9 */ bcc, sta, nop, nop, sty, sta, stx, nop, tya, sta, txs, nop, nop, sta, nop, nop, /* 9 */ -/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, nop, tay, lda, tax, nop, ldy, lda, ldx, nop, /* A */ -/* B */ bcs, lda, nop, nop, ldy, lda, ldx, nop, clv, lda, tsx, nop, ldy, lda, ldx, nop, /* B */ -/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, nop, iny, cmp, dex, nop, cpy, cmp, dec, nop, /* C */ -/* D */ bne, cmp, nop, nop, nop, cmp, dec, nop, cld, cmp, nop, nop, nop, cmp, dec, nop, /* D */ -/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, nop, inx, sbc, nop, sbc, cpx, sbc, inc, nop, /* E */ -/* F */ beq, sbc, nop, nop, nop, sbc, inc, nop, sed, sbc, nop, nop, nop, sbc, inc, nop /* F */ +/* 0 */ brk, ora, nop, nop, tsb, ora, asl, rmb, php, ora, asl, nop, tsb, ora, asl, bbr, /* 0 */ +/* 1 */ bpl, ora, ora, nop, trb, ora, asl, rmb, clc, ora, inc, nop, trb, ora, asl, bbr, /* 1 */ +/* 2 */ jsr, and, nop, nop, bit, and, rol, rmb, plp, and, rol, nop, bit, and, rol, bbr, /* 2 */ +/* 3 */ bmi, and, and, nop, bit, and, rol, rmb, sec, and, dec, nop, bit, and, rol, bbr, /* 3 */ +/* 4 */ rti, eor, nop, nop, nop, eor, lsr, rmb, pha, eor, lsr, nop, jmp, eor, lsr, bbr, /* 4 */ +/* 5 */ bvc, eor, eor, nop, nop, eor, lsr, rmb, cli, eor, phy, nop, nop, eor, lsr, bbr, /* 5 */ +/* 6 */ rts, adc, nop, nop, stz, adc, ror, rmb, pla, adc, ror, nop, jmp, adc, ror, bbr, /* 6 */ +/* 7 */ bvs, adc, adc, nop, stz, adc, ror, rmb, sei, adc, ply, nop, jmp, adc, ror, bbr, /* 7 */ +/* 8 */ bra, sta, nop, nop, sty, sta, stx, smb, dey, bit, txa, nop, sty, sta, stx, bbs, /* 8 */ +/* 9 */ bcc, sta, sta, nop, sty, sta, stx, smb, tya, sta, txs, nop, stz, sta, stz, bbs, /* 9 */ +/* A */ ldy, lda, ldx, nop, ldy, lda, ldx, smb, tay, lda, tax, nop, ldy, lda, ldx, bbs, /* A */ +/* B */ bcs, lda, lda, nop, ldy, lda, ldx, smb, clv, lda, tsx, nop, ldy, lda, ldx, bbs, /* B */ +/* C */ cpy, cmp, nop, nop, cpy, cmp, dec, smb, iny, cmp, dex, wai, cpy, cmp, dec, bbs, /* C */ +/* D */ bne, cmp, cmp, nop, nop, cmp, dec, smb, cld, cmp, phx, stp, nop, cmp, dec, bbs, /* D */ +/* E */ cpx, sbc, nop, nop, cpx, sbc, inc, smb, inx, sbc, nop, sbc, cpx, sbc, inc, bbs, /* E */ +/* F */ beq, sbc, sbc, nop, nop, sbc, inc, smb, sed, sbc, plx, nop, nop, sbc, inc, bbs /* F */ +}; + +static void (*addrtable[256])() = { + /* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | */ + /* 0 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, rel, /* 0 */ + /* 1 */ rel, indy, izp, indy, zp, zpx, zpx, zp, imp, absy, acc, absy, abso, absx, absx, rel, /* 1 */ + /* 2 */ abso, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, rel, /* 2 */ + /* 3 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, acc, absy, absx, absx, absx, rel, /* 3 */ + /* 4 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, abso, abso, abso, rel, /* 4 */ + /* 5 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, absx, absx, absx, rel, /* 5 */ + /* 6 */ imp, indx, imp, indx, zp, zp, zp, zp, imp, imm, acc, imm, ind, abso, abso, rel, /* 6 */ + /* 7 */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, aii, absx, absx, rel, /* 7 */ + /* 8 */ rel, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* 8 */ + /* 9 */ rel, indy, izp, indy, zpx, zpx, zpy, zp, imp, absy, imp, absy, abso, absx, absx, rel, /* 9 */ + /* A */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* A */ + /* B */ rel, indy, izp, indy, zpx, zpx, zpy, zp, imp, absy, imp, absy, absx, absx, absy, rel, /* B */ + /* C */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imp, abso, abso, abso, rel, /* C */ + /* D */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, imp, absx, absx, absx, rel, /* D */ + /* E */ imm, indx, imm, indx, zp, zp, zp, zp, imp, imm, imp, imm, abso, abso, abso, rel, /* E */ + /* F */ rel, indy, izp, indy, zpx, zpx, zpx, zp, imp, absy, imp, absy, absx, absx, absx, rel /* F */ }; static const uint32_t ticktable[256] = { @@ -716,10 +833,14 @@ void nmi6502() { } void irq6502() { - push16(pc); - push8(status); - status |= FLAG_INTERRUPT; - pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8); + // only initiate interrupts when interrupt flag is cleared + + if (!(status & FLAG_INTERRUPT)){ + push16(pc); + push8(status); + status |= FLAG_INTERRUPT; + pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8); + } } void step6502() {