/*

    6505 Emulator.
    2007 Jason Hunt
    nulluser@gmail.com
*/


#ifndef EMU_H
#define EMU_H

#define MEM_SIZE    65536


void emu_start ( void );
void emu_process(void  );



typedef unsigned char byte;
typedef unsigned int word;

#define CF      0x01
#define ZF      0x02
#define IF      0x04
#define DF      0x08
#define BF      0x10
#define UF      0x20
#define VF      0x40
#define SF      0x80


enum inst_list  { i_inv, i_adc, i_and, i_asl, i_bcc, i_bcs, i_beq, i_bit,    
                  i_bmi, i_bne, i_bpl, i_brk, i_bvc, i_bvs, i_clc, i_cld,    
                  i_cli, i_clv, i_cmp, i_cpx, i_cpy, i_dec, i_dex, i_dey,    
                  i_eor, i_inc, i_inx, i_iny, i_jmp, i_jsr, i_lda, i_ldx,    
                  i_ldy, i_lsr, i_nop, i_ora, i_pha, i_php, i_pla, i_plp,    
                  i_rol, i_ror, i_rti, i_rts, i_sbc, i_sec, i_sed, i_sei,    
                  i_sta, i_stx, i_sty, i_tax, i_tay, i_tsx, i_txa, i_txs,    
                  i_tya};


enum mode_list  { m_inv, m_imp, m_acc, m_imm, m_zp,  m_zpx, m_zpy, m_rel,
                  m_ab,  m_abx, m_aby, m_ind, m_idx, m_idy};



class emu;


typedef struct op_map_type 
{
    byte inst;          // instruction enumeraton
    byte mode;          // mode enumeration 

    byte flag_mask;     // which flags will be checked

    byte size;          // number of bytes to advance for instruction

 void (emu::*func) (void);

};



typedef struct
{


} state_type;


class emu
{
       
  public:
        
        
    emu ( void );
       
    void init(void);
    
//    int (A::*pmf) (); 
    

    void set_op(byte num, byte inst, byte mode);
    void set_func(byte num, void (emu::*func) (void), byte f);

    void load_op_map ( void );
    void decode(void);
    void run(void);
    void show_state(void);
    void check_flags(void);
    void dump(unsigned int start, unsigned int end);
        
    void load_program( char * filename );
    void load_memory(byte * data, unsigned int size);
        
    void set_mem(unsigned int addr, unsigned char val);

    void get_src(void);
    word get_16(word a);

    void inv(void); void adc(void); void and1(void); void asl(void);
    void bcc(void); void bcs(void); void beq(void); void bit(void);    
    void bmi(void); void bne(void); void bpl(void); void brk(void);    
    void bvc(void); void bvs(void); void clc(void); void cld(void);    
    void cli(void); void clv(void); void cmp(void); void cpx(void);    
    void cpy(void); void dec(void); void dex(void); void dey(void);    
    void eor(void); void inc(void); void inx(void); void iny(void);    
    void jmp(void); void jsr(void); void lda(void); void ldx(void);    
    void ldy(void); void lsr(void); void nop(void); void ora(void);    
    void pha(void); void php(void); void pla(void); void plp(void);    
    void rol(void); void ror(void); void rti(void); void rts(void);    
    void sbc(void); void sec(void); void sed(void); void  sei(void);    
    void sta(void); void stx(void); void sty(void); void  tax(void);    
    void tay(void); void tsx(void); void txa(void); void txs(void);    
    void tya(void);


bool get_fail(void){return fail;};
private:

    byte mem[MEM_SIZE];
   
    word pc, sp, ab_addr;
    byte acc, ix, iy, ps;
//    byte cf,zf,id,dm,b,ov,n;

   // byte flags;
   byte f_c,    // Carry
        f_z,    // Zero
        f_i,    // Interrupt
        f_d,    // Decimal mode
        f_b,    // Break
        f_v,    // Overflow
        f_n;    // Negative
   
   
    byte op, inst, mode, p1,p2;

    byte src_8;
    word src_16;

    byte res;


    byte sz;    // Size for this instruction

    bool fail;
  
    op_map_type op_map[256];
    
    
};


#endif
