/* 6502.h
 */


#define NSCHED	16	/* number of CPU timers that can be scheduled */

struct sched {
	void 	(*func)(int);	/* function to be scheduled */
	int	param;		/* parameter to call it with */
	int	time;		/* time to call */
};


struct cpu6502 {
	int	tcycles;	/* total number of CPU cycles */

	uint	irq;		/* interrupt request */
	uint	halt;		/* halts the CPU when set */
	uint	sync;		/* syncs the CPU when set */

	uint	pc;		/* current program counter */
	uint	sp;		/* current stack pointer */
	uint	flags;		/* NV?BDIZC flags */
	uint	a;		/* accumulator */
	uint	x;		/* x register */
	uint	y;		/* y register */

	int	htime;		/* horizontal sync time */
	int	hcount;		/* horizontal total count */

	struct sched event[NSCHED];	/* events to schedule */
	struct sched *sched;		/* next scheduled event */
};


struct trace6502 {
	uint	cycle;
	word	pc;		/* program counter at start */
	word	addr;		/* address accessed */
	byte	data;		/* data read/written */
	byte	opcode;		/* opcode */
	word	operand;	/* operand */
	byte	sp;		/* stack pointer */
	byte	flags;		/* NV?BDIZC flags */
	byte	a,x,y;		/* A, X, and Y registers */
};


#define FLAG_N	0x80
#define FLAG_V	0x40
#define FLAG_B	0x10
#define FLAG_D	0x08
#define FLAG_I	0x04
#define FLAG_Z	0x02
#define FLAG_C	0x01

#define VEC_NMI		0xfffa
#define VEC_RESET	0xfffc
#define VEC_IRQ		0xfffe


int	cpu_init(int argc, char **argv);
void	rom_load(byte *rom, word size, char *file);
void	mem_load(word base, word size, char *file);
void	run_6502(int ncycles);
void	trace_6502(int ninst);
void	showtrace_6502(int ninst);
word	dis_6502(word pc);
void	cpu_schedule(int n, int t, void (*s)(int), int p);
void	cpu_monitor(void);
void	cpu_nmi(void);
void	cpu_irq(void);
void	cpu_reset(void);
char*	flagstr(byte f);
void	ostrap(word addr);

/* run the CPU for the specified number of instructions: */
#define RUN_CPU(n) run_6502(n)

/* show the trace of the last n instructions executed: */
#define SHOWTRACE_CPU(n) showtrace_6502(n)

/* trace for specified number of instructions: */
#define TRACE_CPU(n) trace_6502(n)

/* disassemble at given PC and return new PC */
#define DISASSEMBLE(pc) dis_6502(pc)

/* Stack macros: */

#define PUSH(v)		{ MEM_SWRITE(cpu.sp,v); DECB(cpu.sp); }
#define PUSHW(v)	{ MEM_SWRITE(cpu.sp,HI(v)); DECB(cpu.sp); \
			  MEM_SWRITE(cpu.sp,LO(v)); DECB(cpu.sp); }
#define POP(v)		{ INCB(cpu.sp); MEM_SREAD(cpu.sp,v); }
#define POPW(v)		{ INCB(cpu.sp); MEM_SREAD(cpu.sp,v); \
			  INCB(cpu.sp); MEM_SREAD(cpu.sp,n); v = WORD(v,n); }


GLOBAL struct cpu6502 cpu;
GLOBAL struct trace6502 *trace;
GLOBAL uint tracesize;
GLOBAL uint tracepos;

