/******************************************************************************
*
* 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: gtia.h
*
* DESCRIPTION:  This contains function declartions for gtia video functions
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.1     07/18/04  bberlin      Creation
* 0.4.0   07/11/06  bberlin      Added hi-res artifact variables
* 0.5.0   08/25/06  bberlin      Added 'gtia_bottom_button' functions here
* 0.5.0   08/28/06  bberlin      Changed all color vars to unsigned in case we
*                                  want to support 32-bit pixels
******************************************************************************/
#ifndef gtia_h
#define gtia_h

#include "boom6502.h"

/*#define NEW_VIDEO_METHOD 1*/

#define HPOSP0  0x00
#define HPOSP1  0x01
#define HPOSP2  0x02
#define HPOSP3  0x03

#define HPOSM0  0x04
#define HPOSM1  0x05
#define HPOSM2  0x06
#define HPOSM3  0x07

#define SIZEP0  0x08
#define SIZEP1  0x09
#define SIZEP2  0x0a
#define SIZEP3  0x0b
#define SIZEM   0x0c

#define GRAFP0  0x0d
#define GRAFP1  0x0e
#define GRAFP2  0x0f
#define GRAFP3  0x10
#define GRAFM   0x11

/* overlap color */
#define COLOVP1  0x00
#define COLOVP2  0x01

#define COLPM0  0x12
#define COLPM1  0x13
#define COLPM2  0x14
#define COLPM3  0x15

#define COLPF0  0x16
#define COLPF1  0x17
#define COLPF2  0x18
#define COLPF3  0x19
#define COLBK   0x1a

#define M0PF    0x00
#define M1PF    0x01
#define M2PF    0x02
#define M3PF    0x03

#define P0PF    0x04
#define P1PF    0x05
#define P2PF    0x06
#define P3PF    0x07

#define M0PL    0x08
#define M1PL    0x09
#define M2PL    0x0a
#define M3PL    0x0b

#define P0PL    0x0c
#define P1PL    0x0d
#define P2PL    0x0e
#define P3PL    0x0f

#define PRIOR   0x1b
#define VDELAY  0x1c

#define PALR    0x14
#define CONSOL  0x1f

#define GRACTL  0x1d
#define HITCLR  0x1e
#define TRIG0   0x10
#define TRIG1   0x11
#define TRIG2   0x12
#define TRIG3   0x13

#define NTSC   0xf
#define PAL    0x1

/* Color PRIOR Masks */
#define BK_MASK  0x001
#define PF3_MASK 0x002
#define PF2_MASK 0x004
#define PF1_MASK 0x008
#define PF0_MASK 0x010
#define PM3_MASK 0x020
#define PM2_MASK 0x040
#define PM1_MASK 0x080
#define PM0_MASK 0x100
#define MODE2_MASK 0x2000
#define PRIOR_SHIFT 9 

#define BAK_BYTE  0
#define PF3_BYTE  4
#define PF2_BYTE  3
#define PF1_BYTE  2
#define PF0_BYTE  1

struct gtia_surface {
    unsigned char *start;
    unsigned char *current;
    int width;
    int bytes_per_pixel;
    int line_only;
};

typedef struct {
    KBYTE r_reg[0x20];
    KBYTE w_reg[0x20];

    KBYTE pal_or_ntsc;

    /* CONSOL register                  */
    KBYTE  keypad;
    KBYTE pot_enable;
    KBYTE console_reg;
    KBYTE console_mask;
    KBYTE option_pressed;
    KBYTE select_pressed;
    KBYTE start_pressed;
    KBYTE internal_speaker;

    /* player-missle graphics registers */
    KBYTE graph_p0_reg;
    KBYTE graph_p1_reg;
    KBYTE graph_p2_reg;
    KBYTE graph_p3_reg;
    KBYTE graph_m_reg;

    KBYTE graph_p0_line[0x200];
    KBYTE graph_p1_line[0x200];
    KBYTE graph_p2_line[0x200];
    KBYTE graph_p3_line[0x200];
    KBYTE graph_m0_line[0x200];
    KBYTE graph_m1_line[0x200];
    KBYTE graph_m2_line[0x200];
    KBYTE graph_m3_line[0x200];

    int hpos_p0_reg;
    int hpos_p1_reg;
    int hpos_p2_reg;
    int hpos_p3_reg;
    int hpos_m0_reg;
    int hpos_m1_reg;
    int hpos_m2_reg;
    int hpos_m3_reg;

    KBYTE size_p0_reg;
    KBYTE size_p1_reg;
    KBYTE size_p2_reg;
    KBYTE size_p3_reg;
    KBYTE size_m0_reg;
    KBYTE size_m1_reg;
    KBYTE size_m2_reg;
    KBYTE size_m3_reg;

    /* vertical delay                        */
    KBYTE vdelay_reg;
    void ( *transfer_p0_ptr[2] ) ( void );
    void ( *transfer_p1_ptr[2] ) ( void );
    void ( *transfer_p2_ptr[2] ) ( void );
    void ( *transfer_p3_ptr[2] ) ( void );
    void ( *transfer_m0_ptr[2] ) ( void );
    void ( *transfer_m1_ptr[2] ) ( void );
    void ( *transfer_m2_ptr[2] ) ( void );
    void ( *transfer_m3_ptr[2] ) ( void );

    /* need backup of the actual register value  */
    KBYTE color_pm0_reg;
    KBYTE color_pm1_reg;
    KBYTE color_pm2_reg;
    KBYTE color_pm3_reg;
    KBYTE color_pf0_reg;
    KBYTE color_pf1_reg;
    KBYTE color_pf2_reg;
    KBYTE color_pf3_reg;
    KBYTE color_bk_reg;

    /* Use the overlap color for players - PRIOR */
    KBYTE prior_overlap_flag;

    struct gtia_surface d_surface;
    unsigned int *color_array;
    unsigned int col_blk;
    unsigned int col_bk;
    unsigned int col_pm0;
    unsigned int col_pm1;
    unsigned int col_pm2;
    unsigned int col_pm3;
    unsigned int col_pf0;
    unsigned int col_pf1;
    unsigned int col_pf2;
    unsigned int col_pf3;
    unsigned int col_ov01;
    unsigned int col_ov23;

    /* Antic Mode 2,3,f colors for lum only                    */
    unsigned int col_pm0_mode2_set;
    unsigned int col_pm1_mode2_set;
    unsigned int col_pm2_mode2_set;
    unsigned int col_pm3_mode2_set;
    unsigned int col_pm0_mode2_clear;
    unsigned int col_pm1_mode2_clear;
    unsigned int col_pm2_mode2_clear;
    unsigned int col_pm3_mode2_clear;

    unsigned int col_pf3_mode2_set;
    unsigned int col_pf3_mode2_clear;
    unsigned int col_pf1_mode2;
    unsigned int hi_res_current_table[8];
    unsigned int **hi_res_current_ptr_array;

    /* GTIA Mode 1 or 3 colors                                 */
    unsigned int *gtia_mode_col_ptr;
    void ( *gtia_set_byte_mode_2_ptr ) ( void );
    unsigned int gtia_mode_col[2][16];

    /* Priority array containing pointers to colrs       */
    /* The mask will indicate PRIOR, GTIA Mode, Overlap, Mode 2 */
    KBYTE prior_reg;
    unsigned int *prior_ptr_array[0x4000];
    unsigned int prior_mask;
    int prior_overlap;

    unsigned int missle0_mask;
    unsigned int missle1_mask;
    unsigned int missle2_mask;
    unsigned int missle3_mask;
    int gtia_mode;

    /*
     * GTIA mode 10 is delayed by one color clock. These carry the last
     * delayed color clock from one 32-pixel draw block into the next.
     */
    unsigned int gtia_mode10_delay_pm0;
    unsigned int gtia_mode10_delay_pm1;
    unsigned int gtia_mode10_delay_pm2;
    unsigned int gtia_mode10_delay_pm3;
    unsigned int gtia_mode10_delay_pf0;
    unsigned int gtia_mode10_delay_pf1;
    unsigned int gtia_mode10_delay_pf2;
    unsigned int gtia_mode10_delay_pf3;
    unsigned int gtia_mode10_delay_bak;

    /* HSCROL fetch pixels before the visible GTIA-mode edge. */
    int gtia_mode_left_edge_offset;

    /* collisions will have array that is updated on pixel write       */
    KBYTE collision_p0pf[4];
    KBYTE collision_p1pf[4];
    KBYTE collision_p2pf[4];
    KBYTE collision_p3pf[4];
    KBYTE collision_p0pl[4];
    KBYTE collision_p1pl[4];
    KBYTE collision_p2pl[4];
    KBYTE collision_p3pl[4];

    KBYTE collision_m0pf[4];
    KBYTE collision_m1pf[4];
    KBYTE collision_m2pf[4];
    KBYTE collision_m3pf[4];
    KBYTE collision_m0pl[4];
    KBYTE collision_m1pl[4];
    KBYTE collision_m2pl[4];
    KBYTE collision_m3pl[4];

    /* collision registers              */
    KBYTE p0pl_reg;
    KBYTE p1pl_reg;
    KBYTE p2pl_reg;
    KBYTE p3pl_reg;
    KBYTE p0pf_reg;
    KBYTE p1pf_reg;
    KBYTE p2pf_reg;
    KBYTE p3pf_reg;
    KBYTE m0pl_reg;
    KBYTE m1pl_reg;
    KBYTE m2pl_reg;
    KBYTE m3pl_reg;
    KBYTE m0pf_reg;
    KBYTE m1pf_reg;
    KBYTE m2pf_reg;
    KBYTE m3pf_reg;

    /* graphics control, triggers       */
    KBYTE latch_triggers;
    KBYTE player_dma;
    KBYTE missle_dma;

    KBYTE trig[4];
    KBYTE trig_held_down[4];

    /* Playfield bytes set by antic     */
    KBYTE pf_byte[5];

    KBYTE pf_x_byte;
    unsigned int *pf_x_start_ptr;
    int  pf_x;
} t_gtia;

void gtia_transfer_nothing (void);
void gtia_transfer_p0 (void);
void gtia_transfer_p1 (void);
void gtia_transfer_p2 (void);
void gtia_transfer_p3 (void);
void gtia_transfer_m0 (void);
void gtia_transfer_m1 (void);
void gtia_transfer_m2 (void);
void gtia_transfer_m3 (void);

void gtia_init_prior_array ( void );

void gtia_set_blank_line (void);

void gtia_set_byte_blank (void);
void gtia_set_byte_mode_2 (void);
void gtia_set_byte_mode_f (void);
void gtia_set_byte_mode_2_g1g3 (void);
void gtia_set_byte_mode_2_g2 (void);
void gtia_set_byte_mode_4 (void);

void gtia_reset ( int tv_standard );
void gtia_set_screen ( void *surface, unsigned int *color_array, int width, 
                        int bpp, int line_only );
void gtia_get_screen ( void **surface, int *width, int *bpp );
void gtia_set_mode_2_draw_ptr ( void );
KBYTE gtia_read_register ( KWORD addr );
void gtia_write_register ( KWORD addr, KBYTE value );
KBYTE gtia_read_register_debug ( KWORD addr );
void gtia_write_register_debug ( KWORD addr, KBYTE value );
int gtia_bottom_button_down ( int player, int temp, int temp1 );
int gtia_bottom_button_up ( int player, int temp, int temp1 );
void gtia_set_bottom_button_auto_fire ( int player, int down );
void gtia_reset_triggers ( void );
int gtia_set_switch ( int mask, int value );
void gtia_write_console ( KBYTE value );
void gtia_write_collision ( KWORD addr, KBYTE value );
void gtia_init_scanline ( void );
void gtia_end_scanline ( void );
void gtia_draw_scanline ( void );

#endif
