#include "types.h"

#include "audio.h"

#include "z80_ctrl.h"


// single channel 8 bits sample driver
u8 isPlayingSample()
{
    u8 *pb;
    u8 ret;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_SAMPLEPLAY, 1);

    Z80_requestBus(1);

    // point to Z80 play status
    pb = (u8 *) 0xA0007C;

    // status
    ret = *pb & 1;

    Z80_releaseBus();

    return ret;
}

void startPlaySample(const u8 *sample, const u32 len, const u16 rate, const u8 pan)
{
    u8 *pb;
    u32 addr;
    u16 r;
    u16 w;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_SAMPLEPLAY, 1);

    Z80_requestBus(1);

    addr = (u32) sample;

    // point to Z80 base parameters
    pb = (u8 *) 0xA00060;

    // sample address
    pb[0x00] = addr >> 0;
    pb[0x01] = addr >> 8;
    pb[0x02] = addr >> 16;

    // sample length
    pb[0x04] = len >> 0;
    pb[0x05] = len >> 8;
    pb[0x06] = len >> 16;

    // pan (left / right / center)
    pb[0x0B] = pan;

    // command
    pb[0x08] |= 1;

    if (rate > 52000) r = 52000;
    else if (rate < 500) r = 500;
    else r = rate;

    w = 3580000 / r;
    if (w > 84)
    {
        w = (w - 69) / 8;
        if (w & 1) w = (w >> 1) + 1;
        else w = w >> 1;
    }
    else w = 1;

    // wait
    pb[0x0A] = w;

    Z80_releaseBus();
}

void stopPlaySample()
{
    u8 *pb;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_SAMPLEPLAY, 1);

    Z80_requestBus(1);

    // point to Z80 command
    pb = (u8 *) 0xA00068;

    // command
    *pb |= 2;

    Z80_releaseBus();
}


// 2 channels 8 bits sample driver
u8 isPlayingSample2C(const u16 channel)
{
    u8 *pb;
    u8 ret;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_2SAMPLESPLAY, 1);

    Z80_requestBus(1);

    // point to Z80 play status
    pb = (u8 *) 0xA0007C;

    // status
    ret = *pb & (1 << channel);

    Z80_releaseBus();

    return ret;
}

void startPlaySample2C(const u16 *sample, const u32 len, const u16 channel)
{
    u8 *pb;
    u32 addr;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_2SAMPLESPLAY, 1);

    Z80_requestBus(1);

    addr = (u32) sample;

    // point to Z80 base parameters
    pb = (u8 *) 0xA00040;

    if (channel == AUDIO_CHANNELAUTO)
    {
        if (pb[0x3C] & 1)
        {
            // channel 0 busy, we use channel 1
            pb[0] |= 2;
            // base parameters address
            pb = (u8 *) 0xA0004C;
        }
        else
        {
            // channel 0 free, we use it
            pb[0] |= 1;
            // base parameters address
            pb = (u8 *) 0xA00044;
        }
    }
    else
    {
        // we use channel specified
        pb[0] |= (1 << channel);
        // base parameters address
        pb = (u8 *) (0xA00044 + (channel << 3));
    }

    // sample address
    pb[0] = addr >> 0;
    pb[1] = addr >> 8;
    pb[2] = addr >> 16;

    // sample length
    pb[4] = len >> 0;
    pb[5] = len >> 8;
    pb[6] = len >> 16;

    Z80_releaseBus();
}

void stopPlaySample2C(const u16 channel)
{
    u8 *pb;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_2SAMPLESPLAY, 1);

    Z80_requestBus(1);

    // point to Z80 base parameters
    pb = (u8 *) 0xA00040;

    // send stop play sample command
    *pb |= 4 << channel;

    Z80_releaseBus();
}

void stopPlayAllSample2C()
{
    stopPlaySample(3);
}


// MVS Tracker
u8 isPlayingMVSTracker()
{
    u8 *pb;
    u8 ret;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_MVSTRACKER, 0);

    Z80_requestBus(1);

    // point to Z80 play status
    pb = (u8 *) 0xA0151D;

    // status
    // 0 :silence 1: loop play 2: play once
    ret = *pb & 3;

    Z80_releaseBus();

    return ret;
}

void startPlayMVSTracker(const u8 *song, const u8 cmd)
{
    u8 *pb;
    u32 addr;


    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_MVSTRACKER, 0);

    Z80_requestBus(1);

    addr = (u32) song;

    // point to Z80 base parameters
    pb = (u8 *) 0xA0151A;

    // song address
    pb[0x00] = addr >> 0;
    pb[0x01] = addr >> 8;
    pb[0x02] = addr >> 16;

    // command
    pb[0x03] = cmd;

    Z80_releaseBus();
}

void stopPlayMVSTracker()
{
    u8 *pb;

    // load the appropried driver if not already done
    Z80_loadDriver(Z80_DRIVER_MVSTRACKER, 0);

    Z80_requestBus(1);

    // point to Z80 command
    pb = (u8 *) 0xA0151D;

    // command
    *pb = 0;

    Z80_releaseBus();
}

