/******************************************************************************
*
* Copyright (C) 2004-2017  Brian Berlin
* 
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************
*
* FILENAME: boom6502.h
*
* DESCRIPTION:  This contains defs and headers form  6502 processor functions
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.1     07/18/04  bberlin      Creation
******************************************************************************/
#ifndef boom5200_h
#define boom5200_h

#define KWORD   unsigned int
#define KBYTE   unsigned int

/******************************/
/* Define interupt addresses  */
/******************************/
#define INT_NONE   0x0000U
#define INT_IRQ    0xfffeU
#define INT_NMI    0xfffaU
#define INT_RESET  0xfffcU
#define INT_QUIT   0xffffU

/******************************/
/* Define Debug constants     */
/******************************/
#define BEFORE_OP  1
#define DURING_OP  2
#define AFTER_OP   3
#define READ_MEM   1
#define WRITE_MEM  2

/* define 6502 status register */
#define B6502_CARRY_FLG     0x01
#define B6502_ZERO_FLG      0x02
#define B6502_INTERPT_FLG   0x04
#define B6502_DECIMAL_FLG   0x08
#define B6502_BREAK_FLG     0x10
#define B6502_RESRVD_FLG    0x20
#define B6502_OVRFLW_FLG    0x40
#define B6502_SIGN_FLG      0x80

/* define inverses of status  */
#define NOT_B6502_CARRY_FLG     0xfe
#define NOT_B6502_ZERO_FLG      0xfd
#define NOT_B6502_INTERPT_FLG   0xfb
#define NOT_B6502_DECIMAL_FLG   0xf7
#define NOT_B6502_BREAK_FLG     0xef
#define NOT_B6502_RESRVD_FLG    0xdf
#define NOT_B6502_OVRFLW_FLG    0xbf
#define NOT_B6502_SIGN_FLG      0x7f

/* Get flag from status reg   */
#define GET_B6502_CARRY   ((B6502_CARRY_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_ZERO    ((B6502_ZERO_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_INTERPT ((B6502_INTERPT_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_DECIMAL ((B6502_DECIMAL_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_BREAK   ((B6502_BREAK_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_OVRFLW  ((B6502_OVRFLW_FLG & cpu6502.status) ? 1 : 0)
#define GET_B6502_SIGN    ((B6502_SIGN_FLG & cpu6502.status) ? 1 : 0)

/* Test flag from status reg  */
#define IF_B6502_CARRY   (B6502_CARRY_FLG & cpu6502.status)
#define IF_B6502_ZERO    (B6502_ZERO_FLG & cpu6502.status)
#define IF_B6502_INTERPT (B6502_INTERPT_FLG & cpu6502.status)
#define IF_B6502_DECIMAL (B6502_DECIMAL_FLG & cpu6502.status)
#define IF_B6502_BREAK   (B6502_BREAK_FLG & cpu6502.status)
#define IF_B6502_OVRFLW  (B6502_OVRFLW_FLG & cpu6502.status)
#define IF_B6502_SIGN    (B6502_SIGN_FLG & cpu6502.status)

/*
 * Escape Codes for Patches
 */
#define ESC_CODE_SIO  1

#define NMI_REQUEST_VBI  0
#define NMI_REQUEST_DLI  1

typedef struct {

    int i_req;
    int irq_assert;
    int irq_pending;
    int nmi_pending;
    int nmi_scanline;
    int nmi_countdown;
    int nmi_cycle;
    KBYTE nmi_status_reg;
    int i_cnt;
    KBYTE status;
    KBYTE opcode;
    KWORD pc;
    KWORD a_reg;
    KWORD x_reg;
    KWORD y_reg;
    KWORD s_reg;
    KWORD t_reg;
    KWORD h_reg;
    KWORD stack[ 0x100 ];
    KWORD stack_ptr;
    void ( *do_instruct[ 0x100 ] ) ( void );
    KBYTE ( *read_mem[ 0x100 ] ) ( KWORD addr );
    void ( *write_mem[ 0x100 ] ) ( KWORD addr, KBYTE value );
    int op_cycles[ 0x100 ];
    char op_name[ 0x100 ][ 15 ];
} t_cpu;

struct debug_cpu {
    KBYTE stop_on_addr_match_flag;
    KBYTE write_debug_flag;
    KWORD stop_on_match_value;
    KBYTE ram_dump_flag;
    KBYTE single_step_flag;
    KBYTE debug_on;
};

/* Functions used for the 6502 */
void reset_6502 ( void  );
void run_6502 ( void );
void int_6502 ( void );
void cpu_irq_assert ( void );
void cpu_irq_clear ( void );
void cpu_nmi_edge ( int scanline, int cycle, int request_type, KBYTE nmi_status_reg, int countdown );
void set_int_6502 ( KWORD interupt  );
KBYTE cpu_get_stack_value ( KBYTE address  );
void cpu_set_stack_value ( KBYTE address, KBYTE value  );
int cpu_op_is_rmw_wsync_opcode(KBYTE op);
void assign_ops ( void );

#endif
