Status: Initializing...
#include "c64.h"
#include "instr.h"
/*
+-+-+-+-+-+-+-+-+
|N|V| |B|D|I|Z|C| PROCESSOR STATUS REG "P"
+-+-+-+-+-+-+-+-+
| | | | | | |
| | | | | | +> CARRY 1=TRUE
| | | | | +--> ZERO 1=RESULT ZERO
| | | | +----> IRQ DISABLE 1=DISABLE
| | | +------> DECIMAL MODE 1=TRUE
| | +--------> BRK COMMAND
| |
| +------------> OVERFLOW 1=TRUE
+--------------> NEGATIVE 1=NEG
*/
extern FILE *_log, *_ilog;
extern FILE *_cialog;
extern struct writelog _wlog[10];
extern int _widx;
extern int _timerA1, _timerA1L, _keydown;
extern uint8_t _ics1;
enum {
P_CARRY = 1, P_ZERO = 2, P_IRQDIS = 4, P_DECIMAL = 8, P_BRK = 16,
P_OVERFLOW = 64, P_NEGATIVE = 128
};
uint16_t _PC;
uint8_t _A, _X, _Y, _S, _P, _IR;
int _HWIRQ = 0, _NMI = 0;
extern struct memory _page[64];
int crosspage(uint16_t addr1, uint16_t addr2)
{
return (addr1&0xFF00) != (addr2&0xFF00);
}
uint8_t immediate_value(void)
{
uint8_t v = load(_PC++);
if (_log) fprintf(_log, "#%d", v);
return v;
}
uint16_t immediate(void)
{
uint16_t addr = _PC++;
if (_log) fprintf(_log, "#%d", load(addr));
return addr;
}
uint16_t branchaddr(int *cpb)
{
int8_t v = (int8_t)load(_PC++);
uint16_t addr;
addr = _PC + v;
if (_log) fprintf(_log, "%04X", addr);
if (cpb) *cpb = crosspage(_PC-1, addr);
return addr;
}
/* Absolute */
uint16_t absolute(void)
{
uint16_t addr;
uint8_t l, h;
l = load(_PC++);
h = load(_PC++);
addr = (h<<8 | l);
if (_log) fprintf(_log, "%04X",addr);
return addr;
}
/* Absolute,[X|Y] */
uint16_t absolute_indexed(uint8_t idx)
{
uint16_t addr;
uint8_t l, h;
l = load(_PC++);
h = load(_PC++);
addr = (h<<8 | l);
// if (_P & P_CARRY) idx++;
if (_log) fprintf(_log, "%04X,%d",addr, idx);
return addr + idx;
}
/* Zero-page[,X|Y] */
uint16_t zero_page(uint8_t idx)
{
uint8_t l;
l = load(_PC++);
if (_log) fprintf(_log, "%02X,%d", l, idx);
l += idx;
return (0x0000 | l);
}
/* (Zero-page),Y */
uint16_t indirect_indexed(void)
{
uint16_t addr;
uint8_t l, h;
l = load(_PC++);
addr = (0x0000 | l);
if (_log) fprintf(_log, "(%02X),Y:%d",l, _Y);
l = load(addr);
h = load(addr+1);
return (h<<8|l) + _Y;
}
/* (Zero-page,X) */
uint16_t indexed_indirect()
{
uint16_t addr;
uint8_t l, h;
l = load(_PC++) + _X;
addr = 0x0000 | l;
if (_log) fprintf(_log, "(%02X,X:%d)\n",l, _X);
l = load(addr);
h = load(addr+1);
return (h<<8|l);
}
void push(uint8_t data)
{
store(0x0100|_S--,data);
}
uint8_t pop()
{
return load(0x0100|++_S);
}
void adc(uint16_t addr)
{
uint8_t m = load(addr), r;
int v;
v = _A + m + ((_P&P_CARRY)? 1 : 0);
r = _A + m + (uint8_t)((_P&P_CARRY)? 1 : 0);
_P &= ~(P_CARRY|P_NEGATIVE|P_ZERO|P_OVERFLOW);
if (((_A^r)&0x80) && ((m^r)&0x80)) _P |= P_OVERFLOW;
if (v > 255) _P |= P_CARRY;
if (r == 0) _P |= P_ZERO;
if (r&0x80) _P |= P_NEGATIVE;
_A = r;
}
void sbc(uint16_t addr)
{
uint8_t m = load(addr), r;
int v;
m = 255 - m;
v = _A + m + ((_P&P_CARRY)? 1 : 0);
r = _A + m + (uint8_t)((_P&P_CARRY)? 1 : 0);
_P &= ~(P_CARRY|P_NEGATIVE|P_ZERO|P_OVERFLOW);
if (((_A^r)&0x80) && ((m^r)&0x80)) _P |= P_OVERFLOW;
if (v > 255) _P |= P_CARRY;
if (r == 0) _P |= P_ZERO;
if (r&0x80) _P |= P_NEGATIVE;
_A = r;
}
uint8_t ror(uint8_t m)
{
int c = _P & P_CARRY;
_P &= ~(P_CARRY|P_ZERO|P_NEGATIVE);
if (m & 0x01) _P |= P_CARRY;
m >>= 1;
if (c) m |= 0x80;
else m &= 0x7F;
if (m == 0) _P |= P_ZERO;
if (m & 0x80) _P |= P_NEGATIVE;
return m;
}
uint8_t rol(uint8_t m)
{
int c = _P & P_CARRY;
_P &= ~(P_CARRY|P_ZERO|P_NEGATIVE);
if (m & 0x80) _P |= P_CARRY;
m <<= 1;
if (c) m |= 0x01;
if (m == 0) _P |= P_ZERO;
if (m & 0x80) _P |= P_NEGATIVE;
return m;
}
uint8_t lsr(uint8_t m)
{
_P &= ~(P_ZERO | P_CARRY | P_NEGATIVE);
if (m & 0x01) _P |= P_CARRY;
m>>=1;
if (m == 0) _P |= P_ZERO;
return m;
}
uint8_t asl(uint8_t m)
{
_P &= ~(P_ZERO | P_CARRY | P_NEGATIVE);
if (m & 0x80) _P |= P_CARRY;
m<<=1;
if (m == 0) _P |= P_ZERO;
if (m & 0x80) _P |= P_NEGATIVE;
return m;
}
void ora(uint16_t addr)
{
uint8_t m = load(addr);
_A |= m;
_P &= ~(P_NEGATIVE|P_ZERO);
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
}
void lda(uint16_t addr)
{
_A = load(addr);
_P &= ~(P_NEGATIVE | P_ZERO);
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
}
void ldx(uint16_t addr)
{
_X = load(addr);
_P &= ~(P_NEGATIVE | P_ZERO);
if (_X == 0) _P |= P_ZERO;
if (_X & 0x80) _P |= P_NEGATIVE;
}
void ldy(uint16_t addr)
{
_Y = load(addr);
_P &= ~(P_NEGATIVE | P_ZERO);
if (_Y == 0) _P |= P_ZERO;
if (_Y & 0x80) _P |= P_NEGATIVE;
}
void inc(uint16_t addr)
{
uint8_t m = load(addr);
_P &= ~(P_ZERO | P_NEGATIVE);
m++;
if (m == 0) _P |= P_ZERO;
if (m & 0x80) _P |= P_NEGATIVE;
store(addr, m);
}
void dec(uint16_t addr)
{
uint8_t m = load(addr);
_P &= ~(P_ZERO | P_NEGATIVE);
m--;
if (m == 0) _P |= P_ZERO;
if (m & 0x80) _P |= P_NEGATIVE;
store(addr, m);
}
void eor(uint16_t addr)
{
uint8_t m = load(addr);
_P &= ~(P_ZERO | P_NEGATIVE);
_A ^= m;
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
}
/* a = register, b = memory */
void cmp(uint8_t a, uint16_t addr)
{
uint8_t b = load(addr);
if (_log) fprintf(_log," (%d/%d) ",a,b);
_P &= ~(P_ZERO | P_NEGATIVE | P_CARRY);
if (a == b) _P |= P_ZERO;
if (a >= b) _P |= P_CARRY;
a = a-b;
if (a&0x80) _P |= P_NEGATIVE;
}
void and(uint16_t addr)
{
uint8_t m = load(addr);
_P &= ~(P_ZERO | P_NEGATIVE);
_A &= m;
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
}
char *status(uint8_t P)
{
static char f[8];
f[0] = P & P_NEGATIVE? 'N' : '-';
f[1] = P & P_ZERO? 'Z' : '-';
f[2] = P & P_CARRY? 'C' : '-';
f[3] = P & P_IRQDIS? 'I' : '-';
f[4] = P & P_DECIMAL? 'D' : '-';
f[5] = P & P_OVERFLOW? 'V' : '-';
f[6] = 0;
return f;
}
int run() {
int i, cycles = 0, clocks = 0;
uint16_t addr;
uint8_t l, h;
while(1) {
_IR = load(_PC++);
if (_log) fprintf(_log, "%04X %02X:%s ", _PC-1, _IR, _instr[_IR]);
switch(_IR) {
case 0x00: // BRK
_PC++;
push(_PC>>8);
push(_PC&0xFF);
push(_P | P_BRK);
_P |= P_IRQDIS;
_PC = load(0x0317)<<8 | load(0x0316);
cycles = 7;
break;
case 0x01: // ORA (Indirect,X)
ora(indexed_indirect());
cycles = 6;
break;
case 0x05: // ORA Zero-page
ora(zero_page(0));
cycles = 3;
break;
case 0x06: // ASL Zero-page
l = asl(load(addr = zero_page(0)));
store(addr, l);
cycles = 5;
break;
case 0x08: // PHP
push(_P);
cycles = 3;
break;
case 0x09: // ORA Immediate
ora(immediate());
cycles = 2;
break;
case 0x0A: // ASL Accumulator
_A = asl(_A);
cycles = 2;
break;
case 0x0D: // ORA Absolute
ora(absolute());
cycles = 4;
break;
case 0x0E: // ASL Absolute
l = asl(load(addr = absolute()));
store(addr, l);
cycles = 6;
break;
case 0x10: // BPL
l = immediate_value();
cycles = 2;
if (!(_P & P_NEGATIVE)) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0x11: // ORA (Indirect),Y
ora(indirect_indexed());
cycles = 5;
break;
case 0x15: // ORA Zero-Page,X
ora(zero_page(_X));
cycles = 4;
break;
case 0x16: // ASL Zero-Page,X
l = asl(load(addr = zero_page(_X)));
store(addr, l);
cycles = 6;
break;
case 0x18: // CLC
_P &= ~P_CARRY;
cycles = 2;
break;
case 0x19: // ORA Absolute,Y
ora(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x1D: // ORA Absolute,X
ora(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0x1E: // ASL Absolute,X
l = asl(load(addr = absolute_indexed(_X)));
store(addr, l);
cycles = 7;
break;
case 0x20: // JSR
addr = _PC+1;
push(addr>>8);
push(addr&0xFF);
_PC = absolute();
cycles = 6;
break;
case 0x21: // AND (Indirect,X)
and(indexed_indirect());
cycles = 6;
break;
case 0x24: // BIT Zero-page
l = load(zero_page(0));
_P &= ~(P_NEGATIVE|P_ZERO|P_OVERFLOW);
_P |= (l&0xC0);
_P |= (_A&l? 0 : P_ZERO);
cycles = 3;
break;
case 0x25: // AND Zero-page
and(zero_page(0));
cycles = 3;
break;
case 0x26: // ROL Zero-page
l = rol(load(addr = zero_page(0)));
store(addr, l);
cycles = 5;
break;
case 0x28: // PLP
_P = pop();
cycles = 4;
break;
case 0x29: // AND Immediate
and(immediate());
cycles = 2;
break;
case 0x2A: // ROL Accumulator
_A = rol(_A);
cycles = 2;
break;
case 0x2C: // BIT Absolute
l = load(absolute());
_P &= ~(P_NEGATIVE|P_ZERO|P_OVERFLOW);
_P |= (l&0xC0);
_P |= (_A&l? 0 : P_ZERO);
cycles = 4;
break;
case 0x2D: // AND Absolute
and(absolute());
cycles = 4;
break;
case 0x2E: // ROL Absolute
l = rol(load(addr = absolute()));
store(addr, l);
cycles = 6;
break;
case 0x30: // BMI
l = immediate_value();
cycles = 2;
if (_P & P_NEGATIVE) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0x31: // AND (Indirect),Y
and(indirect_indexed());
cycles = 5;
break;
case 0x35: // AND Zero-page,X
and(zero_page(_X));
cycles = 4;
break;
case 0x36: // ROL Zero-page,X
l = rol(load(addr = zero_page(_X)));
store(addr, l);
cycles = 6;
break;
case 0x38: // SEC
_P |= P_CARRY;
cycles = 2;
break;
case 0x39: // AND Absolute,Y
and(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x3D: // AND Absolute,X
and(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0x3E: // ROL Absolute,X
l = rol(load(addr = absolute_indexed(_X)));
store(addr, l);
cycles = 7;
break;
case 0x40: // RTI
_P = pop();
l = pop();
h = pop();
_PC = h<<8 | l;
if (_ilog) {
fprintf(_log, "PC-> %04X", _PC);
fprintf(_log, " S:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
_log = NULL;
}
break;
case 0x41: // EOR (Indirect,X)
eor(indexed_indirect());
cycles = 6;
break;
case 0x45: // EOR Zero-page
eor(zero_page(0));
cycles = 3;
break;
case 0x46: // LSR Zero-page
l = lsr(load(addr = zero_page(0)));
store(addr,l);
cycles = 5;
break;
case 0x48: // PHA
push(_A);
cycles = 3;
break;
case 0x49: // EOR Immediate
eor(immediate());
cycles = 2;
break;
case 0x4A: // LSR Accumulator
_A = lsr(_A);
cycles = 2;
break;
case 0x4C: // JMP Absolute
_PC = absolute();
cycles = 3;
break;
case 0x4D: // EOR Absolute
eor(absolute());
cycles = 4;
break;
case 0x4E: // LSR Absolute
l = lsr(load(addr = absolute()));
store(addr,l);
cycles = 6;
break;
case 0x50: // BVC
l = immediate_value();
cycles = 2;
if (!(_P & P_OVERFLOW)) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0x51: // EOR (Indirect),Y
eor(addr = indirect_indexed());
cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x55: // EOR Zero-page,X
eor(zero_page(_X));
cycles = 4;
break;
case 0x56: // LSR Zero-page,X
l = lsr(load(addr = zero_page(_X)));
store(addr,l);
cycles = 6;
break;
case 0x58: // CLI
_P &= ~(P_IRQDIS);
cycles = 2;
break;
case 0x59: // EOR Absolute,Y
eor(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x5D: // EOR Absolute,X
eor(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0x5E: // LSR Absolute,X
l = lsr(load(addr = absolute_indexed(_X)));
store(addr,l);
cycles = 7;
break;
case 0x60: // RTS
l = pop();
h = pop();
_PC = h<<8 | l;
_PC++;
break;
case 0x61: // ADC (Indirect,X)
adc(indexed_indirect());
cycles = 6;
break;
case 0x65: // ADC Zero-page
adc(zero_page(0));
cycles = 3;
break;
case 0x66: // ROR Zero-page
l = ror(load(addr = zero_page(0)));
store(addr,l);
cycles = 5;
break;
case 0x68: // PLA
_A = pop();
_P &= ~(P_ZERO|P_NEGATIVE);
if (_A == 0) _P |= P_ZERO;
if (_A&0x80) _P |= P_NEGATIVE;
cycles = 4;
break;
case 0x69: // ADC Immediate
adc(immediate());
cycles = 2;
break;
case 0x6A: // ROR Accumulator
_A = ror(_A);
cycles = 2;
break;
case 0x6C: // JMP Indirect
addr = absolute();
l = load(addr);
if ((addr&0x00FF) == 0x00FF) {
fprintf(stderr,"Possible bad indirect jump (addr=%04X)\n", addr);
exit(0);
}
h = load(addr+1);
_PC = h<<8 | l;
cycles = 5;
break;
case 0x6D: // ADC Absolute
adc(absolute());
cycles = 4;
break;
case 0x6E: // ROR Absolute
l = ror(load(addr = absolute()));
store(addr, l);
cycles = 6;
break;
case 0x70: // BVS
l = immediate_value();
cycles = 2;
if (_P & P_OVERFLOW) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0x71: // ADC (Indirect),Y
adc(addr = indirect_indexed());
cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x75: // ADC Zero-page,X
adc(zero_page(_X));
cycles = 4;
break;
case 0x76: // ROR Zero-page,X
l = ror(load(addr = zero_page(_X)));
store(addr, l);
cycles = 6;
break;
case 0x78: // SEI
_P |= P_IRQDIS;
cycles = 2;
break;
case 0x79: // ADC Absolute,Y
adc(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0x7D: // ADC Absolute,X
adc(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0x7E: // ROR Absolute,X
l = ror(load(addr = absolute_indexed(_X)));
store(addr, l);
cycles = 7;
break;
case 0x81: // STA (Indirect,X)
store(indexed_indirect(), _A);
cycles = 6;
break;
case 0x84: // STY Zero-page
store(zero_page(0), _Y);
cycles = 3;
break;
case 0x85: // STA Zero-page
store(zero_page(0), _A);
cycles = 3;
break;
case 0x86: // STX Zero-page
store(zero_page(0), _X);
cycles = 3;
break;
case 0x88: // DEY
_Y--;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_Y == 0) _P |= P_ZERO;
if (_Y & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0x8A: // TXA
_A = _X;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0x8C: // STY Absolute
store(absolute(), _Y);
cycles = 4;
break;
case 0x8D: // STA Absolute
store(absolute(), _A);
cycles = 4;
break;
case 0x8E: // STX Absolute
store(absolute(), _X);
cycles = 4;
break;
case 0x90: // BCC
l = immediate_value();
cycles = 2;
if (!(_P & P_CARRY)) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0x91: // STA (Indirect),Y
store(indirect_indexed(), _A);
cycles = 6;
break;
case 0x94: // STY Zero-page,X
store(zero_page(_X), _Y);
cycles = 4;
break;
case 0x95: // STA Zero-page,X
store(zero_page(_X), _A);
cycles = 4;
break;
case 0x96: // STX Zero-page,Y
store(zero_page(_Y), _X);
cycles = 4;
break;
case 0x98: // TYA
_A = _Y;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_A == 0) _P |= P_ZERO;
if (_A & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0x99: // STA Absolute,Y
store(absolute_indexed(_Y), _A);
cycles = 5;
break;
case 0x9A: // TXS
_S = _X;
cycles = 2;
break;
case 0x9D: // STA Absolute,X
store(absolute_indexed(_X), _A);
cycles = 5;
break;
case 0xA0: // LDY Immediate
ldy(immediate());
cycles = 2;
break;
case 0xA1: // LDA (Indirect,X)
lda(indexed_indirect());
cycles = 6;
break;
case 0xA2: // LDX Immediate
ldx(immediate());
cycles = 2;
break;
case 0xA4: // LDY Zero-page
ldy(zero_page(0));
cycles = 3;
break;
case 0xA5: // LDA Zero-page
lda(zero_page(0));
cycles = 3;
break;
case 0xA6: // LDX Zero-page
ldx(zero_page(0));
cycles = 3;
break;
case 0xA8: // TAY
_Y = _A;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_Y == 0) _P |= P_ZERO;
if (_Y & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xA9: // LDA Immediate
lda(immediate());
cycles = 2;
break;
case 0xAA: // TAX
_X = _A;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_X == 0) _P |= P_ZERO;
if (_X & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xAC: // LDY Absolute
ldy(absolute());
cycles = 4;
break;
case 0xAD: // LDA Absolute
lda(absolute());
cycles = 4;
break;
case 0xAE: // LDX Absolute
ldx(absolute());
cycles = 4;
break;
case 0xB0: // BCS
l = immediate_value();
cycles = 2;
if (_P & P_CARRY) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0xB1: // LDA (Indirect),Y
lda(addr = indirect_indexed());
cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0xB4: // LDY Zero-page,X
ldy(zero_page(_X));
cycles = 4;
break;
case 0xB5: // LDA Zero-page,X
lda(zero_page(_X));
cycles = 4;
break;
case 0xB6: // LDX Zero-page,Y
ldx(zero_page(_Y));
cycles = 4;
break;
case 0xB8: // CLV
_P &= ~P_OVERFLOW;
cycles = 2;
break;
case 0xB9: // LDA Absolute,Y
lda(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0xBA: // TSX
_X = _S;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_X == 0) _P |= P_ZERO;
if (_X & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xBC: // LDY Absolute,X
ldy(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1: 0 ;
break;
case 0xBD: // LDA Absolute,X
lda(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0xBE: // LDX Absolute,Y
ldx(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1: 0 ;
break;
case 0xC0: // CPY Immediate
cmp(_Y, immediate());
cycles = 2;
break;
case 0xC1: // CMP (Indirect,X)
cmp(_A, indexed_indirect());
cycles = 6;
break;
case 0xC4: // CPY Zero-page
cmp(_Y, zero_page(0));
cycles = 3;
break;
case 0xC5: // CMP Zero-page
cmp(_A, zero_page(0));
cycles = 3;
break;
case 0xC6: // DEC Zero-page
dec(zero_page(0));
cycles = 5;
break;
case 0xC8: // INY
_Y++;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_Y == 0) _P |= P_ZERO;
if (_Y & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xC9: // CMP Immediate
cmp(_A, immediate());
cycles = 2;
break;
case 0xCA: // DEX
_X--;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_X == 0) _P |= P_ZERO;
if (_X & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xCC: // CPY Absolute
cmp(_Y, absolute());
cycles = 4;
break;
case 0xCD: // CMP Absolute
cmp(_A, absolute());
cycles = 4;
break;
case 0xCE: // DEC Absolute
dec(absolute());
cycles = 6;
break;
case 0xD0: // BNE
l = immediate_value();
cycles = 2;
if (!(_P & P_ZERO)) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0xD1: // CMP (Indirect),Y
cmp(_A, addr = indirect_indexed());
cycles = 5 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0xD5: // CMP Zero-page,X
cmp(_A, zero_page(_X));
cycles = 4;
break;
case 0xD6: // DEC Zero-page,X
dec(zero_page(_X));
cycles = 6;
break;
case 0xD8: // CLD
_P &= ~(P_DECIMAL);
cycles = 2;
break;
case 0xD9: // CMP Absolute,Y
cmp(_A, addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0xDD: // CMP Absolute,X
cmp(_A, addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0xDE: // DEC Absolute,X
dec(absolute_indexed(_X));
cycles = 7;
break;
case 0xE0: // CPX Immediate
cmp(_X, immediate());
cycles = 2;
break;
case 0xE1: // SBC (Indirect,X)
sbc(indexed_indirect());
cycles = 6;
break;
case 0xE4: // CPX Zero-page
cmp(_X,zero_page(0));
cycles = 3;
break;
case 0xE5: // SBC Zero-page
sbc(zero_page(0));
cycles = 3;
break;
case 0xE6: // INC Zero-page
inc(zero_page(0));
cycles = 5;
break;
case 0xE8: // INX
_X++;
_P &= ~(P_ZERO | P_NEGATIVE);
if (_X == 0) _P |= P_ZERO;
if (_X & 0x80) _P |= P_NEGATIVE;
cycles = 2;
break;
case 0xE9: // SBC Immediate
sbc(immediate());
cycles = 2;
break;
case 0xEA: // NOP
cycles = 2;
break;
case 0xEC: // CPX Absolute
cmp(_X,absolute());
cycles = 4;
break;
case 0xED: // SBC Absolute
sbc(absolute());
cycles = 4;
break;
case 0xEE: // INC Absolute
inc(absolute());
cycles = 6;
break;
case 0xF0: // BEQ
l = immediate_value();
cycles = 2;
if (_P & P_ZERO) {
addr = _PC;
_PC = _PC + (int8_t)l;
cycles += ((addr&0xFF00) != (_PC&0xFF00))? 2 : 1;
}
break;
case 0xF1: // SBC (Indirect),Y
sbc(indirect_indexed());
cycles = 5;
break;
case 0xF5: // SBC Zero-page,X
sbc(zero_page(_X));
cycles = 4;
break;
case 0xF6: // INC Zero-page,X
inc(zero_page(_X));
cycles = 6;
break;
case 0xF8: // SED
fprintf(stderr,"SED HAS BEEN SET!\n");
exit(1);
_P |= P_DECIMAL;
cycles = 2;
break;
case 0xF9: // SBC Absolute,Y
sbc(addr = absolute_indexed(_Y));
cycles = 4 + ((addr&0xFF00) != ((addr-_Y)&0xFF00))? 1 : 0;
break;
case 0xFD: // SBC Absolute,X
sbc(addr = absolute_indexed(_X));
cycles = 4 + ((addr&0xFF00) != ((addr-_X)&0xFF00))? 1 : 0;
break;
case 0xFE: // INC Absolute,X
inc(absolute_indexed(_X));
cycles = 7;
break;
default: // Future Exapansion
fprintf(stderr,"Illegal instruction!!! %02X\n", _IR);
exit(0);
break;
}
clocks += cycles;
if (clocks > 1000) {
clocks -= 1000;
usleep(250);
}
if (_keydown > 0) _keydown -= cycles;
if (_log) {
fprintf(_log, "\tS:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
for(i=0;i<_widx;i++) {
fprintf(_log," %04X -> %02X/%d\n", _wlog[i].addr, _wlog[i].data, _wlog[i].data);
}
}
_widx = 0;
if (_timerA1) {
_timerA1 -= cycles;
if (_timerA1 <= 0) {
if (!(_P & P_IRQDIS)) {
_HWIRQ = 1;
_ics1 |= 0x01;
}
if (_timerA1L) _timerA1 += _timerA1L;
else _timerA1 = 0;
}
}
if (_HWIRQ) {
if (_ilog) {
_log = _ilog;
fprintf(_log, "PC-> %04X", _PC);
fprintf(_log, " S:1%02X A:%d X:%d Y:%d P:%s\n",_S, _A, _X, _Y, status(_P));
}
_IR = 0;
push(_PC>>8);
push(_PC&0xFF);
push(_P & ~P_BRK);
_PC = load(0XFFFF) <<8 | load(0xFFFE);
_HWIRQ = 0;
}
if (_NMI) {
_IR = 0;
push(_PC>>8);
push(_PC&0xFF);
push(_P & ~P_BRK);
_PC = load(0XFFFB) <<8 | load(0xFFFA);
_NMI = 0;
}
}
}
void reset()
{
_IR = 0;
_A = 0xAA;
_X = _Y = 0;
_P = P_BRK;
_S = 0xFD;
_PC = load(0xFFFD) <<8 | load(0xFFFC);
run();
}