/*
 * 6502 CPU Emulator
 */

#ifndef CPU6502EMUL_H
#define CPU6502EMUL_H

#include "types.h"
#include "CPUEmul.h"

template<class MemEmulCls>
class CPU6502Emul: public CPUEmul
{
protected:
	// Basic registers
	byte A, X, Y;
	// Other registers
	wordu S;
	wordu PC;
	struct
	{
		byte N, V, D, I, Z, C;
	} P;
	enum
	{
		CPU_FLG_N = 0x80,
		CPU_FLG_V = 0x40,
		CPU_FLG_ONE = 0x20,
		CPU_FLG_B = 0x10,
		CPU_FLG_D = 0x08,
		CPU_FLG_I = 0x04,
		CPU_FLG_Z = 0x02,
		CPU_FLG_C = 0x01,
	} CPU_Flags;
	
	int IRQ_Waiting, NMI_Waiting;
	
	inline void Push (byte b);
	inline byte Pop (void);
	
	byte d1;
	int extra_cycles;
	
	wordu address;
	
	// Addressing modes
	inline void addr_abs (void);
	inline void addr_zpabs (void);
	inline void addr_zpind (void);
	inline void addr_zpidxX (void);
	inline void addr_zpidxY (void);
	inline void addr_idxX (int do_extra);
	inline void addr_idxY (int do_extra);
	inline void addr_ind (void);
	inline void addr_preindX (void);
	inline void addr_postindY (int do_extra);
	inline void addr_rel (void);
	
	inline byte Do_ASL (byte val);
	inline byte Do_INC (byte val);
	inline byte Do_DEC (byte val);
	inline byte Do_LSR (byte val);
	inline byte Do_ROL (byte val);
	inline byte Do_ROR (byte val);
	
	inline void Do_ADC (byte val);
	inline void Do_AND (byte val);
	inline void Do_BIT (byte val);
	inline void Do_CMP (byte reg, byte val);
	inline void Do_EOR (byte val);
	inline void Do_ORA (byte val);
	inline void Do_SBC (byte val);
	
	inline byte Do_TSB (byte val);
	inline byte Do_TRB (byte val);
	
	inline void Set_Sign (byte val);
	inline void Set_Zero (byte val);
	inline void Set_Overflow (byte old, byte newval, byte val);
	inline void Do_Branch (int condition);
	
	inline void DoIRQ (void);
	inline void DoNMI (void);
	
	MemEmulCls *Mem;

public:
	inline void ExecInstruction (void);
	void Trace (void);
	void ResetCPU (void);
	void SignalIRQ (int queue_anyway = 0);
	void ClearIRQ (int queue_anyway_id);
	void SignalNMI (void);
	int GetPC (void) { return PC.w; }
	
	CPU6502Emul (MemEmulCls *m) { Mem = m; }
};

/* Standard interrupts */
#define IRQ_SYSVIA 2
#define IRQ_USRVIA 4

#endif /* CPU6502EMUL_H */

/* End of file. */
