#help_index "God"

DefineListLoad("ST_RHYTHM_COMPLEXITY", "Simple\0Normal\0Complex\0");

class CMakeSongSettings
{
    I64  complexity     format "$LS,D=\"ST_RHYTHM_COMPLEXITY\"$\n";
    Bool rests          format "$CB,\"Rests\"$\n";
    Bool six_eight      format "$CB,\"Six Eight\"$\n";
    I64  octave         format "$DA-TRM,A=\"Octave:%d\"$\n";
    I64  octave_state;
};

U0 InsertNote(CMakeSongSettings *mss, U8 *buf, I64 k, I64 *j)
{//k is a random note nibble
    if (!k && mss->rests)
    {
        buf[*j] = 'R';
        *j += 1;
    }
    else
    {
        k /= 2;
        if (k < 3)
        {
            if (mss->octave_state != mss->octave)
            {
                mss->octave_state = mss->octave;
                buf[*j] = mss->octave_state + '0';
                *j += 1;
            }
            if (!k)
                buf[*j] = 'G';
            else
                buf[*j] = k - 1 + 'A';
            *j += 1;
        }
        else
        {
            if (mss->octave_state != mss->octave + 1)
            {
                mss->octave_state = mss->octave + 1;
                buf[*j] = mss->octave_state + '0';
                *j += 1;
            }
            buf[*j] = k - 1 + 'A';
            *j += 1;
        }
    }
}

#define DUR_4           0
#define DUR_8_8         1
#define DUR_3_3_3       2
#define DUR_16_16_16_16 3
#define DUR_8DOT_16     4
#define DUR_8_16_16     5
#define DUR_16_16_8     6


U8 god_simple_songs [5] = {DUR_4, DUR_4, DUR_4, DUR_4, DUR_8_8};
U8 god_normal_songs [5] = {DUR_4, DUR_4, DUR_8_8, DUR_3_3_3, DUR_16_16_16_16};
U8 god_complex_songs[9] = {DUR_4, DUR_4, DUR_8_8, DUR_8_8, DUR_8DOT_16, DUR_3_3_3, DUR_8_16_16, DUR_16_16_8, DUR_16_16_16_16};

public U8 *GodSongStr()
{//Make God generate 2 measures of a song. Holy Spirit Instructions
    CMakeSongSettings mss;
    U8 *buf;
    I64 i, j=0, k, n, k2, duration, last_duration = -1, len;

    MemSet(&mss, 0, sizeof(mss));
    mss.complexity = 1;
    mss.rests = FALSE;
    mss.octave = music.octave;

    if (!PopUpForm(&mss))
        return NULL;

    buf = CAlloc(256);
    music.octave = mss.octave=ClampI64(mss.octave, 1, 7);
    progress4 = 0;
    if (mss.six_eight)
        progress4_max = 6;
    else
        progress4_max = 8;

    mss.octave_state = mss.octave + 1;
    buf[j++] = '0' + mss.octave_state;
    if (mss.six_eight)
    {
        len = 6;
        buf[j++] = 'M';
        buf[j++] = '6';
        buf[j++] = '/';
        buf[j++] = '8';
    }
    else
        len = 8;
    FifoU8Flush(god.fifo);
    for (i = 0; i < len; i++)
    {
        n = GodBitsRemove(8);
        if (mss.complexity == 2)
            duration = god_complex_songs[n % 9];
        else if (mss.complexity == 1)
            duration = god_normal_songs[n % 5];
        else
            duration = god_simple_songs[n % 5];

        switch (duration)
        {
            case DUR_8_8:
                if (last_duration != DUR_8_8)
                    buf[j++] = 'e';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                break;

            case DUR_8DOT_16:
                buf[j++] = 'e';
                buf[j++] = '.';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                buf[j++] = 's';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                duration = DUR_16_16_16_16;
                break;

            case DUR_3_3_3:
                if (last_duration != DUR_3_3_3)
                {
                    buf[j++] = 'e';
                    buf[j++] = 't';
                }
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                break;

            case DUR_8_16_16:
                if (last_duration != DUR_8_8)
                    buf[j++] = 'e';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                buf[j++] = 's';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                duration = DUR_16_16_16_16;
                break;

            case DUR_16_16_8:
                if (last_duration != DUR_16_16_16_16)
                    buf[j++] = 's';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                buf[j++] = 'e';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
                duration = DUR_8_8;
                break;

            case DUR_16_16_16_16:
                if (last_duration != DUR_16_16_16_16)
                    buf[j++] = 's';
                k  = GodBitsRemove(4);
                k2 = GodBitsRemove(4);
                InsertNote(&mss, buf, k, &j);
                InsertNote(&mss, buf, k2, &j);
                InsertNote(&mss, buf, k, &j);
                InsertNote(&mss, buf, k2, &j);
                break;

            default:
                if (last_duration != DUR_4)
                    buf[j++] = 'q';
                InsertNote(&mss, buf, GodBitsRemove(4), &j);
        }
        last_duration = duration;
        progress4++;
    }
    buf[j++] = 0;
    progress4 = progress4_max = 0;
    return buf;
}

public U0 GodSong()
{//Make God generate 2measuresx2+2measuresx2. Holy Spirit Instructions
    U8 *st1 = GodSongStr,
       *st2 = GodSongStr;

    if (st1 && st2)
        DocPrint(DocPut, "$SO,\"<Song>\",A=\"%s%s%s%s\"$", st1, st1, st2, st2);
    Free(st1);
    Free(st2);
}