#include "types.h"


#include "vdp.h"
#include "vdp_dma.h"

#include "z80_ctrl.h"


void VDP_DoDMA(u8 area, u32 from, u16 to, u16 len)
{
    volatile u16 *pw;
    volatile u32 *pl;

    VDP_setAutoInc(2);

    pw = (u16 *) GFX_CTRL_PORT;

    /* Setup DMA length (in word here) */
    len >>= 1;
    *pw = 0x9300 + (len & 0xff);
    len >>= 8;
    *pw = 0x9400 + (len & 0xff);

    /* Setup DMA address */
    from >>= 1;
    *pw = 0x9500 + (from & 0xff);
    from >>= 8;
    *pw = 0x9600 + (from & 0xff);
    from >>= 8;
    *pw = 0x9700 + (from & 0xff);

    /* Halt the Z80 for DMA */
//    Z80_RequestBus(0);

    /* Enable DMA */
    pl = (u32 *) GFX_CTRL_PORT;
    switch(area)
    {
        case VDP_DMA_VRAM:
            *pl = GFX_DMA_VRAM_ADDR(to);
            break;

        case VDP_DMA_CRAM:
            *pl = GFX_DMA_CRAM_ADDR(to);
            break;

        case VDP_DMA_VSRAM:
            *pl = GFX_DMA_VSRAM_ADDR(to);
            break;
    }

    /* Enable Z80 */
//    Z80_ReleaseBus();
}

void VDP_DoDMAFill(u8 area, u16 to, u16 len, u16 value)
{
    volatile u16 *pw;
    volatile u32 *pl;

    pw = (u16 *) GFX_CTRL_PORT;

    /* Setup DMA length */
    *pw = 0x9300 + (len & 0xff);
    len >>= 8;
    *pw = 0x9400 + (len & 0xff);

    /* Setup DMA operation (VRAM FILL) */
    *pw = 0x9780;

    /* Enable DMA */
    pl = (u32 *) GFX_CTRL_PORT;
    switch(area)
    {
        case VDP_DMA_VRAM:
            VDP_setAutoInc(1);
            *pl = GFX_DMA_VRAM_ADDR(to);
            break;

        case VDP_DMA_CRAM:
            VDP_setAutoInc(2);
            *pl = GFX_DMA_CRAM_ADDR(to);
            break;

        case VDP_DMA_VSRAM:
            VDP_setAutoInc(2);
            *pl = GFX_DMA_VSRAM_ADDR(to);
            break;
    }

    /* set up value to fill */
    pw = (u16 *) GFX_DATA_PORT;
    *pw = value;
}

void VDP_DoDMACopy(u8 area, u16 from, u16 to, u16 len)
{
    volatile u16 *pw;
    volatile u32 *pl;

    pw = (u16 *) GFX_CTRL_PORT;

    /* Setup DMA length */
    *pw = 0x9300 + (len & 0xff);
    len >>= 8;
    *pw = 0x9400 + (len & 0xff);

    /* Setup DMA address */
    *pw = 0x9500 + (from & 0xff);
    *pw = 0x9600 + ((from >> 8) & 0xff);

    /* Setup DMA operation (VRAM COPY) */
    *pw = 0x97C0;

    /* Enable DMA */
    pl = (u32 *) GFX_CTRL_PORT;
    switch(area)
    {
        case VDP_DMA_VRAM:
            VDP_setAutoInc(1);
            *pl = GFX_DMA_VRAM_ADDR(to);
            break;

        case VDP_DMA_CRAM:
            VDP_setAutoInc(2);
            *pl = GFX_DMA_CRAM_ADDR(to);
            break;

        case VDP_DMA_VSRAM:
            VDP_setAutoInc(2);
            *pl = GFX_DMA_VSRAM_ADDR(to);
            break;
    }
}
