# include "all.h"







////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////



unsigned short ST_Table[96] =
{ 0xef8, 0xe10, 0xd60, 0xc80, 0xbd8, 0xb28, 0xa88, 0x9f0, 0x960, 0x8e0, 0x858, 0x7e0, 0x77c, 0x708, 0x6b0, 0x640, 0x5ec, 0x594, 0x544, 0x4f8, 0x4b0, 0x470, 0x42c, 0x3f0, 0x3be, 0x384, 0x358, 0x320, 0x2f6, 0x2ca, 0x2a2, 0x27c, 0x258, 0x238, 0x216, 0x1f8, 0x1df, 0x1c2, 0x1ac, 0x190, 0x17b, 0x165, 0x151, 0x13e, 0x12c, 0x11c, 0x10b, 0xfc, 0xef, 0xe1, 0xd6, 0xc8, 0xbd, 0xb2, 0xa8, 0x9f, 0x96, 0x8e, 0x85, 0x7e, 0x77, 0x70, 0x6b, 0x64, 0x5e, 0x59, 0x54, 0x4f, 0x4b, 0x47, 0x42, 0x3f, 0x3b, 0x38, 0x35, 0x32, 0x2f, 0x2c, 0x2a, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1c, 0x1a, 0x19, 0x17, 0x16, 0x15, 0x13, 0x12, 0x11, 0x10, 0xf };


//Sound tracker PRO player. KSA.

typedef struct 
{
    unsigned char STP_Delay;
    unsigned char STP_PositionsPointer0, STP_PositionsPointer1;
    unsigned char STP_PatternsPointer0, STP_PatternsPointer1;
    unsigned char STP_OrnamentsPointer0, STP_OrnamentsPointer1;
    unsigned char STP_SamplesPointer0, STP_SamplesPointer1;
    unsigned char STP_Init_Id;
} STP_File;

typedef struct 
{
    unsigned short OrnamentPointer, SamplePointer, Address_In_Pattern, Ton;
    unsigned char Position_In_Ornament, Loop_Ornament_Position, Ornament_Length, Position_In_Sample, Loop_Sample_Position, Sample_Length, Volume, Number_Of_Notes_To_Skip, Note, Amplitude;
    signed short Current_Ton_Sliding;
    bool Envelope_Enabled, Enabled;
    signed char Glissade, Note_Skip_Counter;
}STP_Channel_Parameters;

typedef struct 
{
    unsigned char DelayCounter, CurrentPosition, Transposition;
} STP_Parameters;

typedef struct 
{
    STP_Parameters STP;
    STP_Channel_Parameters STP_A, STP_B, STP_C;
} STP_SongInfo;

STP_SongInfo stp;

#define STP_A (((STP_SongInfo *)info->data)->STP_A)
#define STP_B (((STP_SongInfo *)info->data)->STP_B)
#define STP_C (((STP_SongInfo *)info->data)->STP_C)
#define STP (((STP_SongInfo *)info->data)->STP)

char * KsaId = "KSA SOFTWARE COMPILATION OF ";

#define STP_PositionsPointer (header->STP_PositionsPointer0 | (header->STP_PositionsPointer1 << 8))
#define STP_OrnamentsPointer (header->STP_OrnamentsPointer0 | (header->STP_OrnamentsPointer1 << 8))
#define STP_PatternsPointer (header->STP_PatternsPointer0 | (header->STP_PatternsPointer1 << 8))
#define STP_SamplesPointer (header->STP_SamplesPointer0 | (header->STP_SamplesPointer1 << 8))
#define STP_Delay (header->STP_Delay)

void STP_Init(AYSongInfo * info)
{
    unsigned char *module = info->module;
    STP_File *header = (STP_File *)module;
    
    
    ////*
    info->data = &stp;
        
    memset(&STP_A, 0, sizeof(STP_Channel_Parameters));
    memset(&STP_B, 0, sizeof(STP_Channel_Parameters));
    memset(&STP_C, 0, sizeof(STP_Channel_Parameters));

    STP.DelayCounter = 1;
    STP.Transposition = module[STP_PositionsPointer + 3];
    STP.CurrentPosition = 0;
    STP_A.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2]]);
    STP_B.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2] + 2]);
    STP_C.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2] + 4]);

    STP_A.SamplePointer = ay_sys_getword(&module[STP_SamplesPointer]);
    STP_A.Loop_Sample_Position = module[STP_A.SamplePointer];
    STP_A.SamplePointer++;
    STP_A.Sample_Length = module[STP_A.SamplePointer];
    STP_A.SamplePointer++;
    STP_B.SamplePointer = STP_A.SamplePointer;
    STP_B.Loop_Sample_Position = STP_A.Loop_Sample_Position;
    STP_B.Sample_Length = STP_A.Sample_Length;
    STP_C.SamplePointer = STP_A.SamplePointer;
    STP_C.Loop_Sample_Position = STP_A.Loop_Sample_Position;
    STP_C.Sample_Length = STP_A.Sample_Length;

    STP_A.OrnamentPointer = ay_sys_getword(&module[STP_OrnamentsPointer]);
    STP_A.Loop_Ornament_Position = module[STP_A.OrnamentPointer];
    STP_A.OrnamentPointer++;
    STP_A.Ornament_Length = module[STP_A.OrnamentPointer];
    STP_A.OrnamentPointer++;
    STP_B.OrnamentPointer = STP_A.OrnamentPointer;
    STP_B.Loop_Ornament_Position = STP_A.Loop_Ornament_Position;
    STP_B.Ornament_Length = STP_A.Ornament_Length;
    STP_C.OrnamentPointer = STP_A.OrnamentPointer;
    STP_C.Loop_Ornament_Position = STP_A.Loop_Ornament_Position;
    STP_C.Ornament_Length = STP_A.Ornament_Length;

    STP_A.Envelope_Enabled = false;
    STP_A.Glissade = 0;
    STP_A.Current_Ton_Sliding = 0;
    STP_A.Enabled = false;
    STP_A.Number_Of_Notes_To_Skip = 0;
    STP_A.Note_Skip_Counter = 0;
    STP_A.Volume = 0;
    STP_A.Ton = 0;

    STP_B.Envelope_Enabled = false;
    STP_B.Glissade = 0;
    STP_B.Current_Ton_Sliding = 0;
    STP_B.Enabled = false;
    STP_B.Number_Of_Notes_To_Skip = 0;
    STP_B.Note_Skip_Counter = 0;
    STP_B.Volume = 0;
    STP_B.Ton = 0;

    STP_C.Envelope_Enabled = false;
    STP_C.Glissade = 0;
    STP_C.Current_Ton_Sliding = 0;
    STP_C.Enabled = false;
    STP_C.Number_Of_Notes_To_Skip = 0;
    STP_C.Note_Skip_Counter = 0;
    STP_C.Volume = 0;
    STP_C.Ton = 0;
    
	info->slow = 0;
  //  */
}

void STP_GetInfo(AYSongInfo * info)
{
    unsigned long tm = 0;
    unsigned char a = 1;
    unsigned long i, j1;
    unsigned char *module = info->module;
    unsigned char stDelay = module[0];
    unsigned short stPosPt = ay_sys_getword(&module[1]);
    unsigned long stPatPt = ay_sys_getword(&module[3]);

    for(i = 0; i < module[stPosPt]; i++)
    {
        //if(i == module[stPosPt + 1])
          //  info->Loop = tm * stDelay;
          
        j1 = ay_sys_getword(&module[stPatPt + module[stPosPt + 2 + i * 2]]);
        while(module[j1] != 0)
        {
            unsigned char val = module[j1];
            if((val >= 1 && val <= 0x60) || (val >= 0xd0 && val <= 0xef))
            {
                tm += a;
            }
            else if(val >= 0x80 && val <= 0xbf)
            {
                a = val - 0x7f;
            }
            else if((val >= 0xc0 && val <= 0xcf) || val == 0xf0)
            {
                j1++;
            }
            j1++;
        }
    }
    tm *= stDelay;
    info->len = tm;
    if(!memcmp((void *)&module[10], (void *)KsaId, 28))
        strncpy(info->Name, &module[38], 25);
}

void STP_PatternInterpreter(AYSongInfo * info, STP_Channel_Parameters * chan)
{
///*
    unsigned char *module = info->module;
    STP_File *header = (STP_File *)module;
    bool quit = false;

    do
    {
        unsigned char val = module[chan->Address_In_Pattern];
        if(val >= 1 && val <= 0x60)
        {
            chan->Note = val - 1;
            chan->Position_In_Sample = 0;
            chan->Position_In_Ornament = 0;
            chan->Current_Ton_Sliding = 0;
            chan->Enabled = true;
            quit = true;
        }
        else if(val >= 0x61 && val <= 0x6f)
        {
            chan->SamplePointer = ay_sys_getword(&module[STP_SamplesPointer + (val - 0x61) * 2]);
            chan->Loop_Sample_Position = module[chan->SamplePointer];
            chan->SamplePointer++;
            chan->Sample_Length = module[chan->SamplePointer];
            chan->SamplePointer++;
        }
        else if(val >= 0x70 && val <= 0x7f)
        {
            chan->OrnamentPointer = ay_sys_getword(&module[STP_OrnamentsPointer + (val - 0x70) * 2]);
            chan->Loop_Ornament_Position = module[chan->OrnamentPointer];
            chan->OrnamentPointer++;
            chan->Ornament_Length = module[chan->OrnamentPointer];
            chan->OrnamentPointer++;
            chan->Envelope_Enabled = false;
            chan->Glissade = 0;
        }
        else if(val >= 0x80 && val <= 0xbf)
        {
            chan->Number_Of_Notes_To_Skip = val - 0x80;
        }
        else if(val >= 0xc0 && val <= 0xcf)
        {
            if(val != 0xc0)
            {
                ay_writeay(AY_ENV_SHAPE, val - 0xc0);
                chan->Address_In_Pattern++;
                ay_writeay(AY_ENV_FINE, module[chan->Address_In_Pattern]);
            }
            chan->Envelope_Enabled = true;
            chan->Loop_Ornament_Position = 0;
            chan->Glissade = 0;
            chan->Ornament_Length = 1;
        }
        else if(val >= 0xd0 && val <= 0xdf)
        {
            chan->Enabled = false;
            quit = true;
        }
        else if(val >= 0xe0 && val <= 0xef)
        {
            quit = true;
        }
        else if(val == 0xf0)
        {
            chan->Address_In_Pattern++;
            chan->Glissade = module[chan->Address_In_Pattern];
        }
        else if((unsigned char)val >= 0xf1)
        {
            chan->Volume = val - 0xf1;
        }
        chan->Address_In_Pattern++;
    }
    while(!quit);
    chan->Note_Skip_Counter = chan->Number_Of_Notes_To_Skip;

//*/
}


void STP_GetRegisters(AYSongInfo * info, STP_Channel_Parameters * chan, unsigned char * TempMixer)
{
///*

    unsigned char *module = info->module;
    STP_File *header = (STP_File *)module;
    unsigned char j, b0, b1;
    if(chan->Enabled)
    {
        chan->Current_Ton_Sliding += chan->Glissade;
        if(chan->Envelope_Enabled)
            j = chan->Note + STP.Transposition;
        else
            j = chan->Note + STP.Transposition + module[chan->OrnamentPointer + chan->Position_In_Ornament];
        if(j > 95)
            j = 95;
        b0 = module[chan->SamplePointer + chan->Position_In_Sample * 4];
        b1 = module[chan->SamplePointer + chan->Position_In_Sample * 4 + 1];
        chan->Ton = (ST_Table[j] + chan->Current_Ton_Sliding + ay_sys_getword(&module[chan->SamplePointer + chan->Position_In_Sample * 4 + 2])) & 0xfff;
        chan->Amplitude = (b0 & 15) - chan->Volume;
        if((signed char)(chan->Amplitude) < 0)
            chan->Amplitude = 0;
        if(((b1 & 1) != 0) && chan->Envelope_Enabled)
            chan->Amplitude = chan->Amplitude | 16;
        *TempMixer = ((b0 >> 1) & 0x48) | *TempMixer;
        if((signed char)(b0) >= 0)
            ay_writeay(AY_NOISE_PERIOD, (b1 >> 1) & 31);
        chan->Position_In_Ornament++;
        if(chan->Position_In_Ornament >= chan->Ornament_Length)
            chan->Position_In_Ornament = chan->Loop_Ornament_Position;
        chan->Position_In_Sample++;
        if(chan->Position_In_Sample >= chan->Sample_Length)
        {
            chan->Position_In_Sample = chan->Loop_Sample_Position;
            if((signed char)(chan->Loop_Sample_Position) < 0)
                chan->Enabled = false;
        }
    }
    else
    {
        *TempMixer = *TempMixer | 0x48;
        chan->Amplitude = 0;
    }
    *TempMixer = *TempMixer >> 1;

//*/
}

void STP_Play(AYSongInfo * info)
{

    unsigned char *module = info->module;
    STP_File *header = (STP_File *)module;
    unsigned char TempMixer;
    STP.DelayCounter--;
    if(STP.DelayCounter == 0)
    {
        STP.DelayCounter = STP_Delay;
        STP_A.Note_Skip_Counter--;
        if(STP_A.Note_Skip_Counter < 0)
        {
            if(module[STP_A.Address_In_Pattern] == 0)
            {
                STP.CurrentPosition++;
                if(STP.CurrentPosition == module[STP_PositionsPointer])
                    STP.CurrentPosition = module[STP_PositionsPointer + 1];
                STP_A.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2 + STP.CurrentPosition * 2]]);
                STP_B.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2 + STP.CurrentPosition * 2] + 2]);
                STP_C.Address_In_Pattern = ay_sys_getword(&module[STP_PatternsPointer + module[STP_PositionsPointer + 2 + STP.CurrentPosition * 2] + 4]);
                STP.Transposition = module[STP_PositionsPointer + 3 + STP.CurrentPosition * 2];
            }
            STP_PatternInterpreter(info, &STP_A);
        }
        STP_B.Note_Skip_Counter--;
        if(STP_B.Note_Skip_Counter < 0)
            STP_PatternInterpreter(info, &STP_B);
        STP_C.Note_Skip_Counter--;
        if(STP_C.Note_Skip_Counter < 0)
            STP_PatternInterpreter(info, &STP_C);
    }

    TempMixer = 0;
    STP_GetRegisters(info, &STP_A, &TempMixer);
    STP_GetRegisters(info, &STP_B, &TempMixer);
    STP_GetRegisters(info, &STP_C, &TempMixer);

    ay_writeay(AY_MIXER, TempMixer);

    ay_writeay(AY_CHNL_A_FINE, STP_A.Ton & 0xff);
    ay_writeay(AY_CHNL_A_COARSE, (STP_A.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_B_FINE, STP_B.Ton & 0xff);
    ay_writeay(AY_CHNL_B_COARSE, (STP_B.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_C_FINE, STP_C.Ton & 0xff);
    ay_writeay(AY_CHNL_C_COARSE, (STP_C.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_A_VOL, STP_A.Amplitude);
    ay_writeay(AY_CHNL_B_VOL, STP_B.Amplitude);
    ay_writeay(AY_CHNL_C_VOL, STP_C.Amplitude);

}


bool STP_Detect(unsigned char *module, unsigned int length, AYSongInfo * s)
{
    STP_File *header = (STP_File *)module;
    int j, j1, j2, j3;
    long F_Length; long F_Address;
    
   
    if(length < 10)
        return false;
    if(STP_PositionsPointer> length)
        return false;
    if(STP_PatternsPointer> length)
        return false;
    if(STP_OrnamentsPointer> length)
        return false;
    if(STP_SamplesPointer> length)
        return false;
    if((STP_SamplesPointer- STP_OrnamentsPointer) != 0x20)
    return false;
    if((int)(STP_OrnamentsPointer - STP_PatternsPointer) <= 0)
    return false;
    if(((STP_OrnamentsPointer - STP_PatternsPointer) % 6) != 0)
    return false;
    if((module[STP_PositionsPointer] * 2 + 2 + STP_PositionsPointer - STP_PatternsPointer) != 0)
    return false;
    F_Length = STP_SamplesPointer + 30;
    if(F_Length> 65535)
    return false;
    if(F_Length> length + 1)
    return false;

    j2 = 0;
    j3 = header->STP_Init_Id;
    if(j3 == 0)
    {
        j2 = ay_sys_getword(&module[STP_PatternsPointer]);
        
        
        if(!strncmp((char *)(&module [10]), (char *)(KsaId), (size_t)(strlen(KsaId))))
        j2 -= 0xa + 53;
        else
        j2 -= 0xa;
      
        
        if(j2 < 0)
        return false;
         F_Address = j2;
        j3 = (F_Length - STP_PatternsPointer) / 2;
        for(j1 = 0; j1 < j3; j1++)
        {
            j = ay_sys_getword(&module[STP_PatternsPointer + j1 * 2]);
            j -= j2;
            ay_sys_writeword(&module[STP_PatternsPointer + j1 * 2], j);
        }
    }

    j = ay_sys_getword(&module[STP_OrnamentsPointer]);
    j--;
    if((unsigned long)(j) <= (unsigned long)(length - 1))
    {
        j = ay_sys_getword(&module [j]);
        if(j == 0)
        {
            header->STP_Init_Id = j3;
            strcpy(s->player, "Sound Tracker Pro");
            return true;
        }
    }

    /*for(j1 = 0; j1 < j3; j1++)
    {
        j = ay_sys_getword(&module[STP_PatternsPointer + j1 * 2]);
        j += j2;
        ay_sys_writeword(&module[STP_PatternsPointer + j1 * 2], j);
    }*/

    return false;
}






typedef struct 
{
    unsigned char ST_Delay;
    unsigned char ST_PositionsPointer0, ST_PositionsPointer1;
    unsigned char ST_OrnamentsPointer0, ST_OrnamentsPointer1;
    unsigned char ST_PatternsPointer0, ST_PatternsPointer1;
    signed char ST_Name[18];
    unsigned char ST_Size0, ST_Size1;
} STC_File;

typedef struct 
{
    unsigned short Address_In_Pattern, SamplePointer, OrnamentPointer, Ton;
    unsigned char Amplitude, Note, Position_In_Sample, Number_Of_Notes_To_Skip;
    signed char Sample_Tik_Counter, Note_Skip_Counter;
    bool Envelope_Enabled;
} STC_Channel_Parameters;

typedef struct 
{
    unsigned char DelayCounter, Transposition, CurrentPosition;
} STC_Parameters;

typedef struct 
{
    STC_Parameters STC;
    STC_Channel_Parameters STC_A, STC_B, STC_C;
} STC_SongInfo;

STC_SongInfo stc;

#define STC_A ((STC_SongInfo *)info->data)->STC_A
#define STC_B ((STC_SongInfo *)info->data)->STC_B
#define STC_C ((STC_SongInfo *)info->data)->STC_C
#define STC ((STC_SongInfo *)info->data)->STC

#define ST_PositionsPointer (header->ST_PositionsPointer0 | (header->ST_PositionsPointer1 << 8))
#define ST_OrnamentsPointer (header->ST_OrnamentsPointer0 | (header->ST_OrnamentsPointer1 << 8))
#define ST_PatternsPointer (header->ST_PatternsPointer0 | (header->ST_PatternsPointer1 << 8))
#define ST_Size (header->ST_Size0 | (header->ST_Size1 << 8))
#define ST_Delay (header->ST_Delay)

void STC_Init(AYSongInfo * info)
{
    unsigned long i;
    unsigned char *module = info->module;
    STC_File *header = (STC_File *)module;
    
    info->data = &stc;
    
    
    memset(&STC_A, 0, sizeof(STC_Channel_Parameters));
    memset(&STC_B, 0, sizeof(STC_Channel_Parameters));
    memset(&STC_C, 0, sizeof(STC_Channel_Parameters));

    STC.CurrentPosition = 0;
    STC.Transposition = module[ST_PositionsPointer + 2];
    STC.DelayCounter = 1;

    i = 0;
    while(module[ST_PatternsPointer + 7 * i] != module[ST_PositionsPointer + 1])
        i++;
    STC_A.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 1]);
    STC_B.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 3]);
    STC_C.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 5]);

    STC_A.Note_Skip_Counter = 0;
    STC_A.Envelope_Enabled = false;
    STC_A.Number_Of_Notes_To_Skip = 0;
    STC_A.Sample_Tik_Counter = -1;
    STC_A.Position_In_Sample = 0;
    STC_A.OrnamentPointer = ST_OrnamentsPointer + 1;
    STC_A.Ton = 0;

    STC_B.Note_Skip_Counter = 0;
    STC_B.Envelope_Enabled = false;
    STC_B.Number_Of_Notes_To_Skip = 0;
    STC_B.Sample_Tik_Counter = -1;
    STC_B.Position_In_Sample = 0;
    STC_B.OrnamentPointer = ST_OrnamentsPointer + 1;
    STC_B.Ton = 0;

    STC_C.Note_Skip_Counter = 0;
    STC_C.Envelope_Enabled = false;
    STC_C.Number_Of_Notes_To_Skip = 0;
    STC_C.Sample_Tik_Counter = -1;
    STC_C.Position_In_Sample = 0;
    STC_C.OrnamentPointer = ST_OrnamentsPointer + 1;
    STC_C.Ton = 0;
}

void STC_GetInfo(AYSongInfo *info)
{
    unsigned long len;
    unsigned long tm = 0;
    signed long j, j1, j2, i;
    unsigned char *st_name;
    unsigned char *module = info->module;
    STC_File *header = (STC_File *)module;
    unsigned char stDelay = module[0];
    unsigned short stPosPt = ay_sys_getword(&module[1]);
    unsigned short stPatPt = ay_sys_getword(&module[5]);
    unsigned char a;

    j = -1;
    do
    {
        j++;
        j2 = stPosPt + j * 2 + 1;
        j2 = module[j2];
        i = -1;
        do
        {
            i++;
            j1 = stPatPt + 7 * i;
        }
        while(module[j1] != j2);
        j1 = ay_sys_getword(&module[j1 + 1]);
        a = 1;
        while(module[j1] != 255)
        {
            unsigned char val = module[j1];
            if((val <= 0x5f) || (val == 0x80) || (val == 0x81))
            {
                tm += a;
            }
            else if(val >= 0xa1 && val <= 0xe0)
            {
                a = val - 0xa0;
            }
            else if(val >= 0x83 && val <= 0x8e)
            {
                j1++;
            }
            j1++;
        }
    }
    while(j != module[stPosPt]);
    tm *= stDelay;
    info->len = tm;

    st_name = (unsigned char *)header->ST_Name;

    //if(!memcmp(st_name, "SONG BY ST COMPILE", 18) || !memcmp(st_name, "SONG BY MB COMPILE", 18) || !memcmp(st_name, "SONG BY ST-COMPILE", 18) || !memcmp(st_name, "SOUND TRACKER v1.1", 18) || !memcmp(st_name, "S.T.FULL EDITION ", 17) || !memcmp(st_name, "SOUND TRACKER v1.3", 18)*/)
      //  return;
		
	for (len=0; len<=32; len++)
		if((st_name[len] < 32) || (st_name[len] > 127))
			 break;
	
    strncpy(info->Name, st_name, len);
}

void STC_PatternInterpreter(AYSongInfo * info, STC_Channel_Parameters * chan)
{
    unsigned short k;
    unsigned char *module = info->module;
    STC_File *header = (STC_File *)module;
    while(true)
    {
        unsigned char val = module[chan->Address_In_Pattern];
        if(val <= 0x5f)
        {
            chan->Note = val;
            chan->Sample_Tik_Counter = 32;
            chan->Position_In_Sample = 0;
            chan->Address_In_Pattern++;
            break;
        }
        else if(val >= 0x60 && val <= 0x6f)
        {
            k = 0;
            while(module[0x1b + 0x63 * k] != (val - 0x60))
                k++;
            chan->SamplePointer = 0x1c + 0x63 * k;
        }
        else if(val >= 0x70 && val <= 0x7f)
        {
            k = 0;
            while(module[ST_OrnamentsPointer + 0x21 * k] != (val - 0x70))
                k++;
            chan->OrnamentPointer = ST_OrnamentsPointer + 0x21 * k + 1;
            chan->Envelope_Enabled = false;
        }
        else if(val == 0x80)
        {
            chan->Sample_Tik_Counter = -1;
            chan->Address_In_Pattern++;
            break;
        }
        else if(val == 0x81)
        {
            chan->Address_In_Pattern++;
            break;
        }
        else if(val == 0x82)
        {
            k = 0;
            while(module[ST_OrnamentsPointer + 0x21 * k] != 0)
                k++;
            chan->OrnamentPointer = ST_OrnamentsPointer + 0x21 * k + 1;
            chan->Envelope_Enabled = false;
        }
        else if(val >= 0x83 && val <= 0x8e)
        {
            ay_writeay(AY_ENV_SHAPE, val - 0x80);
            chan->Address_In_Pattern++;
            ay_writeay(AY_ENV_FINE, module[chan->Address_In_Pattern]);
            chan->Envelope_Enabled = true;
            k = 0;
            while(module[ST_OrnamentsPointer + 0x21 * k] != 0)
                k++;
            chan->OrnamentPointer = ST_OrnamentsPointer + 0x21 * k + 1;
        }
        else
            chan->Number_Of_Notes_To_Skip = val - 0xa1;
        chan->Address_In_Pattern++;
    }
    chan->Note_Skip_Counter = chan->Number_Of_Notes_To_Skip;
}

void STC_GetRegisters(AYSongInfo * info, STC_Channel_Parameters * chan, unsigned char * TempMixer)
{
    unsigned short i;
    unsigned char j;
    unsigned char *module = info->module;
    STC_File *header = (STC_File *)module;
    if(chan->Sample_Tik_Counter >= 0)
    {
        chan->Sample_Tik_Counter--;
        chan->Position_In_Sample = (chan->Position_In_Sample + 1) & 0x1f;
        if(chan->Sample_Tik_Counter == 0)
        {
            if(module[chan->SamplePointer + 0x60] != 0)
            {
                chan->Position_In_Sample = module[chan->SamplePointer + 0x60] & 0x1f;
                chan->Sample_Tik_Counter = module[chan->SamplePointer + 0x61] + 1;
            }
            else
                chan->Sample_Tik_Counter = -1;
        }
    }
    if(chan->Sample_Tik_Counter >= 0)
    {
        i = ((chan->Position_In_Sample - 1) & 0x1f) * 3 + chan->SamplePointer;
        if((module[i + 1] & 0x80) != 0)
            *TempMixer = *TempMixer | 64;
        else
            ay_writeay(AY_NOISE_PERIOD, module[i + 1] & 0x1f);
        if((module[i + 1] & 0x40) != 0)
            *TempMixer = *TempMixer | 8;
        chan->Amplitude = module[i] & 15;
        j = chan->Note + module[chan->OrnamentPointer + ((chan->Position_In_Sample - 1) & 0x1f)] + STC.Transposition;
        if(j > 95)
            j = 95;
        if((module[i + 1] & 0x20) != 0)
            chan->Ton = (ST_Table[j] + module[i + 2] + (((unsigned short)(module[i] & 0xf0)) << 4)) & 0xFFF;
        else
            chan->Ton = (ST_Table[j] - module[i + 2] - (((unsigned short)(module[i] & 0xf0)) << 4)) & 0xFFF;
        if(chan->Envelope_Enabled)
            chan->Amplitude = chan->Amplitude | 16;
    }
    else
        chan->Amplitude = 0;

    *TempMixer = *TempMixer >> 1;
}

void STC_Play(AYSongInfo * info)
{
    unsigned char TempMixer;
    unsigned short i;
    unsigned char *module = info->module;
    STC_File *header = (STC_File *)module;

    STC.DelayCounter--;
    if(STC.DelayCounter == 0)
    {
        STC.DelayCounter = ST_Delay;
        STC_A.Note_Skip_Counter--;
        if(STC_A.Note_Skip_Counter < 0)
        {
            if(module[STC_A.Address_In_Pattern] == 255)
            {
                if(STC.CurrentPosition == module[ST_PositionsPointer])
                    STC.CurrentPosition = 0;
                else
                    STC.CurrentPosition++;
                STC.Transposition = module[ST_PositionsPointer + 2 + STC.CurrentPosition * 2];
                i = 0;
                while(module[ST_PatternsPointer + 7 * i] != module[ST_PositionsPointer + 1 + STC.CurrentPosition * 2])
                    i++;
                STC_A.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 1]);
                STC_B.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 3]);
                STC_C.Address_In_Pattern = ay_sys_getword(&module[ST_PatternsPointer + 7 * i + 5]);
            }
            STC_PatternInterpreter(info, &STC_A);
        }

        STC_B.Note_Skip_Counter--;
        if(STC_B.Note_Skip_Counter < 0)
            STC_PatternInterpreter(info, &STC_B);
        STC_C.Note_Skip_Counter--;
        if(STC_C.Note_Skip_Counter < 0)
            STC_PatternInterpreter(info, &STC_C);
    }

    TempMixer = 0;
    STC_GetRegisters(info, &STC_A, &TempMixer);
    STC_GetRegisters(info, &STC_B, &TempMixer);
    STC_GetRegisters(info, &STC_C, &TempMixer);

    ay_writeay(AY_MIXER, TempMixer);

    ay_writeay(AY_CHNL_A_FINE, STC_A.Ton & 0xff);
    ay_writeay(AY_CHNL_A_COARSE, (STC_A.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_B_FINE, STC_B.Ton & 0xff);
    ay_writeay(AY_CHNL_B_COARSE, (STC_B.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_C_FINE, STC_C.Ton & 0xff);
    ay_writeay(AY_CHNL_C_COARSE, (STC_C.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_A_VOL, STC_A.Amplitude);
    ay_writeay(AY_CHNL_B_VOL, STC_B.Amplitude);
    ay_writeay(AY_CHNL_C_VOL, STC_C.Amplitude);
}


bool STC_Detect(unsigned char *module, unsigned int length, AYSongInfo * s)
{
    STC_File *header = (STC_File *)module;
    
    //INT
    int j, j1, j2;
    
    
    if(length < 6)
        return false;
    if(ST_PositionsPointer> length)
        return false;
    if((int)(ST_PatternsPointer- ST_OrnamentsPointer) <= 0)
    return false;
    if(((ST_PatternsPointer - ST_OrnamentsPointer) % 0x21) != 0)
    return false;
    if((int)(ST_PositionsPointer - ST_OrnamentsPointer) >= 0)
    return false;
    if((module[ST_PositionsPointer] * 2 + 3 + ST_PositionsPointer - ST_OrnamentsPointer) != 0)
    return false;

    j = ST_OrnamentsPointer + 0x21;
    if(j> 65535)
    return false;
    if(j> length)
    return false;
    do
    {
        j--;
        if(module[j] != 0)
        return false;;
    }
    while(j != ST_OrnamentsPointer);

    j = ST_PatternsPointer;
    if(j> length)
    return false;
    j1 = 0;
    j2 = 0;
    while((j + 6 <= length) && (j + 6 < 65536) && (module[j] != 255))
    {
        j++;
        j2 = ay_sys_getword(&module[j]);
        if(j1 < j2)
        j1 = j2;
        j += 2;
        j2 = ay_sys_getword(&module[j]);
        if(j1 < j2)
        j1 = j2;
        j += 2;
        j2 = ay_sys_getword(&module[j]);
        if(j1 < j2)
        j1 = j2;
        j += 2;
    }
    if(module[j] != 255)
    return false;
    if(j1> length)
    return false;
    if(module[j1 - 1] != 255)
    return false;
    do
    {
        if((module[j1] >= 0x83) && (module[j1] <= 0x8e))
        j1++;
        j1++;
    }
    while((j1 <= 65535) && (j1 < length) && (module[j1] != 255));
    if(j1> 65535)
    return false;
    if(j1> length)
    return false;

    strcpy(s->player, "Sound Tracker");

    return true;
}





/////////////////////////////////////////////////////
//////////////////////////////////////////////////////





/* This player module was ported from:
 AY-3-8910/12 Emulator
 Version 3.0 for Windows 95
 Author Sergey Vladimirovich Bulba
 (c)1999-2004 S.V.Bulba
 */

const unsigned short SQT_Table[] =
{ 0xd5d, 0xc9c, 0xbe7, 0xb3c, 0xa9b, 0xa02, 0x973, 0x8eb, 0x86b, 0x7f2, 0x780, 0x714, 0x6ae, 0x64e, 0x5f4, 0x59e, 0x54f, 0x501, 0x4b9, 0x475, 0x435, 0x3f9, 0x3c0, 0x38a, 0x357, 0x327, 0x2fa, 0x2cf, 0x2a7, 0x281, 0x25d, 0x23b, 0x21b, 0x1fc, 0x1e0, 0x1c5, 0x1ac, 0x194, 0x17d, 0x168, 0x153, 0x140, 0x12e, 0x11d, 0x10d, 0xfe, 0xf0, 0xe2, 0xd6, 0xca, 0xbe, 0xb4, 0xaa, 0xa0, 0x97, 0x8f, 0x87, 0x7f, 0x78, 0x71, 0x6b, 0x65, 0x5f, 0x5a, 0x55, 0x50, 0x4c, 0x47, 0x43, 0x40, 0x3c, 0x39, 0x35, 0x32, 0x30, 0x2d, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1b, 0x19, 0x18, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe };

typedef struct 
{
    unsigned char SQT_Size0, SQT_Size1;
    unsigned char SQT_SamplesPointer0, SQT_SamplesPointer1;
    unsigned char SQT_OrnamentsPointer0, SQT_OrnamentsPointer1;
    unsigned char SQT_PatternsPointer0, SQT_PatternsPointer1;
    unsigned char SQT_PositionsPointer0, SQT_PositionsPointer1;
    unsigned char SQT_LoopPointer0, SQT_LoopPointer1;
} SQT_File;

#define SQT_Size0 (unsigned int)(header->SQT_Size0 | (header->SQT_Size0 << 8))
#define SQT_SamplesPointer (unsigned int)(header->SQT_SamplesPointer0 | (header->SQT_SamplesPointer1 << 8))
#define SQT_OrnamentsPointer (unsigned int)(header->SQT_OrnamentsPointer0 | (header->SQT_OrnamentsPointer1 << 8))
#define SQT_PatternsPointer (unsigned int)(header->SQT_PatternsPointer0 | (header->SQT_PatternsPointer1 << 8))
#define SQT_PositionsPointer (unsigned int)(header->SQT_PositionsPointer0 | (header->SQT_PositionsPointer1 << 8))
#define SQT_LoopPointer (unsigned int)(header->SQT_LoopPointer0 | (header->SQT_LoopPointer1 << 8))

#define MAKE_PWORD(x) (unsigned short *)(x)

typedef struct 
{
    unsigned short Address_In_Pattern, SamplePointer, Point_In_Sample, OrnamentPointer, Point_In_Ornament, Ton, ix27;
    unsigned char Volume, Amplitude, Note, ix21;
    short Ton_Slide_Step, Current_Ton_Sliding;
    char Sample_Tik_Counter, Ornament_Tik_Counter, Transposit;
    bool Enabled, Envelope_Enabled, Ornament_Enabled, Gliss, MixNoise, MixTon, b4ix0, b6ix0, b7ix0;
} SQT_Channel_Parameters;

typedef struct 
{
    unsigned char Delay, DelayCounter, Lines_Counter;
    unsigned short Positions_Pointer;
}SQT_Parameters;

typedef struct 
{
    SQT_Parameters SQT;
    SQT_Channel_Parameters SQT_A, SQT_B, SQT_C;
} SQT_SongInfo;

#define SQT_A ((SQT_SongInfo *)info->data)->SQT_A
#define SQT_B ((SQT_SongInfo *)info->data)->SQT_B
#define SQT_C ((SQT_SongInfo *)info->data)->SQT_C
#define SQT ((SQT_SongInfo *)info->data)->SQT

bool SQT_PreInit(char * info)
{
    unsigned char *module = info;
    SQT_File *header = (SQT_File *)module;
    long i, i1, i2;
    unsigned long j2;
    unsigned short *pwrd;
    
    
    i = (unsigned int)SQT_SamplesPointer - 10;
    
    if(i < 0)
    {
      //  s->len = 21;
        return false;
     }
        
    i1 = 0;
    i2 = (unsigned int)SQT_PositionsPointer - i;
    
    if(i2 < 0)
    {
   //   s->len = i=2;
        return false;
    }
    
    while(module[i2] != 0)
    {
        if(i2 > (65536 - 8))
        {
       //   s->len = 23;
            return false;
         }
            
        if(i1 < (module[i2] & 0x7f))
            i1 = module[i2] & 0x7f;
        i2 += 2;
        if(i1 < (module[i2] & 0x7f))
            i1 = module[i2] & 0x7f;
        i2 += 2;
        if(i1 < (module[i2] & 0x7f))
            i1 = module[i2] & 0x7f;
        i2 += 3;
    }
    j2 = (unsigned long)(&module[65535]);
    pwrd = MAKE_PWORD(&header->SQT_SamplesPointer0);
    i1 = (SQT_PatternsPointer - i + i1 * 2) / 2;

    if(i1 < 1)
    {
    //  s->len = 24;
        return false;
     }
      
        
    for(i2 = 1; i2 <= i1; i2++)
    {
    /*
        if((unsigned long)(pwrd) >= j2)
        {
          s->len = 25;
            return false;
        }    
    
        if(*pwrd < i)
        {
          s->len = 26;
            return false;
        }   
      */
            
        *pwrd -= i;
        pwrd++;
    }
    
    
    return true;
}

SQT_SongInfo SQT_SI;

void SQT_Init(AYSongInfo * info)
{
    unsigned char *module = info->module;
    SQT_File *header = (SQT_File *)module;

    if(!SQT_PreInit(info->module))
        return;

   
    info->data = &SQT_SI;
 
    SQT_A.Ton = 0;
    SQT_A.Envelope_Enabled = false;
    SQT_A.Ornament_Enabled = false;
    SQT_A.Gliss = false;
    SQT_A.Enabled = false;

    SQT_B.Ton = 0;
    SQT_B.Envelope_Enabled = false;
    SQT_B.Ornament_Enabled = false;
    SQT_B.Gliss = false;
    SQT_B.Enabled = false;

    SQT_C.Ton = 0;
    SQT_C.Envelope_Enabled = false;
    SQT_C.Ornament_Enabled = false;
    SQT_C.Gliss = false;
    SQT_C.Enabled = false;

    SQT.DelayCounter = 1;
    SQT.Delay = 1;
    SQT.Lines_Counter = 1;
    SQT.Positions_Pointer = SQT_PositionsPointer;

    //ay_resetay(&info, 0);
	
	info->slow = 0;
}

void SQT_Call_LC1D1(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned short * Ptr, unsigned char a)
{
    unsigned char *module = info->module;
    ((*Ptr))++;
    if(chan->b6ix0)
    {
        chan->Address_In_Pattern = (unsigned short)(((*Ptr)) + 1);
        chan->b6ix0 = false;
    }
    switch(a - 1)
    {
        case 0:
            if(chan->b4ix0)
                chan->Volume = module[((*Ptr))] & 15;
            break;
        case 1:
            if(chan->b4ix0)
                chan->Volume = (chan->Volume + module[((*Ptr))]) & 15;
            break;
        case 2:
            if(chan->b4ix0)
            {
                SQT_A.Volume = module[((*Ptr))];
                SQT_B.Volume = module[((*Ptr))];
                SQT_C.Volume = module[((*Ptr))];
            }
            break;
        case 3:
            if(chan->b4ix0)
            {
                SQT_A.Volume = (SQT_A.Volume + module[((*Ptr))]) & 15;
                SQT_B.Volume = (SQT_B.Volume + module[((*Ptr))]) & 15;
                SQT_C.Volume = (SQT_C.Volume + module[((*Ptr))]) & 15;
            }
            break;
        case 4:
            if(chan->b4ix0)
            {
                SQT.DelayCounter = module[((*Ptr))] & 31;
                if(SQT.DelayCounter == 0)
                    SQT.DelayCounter = 32;
                SQT.Delay = SQT.DelayCounter;
            }
            break;
        case 5:
            if(chan->b4ix0)
            {
                SQT.DelayCounter = (SQT.DelayCounter + module[((*Ptr))]) & 31;
                if(SQT.DelayCounter == 0)
                    SQT.DelayCounter = 32;
                SQT.Delay = SQT.DelayCounter;
            }
            break;
        case 6:
            chan->Current_Ton_Sliding = 0;
            chan->Gliss = true;
            chan->Ton_Slide_Step = -module[((*Ptr))];
            break;
        case 7:
            chan->Current_Ton_Sliding = 0;
            chan->Gliss = true;
            chan->Ton_Slide_Step = module[((*Ptr))];
            break;
        default:
            chan->Envelope_Enabled = true;
            ay_writeay(AY_ENV_SHAPE, (a - 1) & 15);
            ay_writeay(AY_ENV_FINE, module[((*Ptr))]);
            break;
    }
}

void SQT_Call_LC2A8(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned char a)
{
    unsigned char *module = info->module;
    SQT_File *header = (SQT_File *)module;
    chan->Envelope_Enabled = false;
    chan->Ornament_Enabled = false;
    chan->Gliss = false;
    chan->Enabled = true;
    chan->SamplePointer = ay_sys_getword(&module[a * 2 + SQT_SamplesPointer]);
    chan->Point_In_Sample = chan->SamplePointer + 2;
    chan->Sample_Tik_Counter = 32;
    chan->MixNoise = true;
    chan->MixTon = true;
}

void SQT_Call_LC2D9(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned char a)
{
    unsigned char *module = info->module;
    SQT_File *header = (SQT_File *)module;
    chan->OrnamentPointer = ay_sys_getword(&module[a * 2 + SQT_OrnamentsPointer]);
    chan->Point_In_Ornament = chan->OrnamentPointer + 2;
    chan->Ornament_Tik_Counter = 32;
    chan->Ornament_Enabled = true;
}

void SQT_Call_LC283(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned short * Ptr)
{
    unsigned char *module = info->module;
    unsigned char val = module[(*Ptr)];
    if(val <= 0x7f)
    {
        SQT_Call_LC1D1(info, chan, Ptr, val);
    }
    else if(val >= 0x80)
    {
        if(((val >> 1) & 31) != 0)
            SQT_Call_LC2A8(info, chan, (val >> 1) & 31);
        if((val & 64) != 0)
        {
            int Temp = module[(*Ptr) + 1] >> 4;
            if((val & 1) != 0)
                Temp = Temp | 16;
            if(Temp != 0)
                SQT_Call_LC2D9(info, chan, Temp);
            (*Ptr)++;
            if((module[(*Ptr)] & 15) != 0)
                SQT_Call_LC1D1(info, chan, Ptr, module[(*Ptr)] & 15);
        }
    }
    (*Ptr)++;
}

void SQT_Call_LC191(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned short * Ptr)
{
    unsigned char *module = info->module;
    (*Ptr) = chan->ix27;
    chan->b6ix0 = false;
    if(module[(*Ptr)] <= 0x7f)
    {
        (*Ptr)++;
        SQT_Call_LC283(info, chan, Ptr);
    }
    else if(module[(*Ptr)] >= 0x80)
    {
        SQT_Call_LC2A8(info, chan, module[(*Ptr)] & 31);
    }

}

void SQT_PatternInterpreter(AYSongInfo * info, SQT_Channel_Parameters * chan)
{
    unsigned char *module = info->module;
    unsigned short Ptr = 0;
    unsigned char val;
    
    if(chan->ix21 != 0)
    {
        chan->ix21--;
        if(chan->b7ix0)
            SQT_Call_LC191(info, chan, &Ptr);
        return;
    }
    Ptr = chan->Address_In_Pattern;
    chan->b6ix0 = true;
    chan->b7ix0 = false;
    while(true)
    {
        val = module[Ptr];
        if(val <= 0x5f)
        {
            chan->Note = module[Ptr];
            chan->ix27 = Ptr;
            Ptr++;
            SQT_Call_LC283(info, chan, &Ptr);
            if(chan->b6ix0)
                chan->Address_In_Pattern = Ptr;
            break;
        }
        else if(val >= 0x60 && val <= 0x6e)
        {
            SQT_Call_LC1D1(info, chan, &Ptr, module[Ptr] - 0x60);
            break;
        }
        else if(val >= 0x6f && val <= 0x7f)
        {
            chan->MixNoise = false;
            chan->MixTon = false;
            chan->Enabled = false;
            if(val != 0x6f)
                SQT_Call_LC1D1(info, chan, &Ptr, module[Ptr] - 0x6f);
            else
                chan->Address_In_Pattern = Ptr + 1;
            break;
        }
        else if(val >= 0x80 && val <= 0xbf)
        {
            chan->Address_In_Pattern = Ptr + 1;
            if(val <= 0x9f)
            {
                if((val & 16) == 0)
                    chan->Note += val & 15;
                else
                    chan->Note -= val & 15;
            }
            else
            {
                chan->ix21 = val & 15;
                if((val & 16) == 0)
                    break;
                if(chan->ix21 != 0)
                    chan->b7ix0 = true;
            }
            SQT_Call_LC191(info, chan, &Ptr);
            break;
        }
        else if(val >= 0xc0)
        {
            chan->Address_In_Pattern = Ptr + 1;
            chan->ix27 = Ptr;
            SQT_Call_LC2A8(info, chan, val & 31);
            break;
        }
    }
}

void SQT_GetRegisters(AYSongInfo * info, SQT_Channel_Parameters * chan, unsigned char * TempMixer)
{
    unsigned char noise;
    unsigned char *module = info->module;
    unsigned char j, b0, b1;
    (*TempMixer) = (*TempMixer) << 1;
    if(chan->Enabled)
    {
        b0 = module[chan->Point_In_Sample];
        chan->Amplitude = b0 & 15;
        if(chan->Amplitude != 0)
        {
            chan->Amplitude -= chan->Volume;
            if((signed char)(chan->Amplitude) < 0)
                chan->Amplitude = 0;
        }
        else if(chan->Envelope_Enabled)
            chan->Amplitude = 16;
        b1 = module[chan->Point_In_Sample + 1];
        if((b1 & 32) != 0)
        {
            (*TempMixer) |= 8;
            noise = (b0 & 0xf0) >> 3;
            if((signed char)(b1) < 0)
                noise++;
            ay_writeay(AY_NOISE_PERIOD, noise);
        }
        if((b1 & 64) != 0)
        {
            (*TempMixer) |= 1;
        }
        j = chan->Note;
        if(chan->Ornament_Enabled)
        {
            j += module[chan->Point_In_Ornament];
            chan->Ornament_Tik_Counter--;
            if(chan->Ornament_Tik_Counter == 0)
            {
                if(module[chan->OrnamentPointer] != 32)
                {
                    chan->Ornament_Tik_Counter = module[chan->OrnamentPointer + 1];
                    chan->Point_In_Ornament = chan->OrnamentPointer + 2 + module[chan->OrnamentPointer];
                }
                else
                {
                    chan->Ornament_Tik_Counter = module[chan->SamplePointer + 1];
                    chan->Point_In_Ornament = chan->OrnamentPointer + 2 + module[chan->SamplePointer];
                }
            }
            else
                chan->Point_In_Ornament++;
        }
        j += chan->Transposit;
        if(j > 0x5f)
            j = 0x5f;
        if((b1 & 16) == 0)
            chan->Ton = SQT_Table[j] - (((unsigned short)(b1 & 15) << 8) + module[chan->Point_In_Sample + 2]);
        else
            chan->Ton = SQT_Table[j] + (((unsigned short)(b1 & 15) << 8) + module[chan->Point_In_Sample + 2]);
        chan->Sample_Tik_Counter--;
        if(chan->Sample_Tik_Counter == 0)
        {
            chan->Sample_Tik_Counter = module[chan->SamplePointer + 1];
            if(module[chan->SamplePointer] == 32)
            {
                chan->Enabled = false;
                chan->Ornament_Enabled = false;
            }
            chan->Point_In_Sample = chan->SamplePointer + 2 + module[chan->SamplePointer] * 3;
        }
        else
            chan->Point_In_Sample += 3;
        if(chan->Gliss)
        {
            chan->Ton += chan->Current_Ton_Sliding;
            chan->Current_Ton_Sliding += chan->Ton_Slide_Step;
        }
        chan->Ton = chan->Ton & 0xfff;
    }
    else
        chan->Amplitude = 0;
}

void SQT_Play(AYSongInfo * info)
{
    unsigned char *module = info->module;
    SQT_File *header = (SQT_File *)module;
    unsigned char TempMixer;

    
    // return;

    if(--SQT.DelayCounter == 0)
    {
        SQT.DelayCounter = SQT.Delay;
        if(--SQT.Lines_Counter == 0)
        {
            if(module[SQT.Positions_Pointer] == 0)
                SQT.Positions_Pointer = SQT_LoopPointer;
            if((signed char)(module[SQT.Positions_Pointer]) < 0)
                SQT_C.b4ix0 = true;
            else
                SQT_C.b4ix0 = false;
            SQT_C.Address_In_Pattern = ay_sys_getword(&module[(unsigned char)(module[SQT.Positions_Pointer] * 2) + SQT_PatternsPointer]);
            SQT.Lines_Counter = module[SQT_C.Address_In_Pattern];
            SQT_C.Address_In_Pattern++;
            SQT.Positions_Pointer++;
            SQT_C.Volume = module[SQT.Positions_Pointer] & 15;
            if((module[SQT.Positions_Pointer] >> 4) < 9)
                SQT_C.Transposit = module[SQT.Positions_Pointer] >> 4;
            else
                SQT_C.Transposit = -((module[SQT.Positions_Pointer] >> 4) - 9) - 1;
            SQT.Positions_Pointer++;
            SQT_C.ix21 = 0;

            if(module[SQT.Positions_Pointer] == 0)
                SQT.Positions_Pointer = SQT_LoopPointer;
            if((signed char)(module[SQT.Positions_Pointer]) < 0)
                SQT_B.b4ix0 = true;
            else
                SQT_B.b4ix0 = false;
            SQT_B.Address_In_Pattern = ay_sys_getword(&module[(unsigned char)(module[SQT.Positions_Pointer] * 2) + SQT_PatternsPointer]) + 1;
            SQT.Positions_Pointer++;
            SQT_B.Volume = module[SQT.Positions_Pointer] & 15;
            if((module[SQT.Positions_Pointer] >> 4) < 9)
                SQT_B.Transposit = module[SQT.Positions_Pointer] >> 4;
            else
                SQT_B.Transposit = -((module[SQT.Positions_Pointer] >> 4) - 9) - 1;
            SQT.Positions_Pointer++;
            SQT_B.ix21 = 0;

            if(module[SQT.Positions_Pointer] == 0)
                SQT.Positions_Pointer = SQT_LoopPointer;
            if((signed char)(module[SQT.Positions_Pointer]) < 0)
                SQT_A.b4ix0 = true;
            else
                SQT_A.b4ix0 = false;
            SQT_A.Address_In_Pattern = ay_sys_getword(&module[(unsigned char)(module[SQT.Positions_Pointer] * 2) + SQT_PatternsPointer]) + 1;
            SQT.Positions_Pointer++;
            SQT_A.Volume = module[SQT.Positions_Pointer] & 15;
            if((module[SQT.Positions_Pointer] >> 4) < 9)
                SQT_A.Transposit = module[SQT.Positions_Pointer] >> 4;
            else
                SQT_A.Transposit = -((module[SQT.Positions_Pointer] >> 4) - 9) - 1;
            SQT.Positions_Pointer++;
            SQT_A.ix21 = 0;

            SQT.Delay = module[SQT.Positions_Pointer];
            SQT.DelayCounter = SQT.Delay;
            SQT.Positions_Pointer++;
        }
        SQT_PatternInterpreter(info, &SQT_C);
        SQT_PatternInterpreter(info, &SQT_B);
        SQT_PatternInterpreter(info, &SQT_A);
    }

    TempMixer = 0;
    SQT_GetRegisters(info, &SQT_C, &TempMixer);
    SQT_GetRegisters(info, &SQT_B, &TempMixer);
    SQT_GetRegisters(info, &SQT_A, &TempMixer);
    TempMixer = (-(TempMixer + 1)) & 0x3f;

    if(!SQT_A.MixNoise)
        TempMixer |= 8;
    if(!SQT_A.MixTon)
        TempMixer |= 1;

    if(!SQT_B.MixNoise)
        TempMixer |= 16;
    if(!SQT_B.MixTon)
        TempMixer |= 2;

    if(!SQT_C.MixNoise)
        TempMixer |= 32;
    if(!SQT_C.MixTon)
        TempMixer |= 4;

    ay_writeay(AY_MIXER, TempMixer);
    ay_writeay(AY_CHNL_A_FINE, SQT_A.Ton & 0xff);
    ay_writeay(AY_CHNL_A_COARSE, (SQT_A.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_B_FINE, SQT_B.Ton & 0xff);
    ay_writeay(AY_CHNL_B_COARSE, (SQT_B.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_C_FINE, SQT_C.Ton & 0xff);
    ay_writeay(AY_CHNL_C_COARSE, (SQT_C.Ton >> 8) & 0xf);
    ay_writeay(AY_CHNL_A_VOL, SQT_A.Amplitude);
    ay_writeay(AY_CHNL_B_VOL, SQT_B.Amplitude);
    ay_writeay(AY_CHNL_C_VOL, SQT_C.Amplitude);
}




void SQT_GetChannelInfo(AYSongInfo * info, unsigned char * new_b,  char * new_a1, unsigned short * new_j1, unsigned short * new_cptr, bool * new_f71, bool * new_f61, bool * new_f41, unsigned short * new_j22, unsigned char chnl_num)
{
    unsigned char *module = info->module;
    unsigned char va1, va2, va3, va4;
   
    char a = 0;
    
   
    //gotoxy (5, 5);
   
    if(*new_a1 != 0)
    {
        (*new_a1) --;
        
        //printf ("01");
        
        if(*new_f71)
        {
            *new_cptr = *new_j22;
            *new_f61 = false;
            if(module[*new_cptr] <= 0x7f)
            {
                (*new_cptr) ++;
		va1 = module[*new_cptr];
                if(va1 <= 0x7f)
                {
                    (*new_cptr) ++;
                    if(*new_f61)
                        *new_j1 = *new_cptr + 1;
                    switch(module[*new_cptr - 1] - 1)
                    {
                        case 4:
                            if(*new_f41)
                            {
                                *new_b = module[*new_cptr] & 31;
                                if(*new_b == 0)
				    *new_b = 32;
                            }
                            break;
                        case 5:
                            if(*new_f41)
                            {
				*new_b = (*new_b + module[*new_cptr]) & 31;
                                if(*new_b == 0)
                                    *new_b = 32;
                            }
                            break;
                        default:
                            break;
		    }
                }
                else if(va1 >= 0x80)
                {
                    if((va1 & 64) != 0)
                    {
                        (*new_cptr)++;
                        if((module[*new_cptr] & 15) != 0)
                        {
                            (*new_cptr)++;
                            if(*new_f61)
                                *new_j1 = *new_cptr + 1;
			    switch((module[*new_cptr - 1] & 15) - 1)
			    {
                                case 4:
                                    if(*new_f41)
                                    {
                                        *new_b = module[*new_cptr] & 31;
                                        if(*new_b == 0)
                                            *new_b = 32;
                                    }
                                    break;
                                case 5:
                                    if(*new_f41)
                                    {
                                        *new_b = (*new_b + module[*new_cptr]) & 31;
					if(*new_b == 0)
                                            *new_b = 32;
                                    }
                                    break;
                                default:
				    break;
                            }
                        }
                    }
                }
            }
        }
    }
    else
    {
     //printf ("02");
    
        *new_cptr = *new_j1;
        *new_f61 = true;
        *new_f71 = false;
        while(true)
        {
            va2 = module[*new_cptr];
            
           // gotoxy (20, 5);
            //printf ("%05d %02x %d  ", *new_cptr, va2, a++);
            
            if(va2 <= 0x5f)
            {
                *new_j22 = *new_cptr;
		(*new_cptr) ++;
				
		
                va3 = module[*new_cptr];
		if(va3 <= 0x7f)
                {
                    (*new_cptr) ++;
                    if(*new_f61)
                    {
                        *new_j1 = *new_cptr + 1;
                        *new_f61 = false;
                    }
                    switch(module[*new_cptr - 1] - 1)
                    {
                        case 4:
                            if(*new_f41)
                            {
				*new_b = module[*new_cptr] & 31;
                                if(*new_b == 0)
                                    *new_b = 32;
                            }
			    break;
                        case 5:
                            if(*new_f41)
                            {
                                *new_b = (*new_b + module[*new_cptr]) & 31;
                                if(*new_b == 0)
                                    *new_b = 32;
                            }
                            break;
			default:
                            break;
                    }
                }
                else if(va3 >= 0x80)
                {
                    // printf ("03");
                
                    if((module[*new_cptr] & 64) != 0)
                    {
                        (*new_cptr) ++;
                        if((module[*new_cptr] & 15) != 0)
			{
                            (*new_cptr) ++;
                            if(*new_f61)
			    {
                                *new_j1 = *new_cptr + 1;
                                *new_f61 = false;
                            }
                            switch((module[*new_cptr - 1] & 15) - 1)
                            {
                                case 4:
                                    if(*new_f41)
                                    {
                                        *new_b = module[*new_cptr] & 31;
                                        if(*new_b == 0)
                                            *new_b = 32;
                                    }
				    break;
                                case 5:
                                    if(*new_f41)
				    {
                                        *new_b = (*new_b + module[*new_cptr]) & 31;
                                        if(*new_b == 0)
                                            *new_b = 32;
                                    }
                                    break;
                                default:
                                    break;
                            }

			}
                    }
                }
                (*new_cptr) ++;
                if(*new_f61)
                    *new_j1 = *new_cptr;
                break;
            }
            else if(va2 >= 0x60 && va2 <= 0x6e)
	    {
	       // printf ("04");
	    
                (*new_cptr) ++;
                if(*new_f61)
                    *new_j1 = *new_cptr + 1;
		switch(module[*new_cptr - 1] - 0x60 - 1)
                {
                    case 4:
                        if(*new_f41)
                        {
                            *new_b = module[*new_cptr] & 31;
                            if(*new_b == 0)
                                *new_b = 32;
                        }
                        break;
                    case 5:
                        if(*new_f41)
                        {
			    *new_b = (*new_b + module[*new_cptr]) & 31;
                            if(*new_b == 0)
				*new_b = 32;
                        }
                        break;
                    default:
                        break;
                }
                break;
            }
            else if(va2 >= 0x6f && va2 <= 0x7f)
            {
                // printf ("05");
            
                if(module[*new_cptr] != 0x6f)
		{
                    (*new_cptr) ++;
                    if(*new_f61)
                        *new_j1 = *new_cptr + 1;
                    switch(module[*new_cptr - 1] - 0x6f - 1)
                    {
                        case 4:
                            if(*new_f41)
			    {
                                *new_b = module[*new_cptr] & 31;
                                if(*new_b == 0)
                                    *new_b = 32;
                            }
			    break;
                        case 5:
                            if(*new_f41)
                            {
                                *new_b = (*new_b + module[*new_cptr]) & 31;
                                if(*new_b == 0)
                                    *new_b = 32;
                            }
                            break;
                        default:
                            break;
                    }
                }
		else
		    *new_j1 = *new_cptr + 1;
                break;
            }
            else if(va2 >= 0x80 && va2 <= 0xbf)
            {
                 //printf ("06");
            
                *new_j1 = *new_cptr + 1;
                if(chnl_num == 1)
                {
                    if(va2 >= 0xa0)
                    {
                        *new_a1 = module[*new_cptr] & 15;
                        if((module[*new_cptr] & 16) == 0)
			    break;
                        if(*new_a1 != 0)
                            *new_f71 = true;
                    }
                }
                else if(chnl_num == 2 || chnl_num == 3)
                {
                   // printf ("07");
                
		    if(va2 > 0x9f)
                    {
                        *new_a1 = module[*new_cptr] & 15;
                        if((module[*new_cptr] & 16) == 0)
                            break;
                        if(*new_a1 != 0)
			    *new_f71 = true;
                    }
                }
                *new_cptr = *new_j22;
                *new_f61 = false;
                if(module[*new_cptr] <= 0x7f)
                {
                    (*new_cptr) ++;
                    va4 = module[*new_cptr];
                    if(va4 <= 0x7f)
                    {
                        (*new_cptr) ++;
                        if(*new_f61)
			    *new_j1 = *new_cptr + 1;
                        switch(module[*new_cptr - 1] - 1)
                        {
                            case 4:
                                if(*new_f41)
                                {
                                    *new_b = module[*new_cptr] & 31;
                                    if(*new_b == 0)
                                        *new_b = 32;
                                }
                                break;
                            case 5:
                                if(*new_f41)
				{
                                    *new_b = (*new_b + module[*new_cptr]) & 31;
                                    if(*new_b == 0)
                                        *new_b = 32;
                                }
                                break;
			    default:
                                break;
                        }
                    }
                    else if(va4 >= 0x80)
                    {
                        // printf ("08");
                    
                        if((module[*new_cptr] & 64) != 0)
			{
                            (*new_cptr) ++;
                            if((module[*new_cptr] & 15) != 0)
                            {
                                (*new_cptr) ++;
                                if(*new_f61)
                                    *new_j1 = *new_cptr + 1;
                                switch((module[*new_cptr - 1] & 15) - 1)
                                {
                                    case 4:
                                        if(*new_f41)
                                        {
					    *new_b = module[*new_cptr] & 31;
					    if(*new_b == 0)
                                                *new_b = 32;
                                        }
                                        break;
                                    case 5:
                                        if(*new_f41)
                                        {
                                            *new_b = (*new_b + module[*new_cptr]) & 31;
                                            if(*new_b == 0)
                                                *new_b = 32;
                                        }
                                        break;
                                    default:
					break;
                                }

                            }
                        }
		    }

                }
                break;
            }
            else if(va2 >= 0xc0)
            {
                 //printf ("09");
            
                *new_j1 = *new_cptr + 1;
		*new_j22 = *new_cptr;
                break;
            }
        }
    }
}





void SQT_GetInfo(AYSongInfo * info)
{
  
    unsigned char *module = info->module;
    
    SQT_File *header = (SQT_File *)module;
    unsigned char b;
    unsigned long tm = 0;
    long i;
    char a1, a2, a3;
    unsigned short j1, j2, j3;
    unsigned short pptr, cptr;
    bool f71, f72, f73, f61, f62, f63, f41, f42, f43, flg;
    unsigned short j11, j22, j33;
    unsigned char limit;
    
    
    f71 = f72 = f73 = f61 = f62 = f63 = f41 = f42 = f43 = flg = false;
    j11 = j22 = j33 = 0;
    
    if(!SQT_PreInit(info->module))
    {
        info->len = 0;
        return;
    }

    pptr = SQT_PositionsPointer;
    while(module[pptr] != 0)
    {
        //if(pptr == SQT_LoopPointer)
        //    info->Loop = tm;
            
        f41 = (module[pptr] & 128) ? true : false;
        j1 = ay_sys_getword(&module[(unsigned char)(module[pptr] * 2) + SQT_PatternsPointer]);
        j1++;
        pptr += 2;
        f42 = (module[pptr] & 128) ? true : false;
        j2 = ay_sys_getword(&module[(unsigned char)(module[pptr] * 2) + SQT_PatternsPointer]);
        j2++;
        pptr += 2;
        f43 = (module[pptr] & 128) ? true : false;
        j3 = ay_sys_getword(&module[(unsigned char)(module[pptr] * 2) + SQT_PatternsPointer]);
        j3++;
        pptr += 2;
        b = module[pptr];
        pptr++;
        a1 = a2 = a3 = 0;
        limit = module[j1 - 1];
        for(i = 0; i < limit; i++)
        {
            //gotoxy(5, 5);
           // printf ("2                       ");
            SQT_GetChannelInfo(info, &b, &a1, &j1, &cptr, &f71, &f61, &f41, &j11, 1);
	    
	    //gotoxy(5, 5);
	    //printf ("3                       ");	    
	    SQT_GetChannelInfo(info, &b, &a2, &j2, &cptr, &f72, &f62, &f42, &j22, 2);
	    
	    //gotoxy(5, 5);
	    //printf ("4                       ");
	    SQT_GetChannelInfo(info, &b, &a3, &j3, &cptr, &f73, &f63, &f43, &j33, 3);
            
            
          
            tm += b;
            
            //gotoxy(0, 5);
            //printf("%d                              ", tm);
        }
    }
    
    info->len = tm;
    
    FN(info); 
}


bool SQT_Detect(unsigned char *module, unsigned int length, AYSongInfo * s)
{
    int j, j1, j2, j3;
    SQT_File *header = (SQT_File *)module;
    unsigned short *pwrd;
    long F_Length;
    
    int PD_rv;
    
    
    //return false;
    
    if(length < 17)
    {
     // s->len = 1;
        return false;
        }
        
    if((unsigned int)SQT_SamplesPointer < 10)
    {
    //s->len = 2;
        return false;
    }
    
    if(SQT_OrnamentsPointer <= SQT_SamplesPointer)
   {
 //  s->len = 3;
        return false;
    }
    
    if(SQT_PatternsPointer < SQT_OrnamentsPointer)
 {
// s->len = 4;
        return false;
  }
    
    if(SQT_PositionsPointer <= SQT_PatternsPointer)
    {
   // s->len = 5;
        return false;
    }
    
    if(SQT_LoopPointer < SQT_PositionsPointer)
     {
    // s->len = 6;
        return false;
}

    j = SQT_SamplesPointer - 10;
    if(SQT_LoopPointer - j >= length)
 {
 //s->len = 7;
        return false;
}

    j1 = SQT_PositionsPointer - j;
    if(module[j1] == 0)
 {
// s->len = 8;
        return false;
 }
 
    j2 = 0;
    while(module[j1] != 0)
    {
        if(j1 + 7 >= length)
        {
        //s->len = 9;
            return false;
         }   
  
        if(j2 < (module[j1] & 0x7f))
            j2 = module[j1] & 0x7f;
        j1 += 2;
        if(j2 < (module[j1] & 0x7f))
            j2 = module[j1] & 0x7f;
        j1 += 2;
        if(j2 < (module[j1] & 0x7f))
            j2 = module[j1] & 0x7f;
        j1 += 3;
    }

    pwrd = (unsigned short *)&module[SQT_SamplesPointer - j + 2];
    if(*pwrd - SQT_PatternsPointer - 2 != j2 * 2)
    {
   // s->len = 10;
        return false;
        }

    F_Length = j1 + 7;
    pwrd = (unsigned short *)&module[12];
    j2 = *pwrd;
    for(j1 = 1; j1 <= (SQT_OrnamentsPointer- SQT_SamplesPointer) / 2; j1++)
    {
        pwrd++;
        j3 = *pwrd;
        if( j3 - j2 != 0x62 )
        {
        //s->len = 11;
        return false;
        }
        
        j2 = j3;
    }

    for(j1 = 1; j1 <= (SQT_PatternsPointer - SQT_OrnamentsPointer) / 2; j1++)
    {
        pwrd++;
        j3 = *pwrd;
        if( j3 - j2 != 0x22) 
        {
        //s->len = 12;
        return false;
        }
        j2 = j3;
    }

    PD_rv = SQT_PreInit(module);
    
    if (!PD_rv)
      return 0;

    strcpy (s->player, "SQ Tracker");

    return  1;
}









//////



bool PT3_Detect(unsigned char *module, unsigned int length,AYSongInfo * s)
{
    long F_Length;
    int j, j1, j2;
    PT3_File *header = (PT3_File *)module;
    
    
   // return true;
    
    if(length < 202)
    {
       // s->err = 1;
        return false;
    }
    
    if(PT3_PatternsPointer> length)
    {
       //s->err = 2;
       return false;
    }
    
    
    if(module[PT3_PatternsPointer - 1] != 255)
    {
       // s->err = 3;
        return false;
    }
        
        
    if(PT3_OrnamentsPointers(0) + 2 > length)
    {
       // s->err = 4;
        return false;
     }

   // return true;

    j = 0;
    memcpy(&j, &module[PT3_OrnamentsPointers(0)], 3);
    if(j != 256)
    {
       // s->err = 5;
        return false;
    }

    j = ay_sys_getword(&module[PT3_PatternsPointer]);
    if(j > length)
    {
        //s->err = 5;
        return false;
    }
    
    if(j - (int)(PT3_PatternsPointer) <= 0)
    {
       // s->err = 6;
        return false;
    }
    
    /*if(((j - (int)(PT3_PatternsPointer)) % 6) != 0)
     return false;*/

    j1 = 0;
    j2 = 0;
    while((j2 < 256) && (j2 <= length - 201) && (header->PT3_PositionList[j2] != 255))
    {
        if((unsigned long)(j1) < header->PT3_PositionList[j2])
            j1 = header->PT3_PositionList[j2];
        if((j1 % 3) != 0)
        {
            //s->err = 7;
            return false;
        }    
        j2++;
    }
    
    //if(((j - (int)(PT3_PatternsPointer)) / 6) != ((j1 / 3) + 1))
    //{
    //    s->err = 8;
    //    return false;
    //}

    j = 15;
    while((j > 0) && (PT3_OrnamentsPointers(j) == 0))
        j--;

    F_Length = PT3_OrnamentsPointers(j) + module[PT3_OrnamentsPointers(j) + 1] + 2;
    
    if(F_Length > length + 1)
    {
        //s->err = 9;
        return false;
    }

    //header->PT3_NumberOfPositions = j2;
    
    strcpy(s->player, "Pro Tracker v3");
    
    return true;
}










////// LIB  //////




void ClearScreen(void)
{	
    bzero((void *)D_49152, 6144);	
    
   
    attr_old(0, 32, WHITE);    
    attr_old(32, 32*4, BLUE*8+WHITE);
    attr_old(32*5, 32*3, GREEN+64);
    attr_old(32*8, 32*16, BLACK*8+WHITE+64);     
    
   
    printf("Shuffle Player %s\n\n\n\n\n\n\n\nControls:\n'A','B','C','D' = Disk select\n<SS>+A+B = Select disk A+B\n'Space' = next tune, 'P' = Pause\n'Enter',Cursor keys = navigation\n'Backspace' = previous tune", VERSION); 
    
     
   // attr_old(32*9, 9, MAGENTA);    
}




void Status(char * s, int code1, int code2, int good)
{ 
	if (good)
		attr_old(4*32, 32, BLUE*8+WHITE);
	else
		attr_old(4*32, 32, RED*8+YELLOW+64+128); 
      
    clearstring(4);

	gotoxy(0, 4);
	printf (s, code1, code2);
}



void ClearList(void)
{        
        clearstring(7);
        attr_old(32*7, 32, CYAN+64);
        bzero1 (); 
		attr_too_old();   
}

void ay_sys_writeword(unsigned char *p, unsigned int val)
{
    *p = (unsigned char)(val & 0xff);
    *(p + 1) = (unsigned char)((val >> 8) & 0xff);
}



void tiho (void)
{
	output(0xFFFD, 8); output(0xBFFD, 0);  
	output(0xFFFD, 9); output(0xBFFD, 0);  
	output(0xFFFD, 10); output(0xBFFD, 0);   	    
}



void DiskErrMesage(char m, int m1)
{
	
    switch (m)
    {
    case 1:
        Status("No disk !", 0,0,0);
        break;
  
     case 4:
          Status( "Sector src error !", 0, 0, 0);
        break;
       
     case 5:
            Status("Disk reading error (Err=%d)!", m1, 0, 0);
          break;
			
     case 6:
		    Status("Unknown file format (Err=%d)!", m1, 0, 0);
			break;
			
		default:
			Status("Unknown disk Err=%d!", m, 0, 0);
   }	
     
 
}


void delay (unsigned int arg)
{
	unsigned short i;

	for (i=0; i<arg; i++)
		;

}

void clock (void)
{
	static unsigned char h=0, m=0, ssss=0;


	ssss++;

	if (ssss > 59)
	{
		ssss = 0;
		m++;

		if (m>59)
		{
			m=0;
			h++;
		}
	}

	printstring1(24, d2s(h));
	printstring1(27, d2s(m));
	printstring1(30, d2s(ssss));	 
}
