
#include "shared.h"

/* Global data */
vuint16 *vdp1_vram = (vuint16 *)VDP1_VRAM;
vuint16 *vdp1_fb   = (vuint16 *)VDP1_FRAMEBUFFER;
vuint16 *vdp2_vram = (vuint16 *)VDP2_VRAM;
vuint16 *vdp2_cram = (vuint16 *)VDP2_CRAM;
vuint16 *vdp2_reg  = (vuint16 *)VDP2_REGISTER_BASE;

void vdp_init(void)
{
    int i;
    TVMD = 0x0000;

    *((unsigned short *) 0x25f8000e) = *((unsigned short *) 0x25f8000e) & (~0x3000);

    // Map Offset Register: Bitmap screen will be located at VRAM offset 0
    /*0x25f8003c*/MPOFN = 0;

    // Character Control Register: 256 colors, enable NBG0 as a bitmap
    // |8 for 1024x256 bitmap
    /*0x25f80028*/CHCTLA = 0x0012|8;

    // Screen Scroll Value Registers: No scroll
    /*0x25f80070*/SCXIN0 = 0;
    /*0x25f80072*/SCXDN0 = 0;
    /*0x25f80074*/SCYIN0 = 0;

    // Screen Display Enable Register: Invalidate the transparency code for
    // NBG0 and display NBG0
    /*0x25f80020*/BGON = 0x0001;

    /* Clear VRAM */
    for(i = 0; i < 0x40000; i++)
        vdp2_vram[i] = 0x0000;

    /* Clear CRAM */
    for(i = 0; i < 0x0800; i++)
        vdp2_cram[i] = 0x0000;


    /* Init global variables. */
    list_index = 1;
    mesh_flag = 0;
}

void vdp_shutdown(void)
{
    int i;

    TVMD = 0x0000;

    for(i = 0; i < 0x100; i++)
        vdp2_reg[i] = 0x0000;

    for(i = 0; i < 0x40000; i++)
        vdp2_vram[i] = 0x0000;

    for(i = 0; i < 0x0800; i++)
        vdp2_cram[i] = 0x0000;
}

void wait_hblank_in(void)
{
    while((TVSTAT & 4) == 0);
}

void wait_hblank_out(void)
{
    while((TVSTAT & 4) == 4);
}

void wait_vblank_in(void)
{
    while((TVSTAT & 8) == 0);
}

void wait_vblank_out(void)
{
    while((TVSTAT & 8) == 8);
}

void wait_vblank(void)
{
    while((TVSTAT & 8) == 0);
    while((TVSTAT & 8) == 8);
}

void wait_hblank(void)
{
    while((TVSTAT & 4) == 0);
    while((TVSTAT & 4) == 4);
}


/* Wait for V-Blank + perform transfers for SatCom. */
void my_wait_vblank(void)
{
    /* SatCom: if needed, transfer data. */
    sc_check();

    /* Wait for V-Blank. */
    wait_vblank_out();
    wait_vblank_in();
}

/* Clear command list */
unsigned short list_index = 1;  /* Offset into the command list */
unsigned short mesh_flag = 0;   /* Global mesh enable flag */
void list_clear(void)
{
    unsigned short *p = (unsigned short *)VDP1_VRAM;
    int i;
    for(i=0;i<16;i++)
        p[i] = 0xFFFF;
    p[CMDCTRL] = 0x4000;
    list_index = 1;
}

/* Add end marker to command list */
void list_end(void)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));
    p[CMDCTRL] = 0x8000;
    list_index++;
}

/* Add system clip to command list */
void list_set_system_clip(short x, short y)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x0009; /* Set system clip */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDXC]   = x;
    p[CMDYC]   = y;
    list_index++;
}


/* Add user clip to command list */
void list_set_user_clip(short x1, short y1, short x2, short y2)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x0008; /* Set user clip */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDXA]   = x1;
    p[CMDYA]   = y1;
    p[CMDXC]   = x2;
    p[CMDYC]   = y2;
    list_index++;
}

/* Add local coords to command list */
void list_set_local_coords(short x, short y)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x000A; /* Set local coords */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDXA]   = x;
    p[CMDYA]   = y;
    list_index++;
}

/* Add local coords to command list */
void list_polyline(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, unsigned short color)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x0005; /* Polyline */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDPMOD] = 0x00C0 | mesh_flag;
    p[CMDCOLR] = color;
    p[CMDXA]   = x1;
    p[CMDYA]   = y1;
    p[CMDXB]   = x2;
    p[CMDYB]   = y2;
    p[CMDXC]   = x3;
    p[CMDYC]   = y3;
    p[CMDXD]   = x4;
    p[CMDYD]   = y4;
    list_index++;
}

/* Add local coords to command list */
void list_polygon(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, unsigned short color, unsigned long grda)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x0004; /* Polygon */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDPMOD] = 0x00C0 | mesh_flag | 4;
    p[CMDCOLR] = color;
    p[CMDXA]   = x1;
    p[CMDYA]   = y1;
    p[CMDXB]   = x2;
    p[CMDYB]   = y2;
    p[CMDXC]   = x3;
    p[CMDYC]   = y3;
    p[CMDXD]   = x4;
    p[CMDYD]   = y4;
    p[CMDGRDA] = grda>>3;
    list_index++;
}

/* Add local coords to command list */
void list_distorted_sprite(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4, unsigned long source, int w, int h)
{
    unsigned short *p = (unsigned short *)(VDP1_VRAM + (list_index << 5));

    p[CMDCTRL] = 0x1002; /* Distorted sprite, RGB mode */
    p[CMDLINK] = 0x0000; /* Jump address */
    p[CMDPMOD] = 0x00A8 | mesh_flag;
    p[CMDCOLR] = 0;
    p[CMDSRCA] = source;
    p[CMDSIZE] = (((w>>3)&0x3F)<<8)|(h&0xFF);
    p[CMDXA]   = x1;
    p[CMDYA]   = y1;
    p[CMDXB]   = x2;
    p[CMDYB]   = y2;
    p[CMDXC]   = x3;
    p[CMDYC]   = y3;
    p[CMDXD]   = x4;
    p[CMDYD]   = y4;
    list_index++;
}

