#ifndef _6502P_H_
#define _6502P_H_

/* Private include file for 6502 module */
#include "6502.h"

/* Our bits in the status register P */
#define P_C 0x01
#define P_Z 0x02
#define P_I 0x04
#define P_D 0x08
#define P_B 0x10
#define P_U 0x20
#define P_V 0x40
#define P_N 0x80

/*
 * Some macros to set, clear, and get bits from P. I resisted the urge to use
 * token pasting to create fewer, but more obfuscated, macros.
 */
#define set_C() (P |= P_C)
#define set_Z() (P |= P_Z)
#define set_I() (P |= P_I)
#define set_D() (P |= P_D)
#define set_B() (P |= P_B)
#define set_V() (P |= P_V)
#define set_N() (P |= P_N)

#define clr_C() (P &= ~P_C)
#define clr_Z() (P &= ~P_Z)
#define clr_I() (P &= ~P_I)
#define clr_D() (P &= ~P_D)
#define clr_B() (P &= ~P_B)
#define clr_V() (P &= ~P_V)
#define clr_N() (P &= ~P_N)
#define clr_ZN() (P &= ~(P_Z + P_N))

#define get_C() ((P & P_C) != 0)
#define get_Z() ((P & P_Z) != 0)
#define get_I() ((P & P_I) != 0)
#define get_D() ((P & P_D) != 0)
#define get_B() ((P & P_B) != 0)
#define get_V() ((P & P_V) != 0)
#define get_N() ((P & P_N) != 0)

#define reset_C(x) ((void)((x) ? set_C() : clr_C()))
#define reset_Z(x) ((void)((x) ? set_Z() : clr_Z()))
#define reset_I(x) ((void)((x) ? set_I() : clr_I()))
#define reset_D(x) ((void)((x) ? set_D() : clr_D()))
#define reset_B(x) ((void)((x) ? set_B() : clr_B()))
#define reset_V(x) ((void)((x) ? set_V() : clr_V()))
#define reset_N(x) ((void)((x) ? set_N() : clr_N()))

#define reset_ZN(x) ((void)((x) & 0x80 \
			    ? (set_N(), clr_Z()) \
			    : ((x) == 0 \
			       ? (set_Z(), clr_N()) \
			       : clr_ZN())))

/*
 * Addressing mode defines.
 */
#ifdef ASSUME
#    define arg_byte readbq(PC+1)
#    define arg_addr readwq(PC+1)
#    define readbi readbq
#    define writebi writebq
#else
#    define arg_byte readb(PC+1)
#    define arg_addr readw(PC+1)
#    define readbi readb
#    define writebi writeb
#endif

#define imm()	(PC+1)
#define zp()	(arg_byte)
#define zp_x()	((byte)(arg_byte + X))
#define zp_y()	((byte)(arg_byte + Y))
#define ind_zp()(readwq(arg_byte))
#define abs()	(arg_addr)
#define abs_x()	((word)(arg_addr + X))
#define abs_y()	((word)(arg_addr + Y))
#define ind_x()	(readwq((byte)(arg_byte + X)))
#define ind_y()	((word)(readwq(arg_byte) + Y))
#define ind()	(readw(arg_addr))
#define absind_x() (readw((byte)(arg_byte + X)))

/*
 * Other misc defines to make things seem all functional
 */
#define inc_PC(x) (PC += x)
/* #define inc_time(x) (T += x) */
#define inc_time(x)
/* What's this twaddle here? Ignore for time being ;) */
#define page_crossed() ((PC & 0xff) == 0xff)

extern byte A;
extern byte X;
extern byte Y;
extern byte P;
extern byte SP;
extern word PC;
extern long /* time_t */ T;

extern void (*opcode[256])();

#endif /* _6502P_H_ */
