#include #define u8 unsigned char #define u16 unsigned short extern u8 A, X, Y, S, tmp; /* tmp is result for cmp/cpx/cpy */ extern u8 mem[1 << 16]; /* 64K */ extern u8 *stack; /* page 1 */ extern unsigned int wtmp; /* wide temporary for adc/sbc */ extern u8 CF, ZF, NF; /* flags should really be a bitfield, *shrug* */ extern void dump_state(void); extern void dump_mem(int start, int end); #define dump_zp() dump_mem(0, 0xff); #define dump_stack() dump_mem(0x100, 0x1ff); #define dump_page(x) dump_mem(x * 0x100, x * 0x100 + 0x1ff); #define _ind_y(x) mem[Y + (mem[x] | (mem[x+1] << 8))] #define setnz(x) ZF=!x; NF=(x&0x80)!=0; #define pha() stack[S--] = A; #define pla() A = stack[++S]; setnz(A); #define php() stack[S--] = (NF<<7 | ZF<<1 | CF); #define plp() tmp = stack[++S]; NF=(tmp&0x80)!=0 ; ZF=(tmp&0x02)!=0; CF=tmp&0x01; #define lda_i(x) A=x; setnz(A); #define ldy_i(x) Y=x; setnz(Y); #define ldx_i(x) X=x; setnz(X); #define lda(x) A=mem[x]; setnz(A); #define ldx(x) X=mem[x]; setnz(X); #define ldy(x) Y=mem[x]; setnz(Y); #define lda_abs_x(x) A=mem[x+X]; setnz(A); #define lda_abs_y(x) A=mem[x+Y]; setnz(A); #define lda_ind_y(x) A=_ind_y(x); setnz(A); #define sta(x) mem[x] = A; #define sta_abs_x(x) mem[x + X] = A; #define sta_abs_y(x) mem[x + Y] = A; #define sta_ind_y(x) _ind_y(x) = A; #define stx(x) mem[x] = X; #define sty(x) mem[x] = Y; #define sec() CF=1; #define clc() CF=0; #define tax() X=A; setnz(X); #define tay() Y=A; setnz(Y); #define txa() A=X; setnz(A); #define tya() A=Y; setnz(A); #define txs() S=X; setnz(S); /* note: tsx doesn't affect flags */ #define tsx() X=S; #define _ror(x) tmp=x&1; x>>=1; x|=(CF<<7); CF=tmp; setnz(x); #define _rol(x) tmp=(x&0x80)!=0; x<<=1; x|=CF; CF=tmp; setnz(x); #define ror_a() _ror(A); #define rol_a() _rol(A); #define ror(x) _ror(mem[x]); #define rol(x) _rol(mem[x]); #define _lsr(x) CF=x&1; x>>=1; setnz(x); #define _asl(x) CF=(x&0x80)!=0; x<<=1; setnz(x); #define lsr_a() _lsr(A); #define asl_a() _asl(A); #define lsr(x) _lsr(mem[x]); #define asl(x) _asl(mem[x]); #define inx() X++; setnz(X); #define iny() Y++; setnz(Y); #define dex() X--; setnz(X); #define dey() Y--; setnz(Y); #define inc(x) mem[x]++; setnz(mem[x]); #define dec(x) mem[x]--; setnz(mem[x]); #define jsr(x) x(); #define rts() return; #define jmp(x) goto x; #define bne(x) if(!ZF) goto x; #define beq(x) if(ZF) goto x; #define bcc(x) if(!CF) goto x; #define bcs(x) if(CF) goto x; #define bpl(x) if(!NF) goto x; #define bmi(x) if(NF) goto x; #define ora_i(x) A|=x; setnz(A); #define ora(x) A|=mem[x]; setnz(A); #define and_i(x) A&=x; setnz(A); #define and(x) A&=mem[x]; setnz(A); #define and_abx_x(x) A&=mem[x+X]; setnz(A); #define and_abs_y(x) A&=mem[x+Y]; setnz(A); #define and_ind_y(x) A&=_ind_y(x); setnz(A); #define eor_i(x) A^=x; setnz(A); #define eor(x) A^=mem[x]; setnz(A); #define adc_i(x) wtmp=A+x+CF; A=wtmp&0xff; CF=(wtmp&0x100)!=0; setnz(A); #define adc(x) adc_i(mem[x]); #define adc_abs_x(x) adc_i(mem[x+X]); #define adc_abs_y(x) adc_i(mem[x+Y]); #define adc_ind_y(x) adc_i(_ind_y(x)); /* TODO: actually check this logic! */ #define _sub(dst,orig,c,operand) wtmp=orig+(operand^0xff)+c; dst=wtmp&0xff; CF=(wtmp&0x100)!=0; setnz(dst); #define sbc_i(x) _sub(A,A,CF,x) #define sbc(x) _sub(A,A,CF,mem[x]) #define cmp_i(x) _sub(tmp,A,1,x) #define cpy_i(x) _sub(tmp,Y,1,x) #define cpx_i(x) _sub(tmp,X,1,x) #define cmp(x) cmp_i(mem[x]) #define cmp_abs_x(x) cmp_i(mem[x+X]) #define cpy(x) cpy_i(mem[x]) #define cpx(x) cpx_i(mem[x]) #define nop() {} /* this should produce a compile error instead */ #define brk() nop()