# include "all.h"



AYSongInfo * ss = 0;

const unsigned short ASM_Table[] =
{ 0xedc, 0xe07, 0xd3e, 0xc80, 0xbcc, 0xb22, 0xa82, 0x9ec, 0x95c, 0x8d6, 0x858, 0x7e0, 0x76e, 0x704, 0x69f, 0x640, 0x5e6, 0x591, 0x541, 0x4f6, 0x4ae, 0x46b, 0x42c, 0x3f0, 0x3b7,
0x382, 0x34f, 0x320, 0x2f3, 0x2c8, 0x2a1, 0x27b, 0x257, 0x236, 0x216, 0x1f8, 0x1dc, 0x1c1, 0x1a8, 0x190, 0x179, 0x164, 0x150, 0x13d, 0x12c, 0x11b, 0x10b, 0xfc, 0xee, 0xe0, 
0xd4, 0xc8, 0xbd, 0xb2, 0xa8, 0x9f, 0x96, 0x8d, 0x85, 0x7e, 0x77, 0x70, 0x6a, 0x64, 0x5e, 0x59, 0x54, 0x50, 0x4b, 0x47, 0x43, 0x3f, 0x3c, 0x38, 0x35, 0x32, 0x2f, 0x2d, 0x2a, 
0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c };

typedef struct 
{
	signed char PSC_MusicName[69];
	unsigned char PSC_UnknownPointer0, PSC_UnknownPointer1;
	unsigned char PSC_PatternsPointer0, PSC_PatternsPointer1;
	unsigned char PSC_Delay;
	unsigned char PSC_OrnamentsPointer0, PSC_OrnamentsPointer1;
	unsigned char PSC_SamplesPointers0[64];
} PSC_File;

#define PSC_UnknownPointer (header->PSC_UnknownPointer0 | (header->PSC_UnknownPointer1 << 8))
#define PSC_PatternsPointer (header->PSC_PatternsPointer0 | (header->PSC_PatternsPointer1 << 8))
#define PSC_OrnamentsPointer (header->PSC_OrnamentsPointer0 | (header->PSC_OrnamentsPointer1 << 8))
#define PSC_SamplesPointers(x) (header->PSC_SamplesPointers0 [(x) * 2] | ((header->PSC_SamplesPointers0 [((x) * 2) + 1]) << 8))

typedef struct 
{
	unsigned char num;
	unsigned int Address_In_Pattern, OrnamentPointer, SamplePointer, Ton;
	int Current_Ton_Sliding, Ton_Accumulator, Addition_To_Ton;
	signed char Initial_Volume, Note_Skip_Counter;
	unsigned char Note, Volume, Amplitude, Volume_Counter, Volume_Counter1, Volume_Counter_Init, Noise_Accumulator, Position_In_Sample, Loop_Sample_Position, Position_In_Ornament, Loop_Ornament_Position;
	bool Enabled, Ornament_Enabled, Envelope_Enabled, Gliss, Ton_Slide_Enabled, Break_Sample_Loop, Break_Ornament_Loop, Volume_Inc;
} PSC_Channel_Parameters;

typedef struct 
{
	unsigned char Delay, DelayCounter, Lines_Counter, Noise_Base;
	unsigned int Positions_Pointer;
} PSC_Parameters;

typedef struct 
{
	PSC_Parameters PSC;
	PSC_Channel_Parameters PSC_A, PSC_B, PSC_C;
} PSC_SongInfo;


PSC_SongInfo ppp;

#define PSC_A ((PSC_SongInfo *)info->data)->PSC_A
#define PSC_B ((PSC_SongInfo *)info->data)->PSC_B
#define PSC_C ((PSC_SongInfo *)info->data)->PSC_C
#define PSC ((PSC_SongInfo *)info->data)->PSC

void PSC_Init(AYSongInfo * info)
{
	unsigned char * module = info->module;
	PSC_File *header = (PSC_File *)module;

	info->data = (PSC_SongInfo *) &ppp;

	if (info)

		PSC.DelayCounter = 1;
	PSC.Delay = header->PSC_Delay;
	PSC.Positions_Pointer = PSC_PatternsPointer;
	PSC.Lines_Counter = 1;
	PSC.Noise_Base = 0;

	PSC_A.num = 0;
	PSC_B.num = 1;
	PSC_C.num = 2;

	PSC_A.SamplePointer = PSC_SamplesPointers(0) + 0x4c;
	PSC_B.SamplePointer = PSC_A.SamplePointer;
	PSC_C.SamplePointer = PSC_A.SamplePointer;
	PSC_A.OrnamentPointer = ay_sys_getword(&module[PSC_OrnamentsPointer]) + PSC_OrnamentsPointer;
	PSC_B.OrnamentPointer = PSC_A.OrnamentPointer;
	PSC_C.OrnamentPointer = PSC_A.OrnamentPointer;

	PSC_A.Break_Ornament_Loop = false;
	PSC_A.Ornament_Enabled = false;
	PSC_A.Enabled = false;
	PSC_A.Break_Sample_Loop = false;
	PSC_A.Ton_Slide_Enabled = false;
	PSC_A.Note_Skip_Counter = 1;
	PSC_A.Ton = 0;

	PSC_B.Break_Ornament_Loop = false;
	PSC_B.Ornament_Enabled = false;
	PSC_B.Enabled = false;
	PSC_B.Break_Sample_Loop = false;
	PSC_B.Ton_Slide_Enabled = false;
	PSC_B.Note_Skip_Counter = 1;
	PSC_B.Ton = 0;

	PSC_C.Break_Ornament_Loop = false;
	PSC_C.Ornament_Enabled = false;
	PSC_C.Enabled = false;
	PSC_C.Break_Sample_Loop = false;
	PSC_C.Ton_Slide_Enabled = false;
	PSC_C.Note_Skip_Counter = 1;
	PSC_C.Ton = 0;

	info->slow = 1;
}

void PSC_PatternInterpreter(AYSongInfo * info, PSC_Channel_Parameters * chan)
{
	unsigned char *module = info->module;
	PSC_File *header = (PSC_File *)module;
	bool quit;
	bool b1b, b2b, b3b, b4b, b5b, b6b, b7b;
	quit = b1b = b2b = b3b = b4b = b5b = b6b = b7b = false;
	do
	{
		unsigned char val = module[chan->Address_In_Pattern];
		if(val >= 0xc0)
		{
			chan->Note_Skip_Counter = val - 0xbf;
			quit = true;
		}
		else if(val >= 0xa0 && val <= 0xbf)
		{
			//chan->OrnamentPointer = (*(unsigned short *) &module[PSC_OrnamentsPointer + (val - 0xa0) * 2]) +PSC_OrnamentsPointer;
			chan->OrnamentPointer = ay_sys_getword(&module[PSC_OrnamentsPointer + (val - 0xa0) * 2]) + PSC_OrnamentsPointer;
		}
		else if(val >= 0x7e && val <= 0x9f)
		{
			if(val >= 0x80)
				chan->SamplePointer = PSC_SamplesPointers(val - 0x80) + 0x4c;
		}
		else if(val == 0x6b)
		{
			chan->Address_In_Pattern++;
			chan->Addition_To_Ton = module[chan->Address_In_Pattern];
			b5b = true;
		}
		else if(val == 0x6c)
		{
			chan->Address_In_Pattern++;
			chan->Addition_To_Ton = -(signed char)(module[chan->Address_In_Pattern]);
			b5b = true;
		}
		else if(val == 0x6d)
		{
			b4b = true;
			chan->Address_In_Pattern++;
			chan->Addition_To_Ton = module[chan->Address_In_Pattern];
		}
		else if(val == 0x6e)
		{
			chan->Address_In_Pattern++;
			PSC.Delay = module[chan->Address_In_Pattern];
		}
		else if(val == 0x6f)
		{
			b1b = true;
			chan->Address_In_Pattern++;
		}
		else if(val == 0x70)
		{
			b3b = true;
			chan->Address_In_Pattern++;
			chan->Volume_Counter1 = module[chan->Address_In_Pattern];
		}
		else if(val == 0x71)
		{
			chan->Break_Ornament_Loop = true;
			chan->Address_In_Pattern++;
		}
		else if(val == 0x7a)
		{
			chan->Address_In_Pattern++;
			if(chan->num == 1)
			{
				ay_writeay(AY_ENV_SHAPE, module[chan->Address_In_Pattern] & 15);
				ay_writeay(AY_ENV_FINE, module[chan->Address_In_Pattern + 1]);
				ay_writeay(AY_ENV_COARSE, module[chan->Address_In_Pattern + 2]);
				chan->Address_In_Pattern += 2;
			}
		}
		else if(val == 0x7b)
		{
			chan->Address_In_Pattern++;
			if(chan->num == 1)
				PSC.Noise_Base = module[chan->Address_In_Pattern];
		}
		else if(val == 0x7c)
		{
			b1b = b3b = b4b = b5b = b6b = b7b = false;
			b2b = true;
		}
		else if(val == 0x7d)
		{
			chan->Break_Sample_Loop = true;
		}
		else if(val >= 0x58 && val <= 0x66)
		{
			chan->Initial_Volume = val - 0x57;
			chan->Envelope_Enabled = false;
			b6b = true;
		}
		else if(val == 0x57)
		{
			chan->Initial_Volume = 0xf;
			chan->Envelope_Enabled = true;
			b6b = true;
		}
		else if(val <= 0x56)
		{
			chan->Note = val;
			b6b = true;
			b7b = true;
		}
		else
			chan->Address_In_Pattern++;
		chan->Address_In_Pattern++;
	}
	while(!quit);

	if(b7b)
	{
		chan->Break_Ornament_Loop = false;
		chan->Ornament_Enabled = true;
		chan->Enabled = true;
		chan->Break_Sample_Loop = false;
		chan->Ton_Slide_Enabled = false;
		chan->Ton_Accumulator = 0;
		chan->Current_Ton_Sliding = 0;
		chan->Noise_Accumulator = 0;
		chan->Volume_Counter = 0;
		chan->Position_In_Sample = 0;
		chan->Position_In_Ornament = 0;
	}
	if(b6b)
		chan->Volume = chan->Initial_Volume;
	if(b5b)
	{
		chan->Gliss = false;
		chan->Ton_Slide_Enabled = true;
	}
	if(b4b)
	{
		chan->Current_Ton_Sliding = chan->Ton - ASM_Table[chan->Note];
		chan->Gliss = true;
		if(chan->Current_Ton_Sliding >= 0)
			chan->Addition_To_Ton = -chan->Addition_To_Ton;
		chan->Ton_Slide_Enabled = true;
	}
	if(b3b)
	{
		chan->Volume_Counter = chan->Volume_Counter1;
		chan->Volume_Inc = true;
		if((chan->Volume_Counter & 0x40) != 0)
		{
			chan->Volume_Counter = -(signed char)(chan->Volume_Counter | 128);
			chan->Volume_Inc = false;
		}
		chan->Volume_Counter_Init = chan->Volume_Counter;
	}
	if(b2b)
	{
		chan->Break_Ornament_Loop = false;
		chan->Ornament_Enabled = false;
		chan->Enabled = false;
		chan->Break_Sample_Loop = false;
		chan->Ton_Slide_Enabled = false;
	}
	if(b1b)
		chan->Ornament_Enabled = false;
}

void PSC_GetRegisters(AYSongInfo * info, PSC_Channel_Parameters * chan, unsigned char * TempMixer)
{
	unsigned char *module = info->module;
	unsigned char j, b;
	if(chan->Enabled)
	{
		j = chan->Note;
		if(chan->Ornament_Enabled)
		{
			b = module[chan->OrnamentPointer + chan->Position_In_Ornament * 2];
			chan->Noise_Accumulator += b;
			j += module[chan->OrnamentPointer + chan->Position_In_Ornament * 2 + 1];
			if((signed char)j < 0)
				j += 0x56;
			if(j > 0x55)
				j -= 0x56;
			if(j > 0x55)
				j = 0x55;
			if((b & 128) == 0)
				chan->Loop_Ornament_Position = chan->Position_In_Ornament;
			if((b & 64) == 0)
			{
				if(!chan->Break_Ornament_Loop)
					chan->Position_In_Ornament = chan->Loop_Ornament_Position;
				else
				{
					chan->Break_Ornament_Loop = false;
					if((b & 32) == 0)
						chan->Ornament_Enabled = false;
					chan->Position_In_Ornament++;
				}
			}
			else
			{
				if((b & 32) == 0)
					chan->Ornament_Enabled = false;
				chan->Position_In_Ornament++;
			}
		}
		chan->Note = j;
		//chan->Ton = *(unsigned short *) &module[chan->SamplePointer + chan->Position_In_Sample * 6];
		chan->Ton = ay_sys_getword(&module[chan->SamplePointer + chan->Position_In_Sample * 6]);
		chan->Ton_Accumulator += chan->Ton;
		chan->Ton = ASM_Table[j] + chan->Ton_Accumulator;
		if(chan->Ton_Slide_Enabled)
		{
			chan->Current_Ton_Sliding += chan->Addition_To_Ton;
			if(chan->Gliss && (((chan->Current_Ton_Sliding < 0) && (chan->Addition_To_Ton <= 0)) || ((chan->Current_Ton_Sliding >= 0) && (chan->Addition_To_Ton >= 0))))
				chan->Ton_Slide_Enabled = false;
			chan->Ton += chan->Current_Ton_Sliding;
		}
		chan->Ton = chan->Ton & 0xfff;
		b = module[chan->SamplePointer + chan->Position_In_Sample * 6 + 4];
		*TempMixer = *TempMixer | ((b & 9) << 3);
		j = 0;
		if((b & 2) != 0)
			j++;
		if((b & 4) != 0)
			j--;
		if(chan->Volume_Counter > 0)
		{
			chan->Volume_Counter--;
			if(chan->Volume_Counter == 0)
			{
				if(chan->Volume_Inc)
					j++;
				else
					j--;
				chan->Volume_Counter = chan->Volume_Counter_Init;
			}
		}
		chan->Volume += j;
		if((signed char)chan->Volume < 0)
			chan->Volume = 0;
		else if(chan->Volume > 15)
			chan->Volume = 15;
		chan->Amplitude = ((chan->Volume + 1) * (module[chan->SamplePointer + chan->Position_In_Sample * 6 + 3] & 15)) >> 4;
		if(chan->Envelope_Enabled && ((b & 16) == 0))
			chan->Amplitude = chan->Amplitude | 16;
		if(((chan->Amplitude & 16) != 0) & ((b & 8) != 0))
		{
			unsigned short env = ay_readay(AY_ENV_FINE) | (ay_readay(AY_ENV_COARSE) << 8);
			env += (signed char)(module[chan->SamplePointer + chan->Position_In_Sample * 6 + 2]);
			ay_writeay(AY_ENV_FINE, env & 0xff);
			ay_writeay(AY_ENV_COARSE, (env >> 8) & 0xff);
		}
		else
		{
			chan->Noise_Accumulator += module[chan->SamplePointer + chan->Position_In_Sample * 6 + 2];
			if((b & 8) == 0)
				ay_writeay(AY_NOISE_PERIOD, chan->Noise_Accumulator & 31);
		}
		if((b & 128) == 0)
			chan->Loop_Sample_Position = chan->Position_In_Sample;
		if((b & 64) == 0)
		{
			if(!chan->Break_Sample_Loop)
				chan->Position_In_Sample = chan->Loop_Sample_Position;
			else
			{
				chan->Break_Sample_Loop = false;
				if((b & 32) == 0)
					chan->Enabled = false;
				chan->Position_In_Sample++;
			}
		}
		else
		{
			if((b & 32) == 0)
				chan->Enabled = false;
			chan->Position_In_Sample++;
		}
	}
	else
		chan->Amplitude = 0;
	*TempMixer = *TempMixer >> 1;
}

void PSC_Play(AYSongInfo * info)
{
	unsigned char *module; 
	unsigned char TempMixer;

	//return;

	module = info->module;

	if(--PSC.DelayCounter <= 0)
	{
		if(--PSC.Lines_Counter <= 0)
		{
			if(module[PSC.Positions_Pointer + 1] == 255)
			{
				//PSC.Positions_Pointer = *(unsigned short *) &module[PSC.Positions_Pointer + 2];
				PSC.Positions_Pointer = ay_sys_getword(&module[PSC.Positions_Pointer + 2]);
			}
			PSC.Lines_Counter = module[PSC.Positions_Pointer + 1];
			//PSC_A.Address_In_Pattern = *(unsigned short *) &module[PSC.Positions_Pointer + 2];
			//PSC_B.Address_In_Pattern = *(unsigned short *) &module[PSC.Positions_Pointer + 4];
			//PSC_C.Address_In_Pattern = *(unsigned short *) &module[PSC.Positions_Pointer + 6];
			PSC_A.Address_In_Pattern = ay_sys_getword(&module[PSC.Positions_Pointer + 2]);
			PSC_B.Address_In_Pattern = ay_sys_getword(&module[PSC.Positions_Pointer + 4]);
			PSC_C.Address_In_Pattern = ay_sys_getword(&module[PSC.Positions_Pointer + 6]);
			PSC.Positions_Pointer += 8;
			PSC_A.Note_Skip_Counter = 1;
			PSC_B.Note_Skip_Counter = 1;
			PSC_C.Note_Skip_Counter = 1;
		}
		if(--PSC_A.Note_Skip_Counter == 0)
			PSC_PatternInterpreter(info, &PSC_A);
		if(--PSC_B.Note_Skip_Counter == 0)
			PSC_PatternInterpreter(info, &PSC_B);
		if(--PSC_C.Note_Skip_Counter == 0)
			PSC_PatternInterpreter(info, &PSC_C);
		PSC_A.Noise_Accumulator += PSC.Noise_Base;
		PSC_B.Noise_Accumulator += PSC.Noise_Base;
		PSC_C.Noise_Accumulator += PSC.Noise_Base;
		PSC.DelayCounter = PSC.Delay;
	}
	TempMixer = 0;
	PSC_GetRegisters(info, &PSC_A, &TempMixer);
	PSC_GetRegisters(info, &PSC_B, &TempMixer);
	PSC_GetRegisters(info, &PSC_C, &TempMixer);

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

void PSC_GetInfo(AYSongInfo * info)
{
	unsigned char *module = info->module;
	PSC_File *header = (PSC_File *)module;
	unsigned char b;
	unsigned long tm = 0;
	long i;
	char a1, a2, a3;
	unsigned long j1, j2, j3;
	unsigned long pptr, cptr;
	bool f71, f72, f73, f61, f62, f63, f41, f42, f43, flg;
	unsigned short j11, j22, j33;
	//unsigned char * ptr;

	f71 = f72 = f73 = f61 = f62 = f63 = f41 = f42 = f43 = flg = false;
	j11 = j22 = j33 = 0;

	b = header->PSC_Delay;
	pptr = PSC_PatternsPointer;
	pptr++;
	while(module[pptr] != 255)
	{
		pptr += 8;
		if(pptr >= 65536)
		{
			info->Length = 0;
			return;
		}
	}
	if(pptr >= 65546 - 2)
	{
		info->Length = 0;
	}
	//cptr = *(unsigned short *) &module[pptr + 1];
	cptr = ay_sys_getword(&module[pptr + 1]);
	cptr++;
	pptr = PSC_PatternsPointer;
	pptr++;
	while(module[pptr] != 255)
	{
		// if(pptr == cptr)
		//     info->Loop = tm;

		if(pptr >= 65536 - 6)
		{
			info->Length = 0;
			return;
		}
		//j1 = *(unsigned short *) &module[pptr + 1];
		//j2 = *(unsigned short *) &module[pptr + 3];
		//j3 = *(unsigned short *) &module[pptr + 5];
		j1 = ay_sys_getword(&module[pptr + 1]);
		j2 = ay_sys_getword(&module[pptr + 3]);
		j3 = ay_sys_getword(&module[pptr + 5]);
		pptr += 8;
		if(pptr >= 65536)
		{
			info->Length = 0;
			return;
		}
		a1 = a2 = a3 = 1;
		for(i = 0; i < module[pptr - 8]; i++)
		{
			a1--;
			if(a1 == 0)
			{
				while(true)
				{
					unsigned char val = module[j1];
					if(val >= 0xc0)
					{
						a1 = val - 0xbf;
						j1++;
						break;
					}
					else if((val >= 0x67 && val <= 0x6d) || (val >= 0x6f && val <= 0x7b))
					{
						j1++;
					}
					else if(val == 0x6e)
					{
						j1++;
						b = module[j1];
					}
					j1++;
				}

			}

			a2--;
			if(a2 == 0)
			{
				while(true)
				{
					unsigned char val = module[j2];
					if(val >= 0xc0)
					{
						a2 = val - 0xbf;
						j2++;
						break;
					}
					else if((val >= 0x67 && val <= 0x6d) || (val >= 0x6f && val <= 0x7b))
					{
						j2++;
					}
					else if(val == 0x6e)
					{
						j2++;
						b = module[j2];
					}
					j2++;
				}
			}

			a3--;
			if(a3 == 0)
			{
				while(true)
				{
					unsigned char val = module[j3];
					if(val >= 0xc0)
					{
						a3 = val - 0xbf;
						j3++;
						break;
					}
					else if((val >= 0x67 && val <= 0x6d) || (val >= 0x6f && val <= 0x7b))
					{
						j3++;
					}
					else if(val == 0x6e)
					{
						j3++;
						b = module[j3];
					}
					j3++;
				}
			}
			tm += b;
		}
	}

	info->len = tm;
	//ptr = module + 0x19;

	//s->counter = (int)&module[0x10];

	strncpy(info->Name, &module[0x19], 20);
	strncpy(info->Autor, &module[0x31], 20);
	//ptr = module + 0x31;
	//info->Author = ay_sys_getstr(ptr, 20);
}

bool PSC_Detect(unsigned char * module, unsigned int length, AYSongInfo * s)
{
	unsigned int j, j1;
	PSC_File *header = (PSC_File *)module;




	//s->counter = 1001;

	if(length < 0x4c + 2)
		return false;

	//s->counter = 1002;

	if(PSC_OrnamentsPointer >= length)
		return false;

	// s->counter = 1003; 

	if(PSC_OrnamentsPointer < 0x4c + 2)
		return false;
	// s->counter = 1004;    

	if(PSC_OrnamentsPointer > 64 + 0x4c)
		return false;

	// s->counter = 1005;

	if((PSC_OrnamentsPointer % 2) != 0)
		return false;

	//s->counter = 1006;    

	if((unsigned long)(PSC_SamplesPointers(0) + 0x4c + 5) > 65534)
		return false;

	// s->counter = 1007;    

	if(PSC_SamplesPointers(0) + 0x4c + 5 > length)
		return false;

	//s->err = 8;

	j = ay_sys_getword(&module[PSC_OrnamentsPointer]);
	j += PSC_OrnamentsPointer;

	//s->counter =j;

	//if(j > 65535)
	//    return false;

	// s->counter = 1009;    

	if(j >= length)
		return false;

	j1 = 0;
	j1 = ay_sys_getword(&module[PSC_OrnamentsPointer-2]);
	j1 += 0x4c;
	//  if(j1 > 65535)
	//      return false;

	//  s->err = 9;


	if(j1 >= length)
		return false;

	// s->err = 10;


	if(j - j1 < 8)
		return false;

	//s->counter = 1013;    

	// s->err = 11; 

	if(((j - j1) % 6) != 2) //// 17.11
	{
		s->err = 1;
		return false;
	}

	//s->err = 12;

	j1 = PSC_SamplesPointers(0) + 0x4c + 4;
	while(/*(j1 < 65536) &&*/ (j1 <= length) && ((module[j1] & 32) != 0))
		j1 += 6;
	if(j1 > 65534)
		return false;

	//s->err = 13;   

	// s->counter = 1014;    

	if(j1 > length)
		return false;

	//s->err = 1;

	if(PSC_OrnamentsPointer - 0x4c - 2 > 0)
	{
		if(j1 + 3 != PSC_SamplesPointers(1) + 0x4c) //17.11
		{
			s->err = 2;
			return false;
		}
	}
	else 
		if(j1 + 4 != j)
		{
			//s->counter = 1015;
			return false;
		}

		//s->err = 14;

		// s->counter = 1016;

		if((unsigned long)(PSC_PatternsPointer + 11) > 65535)
			return false;

		// s->counter = 1017;     

		if(PSC_PatternsPointer + 11 >= length)
			return false;

		//s->counter = 1018;

		j = PSC_PatternsPointer + 1;
		if(module[j] == 255)
			return false;

		//  s->counter = 1019;

		while(1)
		{
			j += 8;
			if((j > 65532) && (j + 2 > length) || (module[j] == 255))
				break;
		}

		if(j > 65532)
			return false;

		//s->counter = 1020;    

		if(j + 2 > length)
			return false;

		//  s->counter = 1021;

		strcpy(s->player, "Pro Sound Creator");	

		return true;

}









int pp = 0;
int offset;


typedef struct 
{
	unsigned char ASC0_Delay;
	unsigned char ASC0_PatternsPointers0, ASC0_PatternsPointers1;
	unsigned char ASC0_SamplesPointers0, ASC0_SamplesPointers1;
	unsigned char ASC0_OrnamentsPointers0, ASC0_OrnamentsPointers1;
	unsigned char ASC0_Number_Of_Positions;
	unsigned char ASC0_Positions[65536 - 8];
} ASC0_File;

typedef struct 
{
	unsigned char ASC1_Delay, ASC1_LoopingPosition;
	unsigned char ASC1_PatternsPointers0, ASC1_PatternsPointers1;
	unsigned char ASC1_SamplesPointers0, ASC1_SamplesPointers1;
	unsigned char ASC1_OrnamentsPointers0, ASC1_OrnamentsPointers1;
	unsigned char ASC1_Number_Of_Positions;
	unsigned char ASC1_Positions[65536 - 8];
} ASC1_File;

#define ASC1_PatternsPointers (header->ASC1_PatternsPointers0 | (header->ASC1_PatternsPointers1 << 8))
#define ASC1_SamplesPointers (header->ASC1_SamplesPointers0 | (header->ASC1_SamplesPointers1 << 8))
#define ASC1_OrnamentsPointers (header->ASC1_OrnamentsPointers0 | (header->ASC1_OrnamentsPointers1 << 8))

#define ASC0_PatternsPointers (header0->ASC0_PatternsPointers0 | (header0->ASC0_PatternsPointers1 << 8))
#define ASC0_SamplesPointers (header0->ASC0_SamplesPointers0 | (header0->ASC0_SamplesPointers1 << 8))
#define ASC0_OrnamentsPointers (header0->ASC0_OrnamentsPointers0 | (header0->ASC0_OrnamentsPointers1 << 8))


typedef struct 
{
	unsigned short Initial_Point_In_Sample, Point_In_Sample, Loop_Point_In_Sample, Initial_Point_In_Ornament, Point_In_Ornament, Loop_Point_In_Ornament, Address_In_Pattern, Ton, Ton_Deviation;
	unsigned char Note, Addition_To_Note, Number_Of_Notes_To_Skip, Initial_Noise, Current_Noise, Volume, Ton_Sliding_Counter, Amplitude, Amplitude_Delay, Amplitude_Delay_Counter;
	short Current_Ton_Sliding, Substruction_for_Ton_Sliding;
	signed char Note_Skip_Counter, Addition_To_Amplitude;
	bool Envelope_Enabled, Sound_Enabled, Sample_Finished, Break_Sample_Loop, Break_Ornament_Loop;
} ASC_Channel_Parameters;

typedef struct 
{
	unsigned char Delay, DelayCounter, CurrentPosition;
} ASC_Parameters;

typedef struct 
{
	ASC_Parameters ASC;
	ASC_Channel_Parameters ASC_A, ASC_B, ASC_C;
} ASC_SongInfo;

ASC_SongInfo asc;

#define ASC_A ((ASC_SongInfo *)info->data)->ASC_A
#define ASC_B ((ASC_SongInfo *)info->data)->ASC_B
#define ASC_C ((ASC_SongInfo *)info->data)->ASC_C
#define ASC ((ASC_SongInfo *)info->data)->ASC

#define GET_ADDRINPATT(x,y) ((module[ascPatPt + 6 * module[x + 9] + y * 2] | (module[ascPatPt + 6 * module[x + 9] + 1 + y * 2] << 8))  + ascPatPt)


void ASC_Init_orig(AYSongInfo * info)
{
	unsigned char *module = info->module;
	ASC1_File *header = (ASC1_File *)module;
	unsigned short ascPatPt = ASC1_PatternsPointers;

	info->data = &asc;

	memset(&ASC_A, 0, sizeof(ASC_Channel_Parameters));
	memset(&ASC_B, 0, sizeof(ASC_Channel_Parameters));
	memset(&ASC_C, 0, sizeof(ASC_Channel_Parameters));

	ASC.CurrentPosition = 0;
	ASC.DelayCounter = 1;
	ASC.Delay = header->ASC1_Delay;
	ASC_A.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[9]]) + ascPatPt;
	ASC_B.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[9] + 2]) + ascPatPt;
	ASC_C.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[9] + 4]) + ascPatPt;

	info->slow = 1;
}


void AS0_Init(AYSongInfo * info)
{
	unsigned char *module = info->module;
	ASC0_File *header0 = (ASC0_File *)module;
	unsigned short ascPatPt = ASC0_PatternsPointers;


	info->data = &asc;

	memset(&ASC_A, 0, sizeof(ASC_Channel_Parameters));
	memset(&ASC_B, 0, sizeof(ASC_Channel_Parameters));
	memset(&ASC_C, 0, sizeof(ASC_Channel_Parameters));
	ASC.CurrentPosition = 0;
	ASC.DelayCounter = 1;
	ASC.Delay = header0->ASC0_Delay;
	ASC_A.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[8]]) + ascPatPt;
	ASC_B.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[8] + 2]) + ascPatPt;
	ASC_C.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[8] + 4]) + ascPatPt;

	info->slow = 0;
}

void ASC_Init(AYSongInfo * info)
{

	if (pp==3)
		AS0_Init(info);		  
	else	
		ASC_Init_orig(info);		   
}


void ASC_PatternInterpreter(AYSongInfo * info, ASC_Channel_Parameters * chan, int AS0)
{
	unsigned char *module = info->module;

	ASC1_File *header = (ASC1_File *)module;
	ASC0_File *header0 = (ASC0_File *)module;

	short delta_ton;
	bool Initialization_Of_Ornament_Disabled, Initialization_Of_Sample_Disabled;

	Initialization_Of_Ornament_Disabled = Initialization_Of_Sample_Disabled = false;

	chan->Ton_Sliding_Counter = 0;
	chan->Amplitude_Delay_Counter = 0;
	while(true)
	{
		unsigned char val = module[chan->Address_In_Pattern];
		if(val <= 0x55)
		{
			chan->Note = val;
			chan->Address_In_Pattern++;
			chan->Current_Noise = chan->Initial_Noise;
			if((signed char)(chan->Ton_Sliding_Counter) <= 0)
				chan->Current_Ton_Sliding = 0;
			if(!Initialization_Of_Sample_Disabled)
			{
				chan->Addition_To_Amplitude = 0;
				chan->Ton_Deviation = 0;
				chan->Point_In_Sample = chan->Initial_Point_In_Sample;
				chan->Sound_Enabled = true;
				chan->Sample_Finished = false;
				chan->Break_Sample_Loop = false;
			}
			if(!Initialization_Of_Ornament_Disabled)
			{
				chan->Point_In_Ornament = chan->Initial_Point_In_Ornament;
				chan->Addition_To_Note = 0;
			}
			if(chan->Envelope_Enabled)
			{
				ay_writeay(AY_ENV_FINE, module[chan->Address_In_Pattern]);
				chan->Address_In_Pattern++;
			}
			break;
		}
		else if((val >= 0x56) && (val <= 0x5d))
		{
			chan->Address_In_Pattern++;
			break;
		}
		else if(val == 0x5e)
		{
			chan->Break_Sample_Loop = true;
			chan->Address_In_Pattern++;
			break;
		}
		else if(val == 0x5f)
		{
			chan->Sound_Enabled = false;
			chan->Address_In_Pattern++;
			break;
		}
		else if((val >= 0x60) && (val <= 0x9f))
		{
			chan->Number_Of_Notes_To_Skip = val - 0x60;
		}
		else if((val >= 0xa0) && (val <= 0xbf))
		{
			if (!AS0)
				chan->Initial_Point_In_Sample = ay_sys_getword(&module[(module[chan->Address_In_Pattern] - 0xa0) * 2 + ASC1_SamplesPointers]) + ASC1_SamplesPointers;
			else
				chan->Initial_Point_In_Sample = ay_sys_getword(&module[(module[chan->Address_In_Pattern] - 0xa0) * 2 + ASC0_SamplesPointers]) + ASC0_SamplesPointers;

		}
		else if((val >= 0xc0) && (val <= 0xdf))
		{
			if (!AS0)
				chan->Initial_Point_In_Ornament = ay_sys_getword(&module[(module[chan->Address_In_Pattern] - 0xc0) * 2 + ASC1_OrnamentsPointers]) + ASC1_OrnamentsPointers;
			else
				chan->Initial_Point_In_Ornament = ay_sys_getword(&module[(module[chan->Address_In_Pattern] - 0xc0) * 2 + ASC0_OrnamentsPointers]) + ASC0_OrnamentsPointers;

		}
		else if(val == 0xe0)
		{
			chan->Volume = 15;
			chan->Envelope_Enabled = true;
		}
		else if((val >= 0xe1) && (val <= 0xef))
		{
			chan->Volume = val - 0xe0;
			chan->Envelope_Enabled = false;
		}
		else if(val == 0xf0)
		{
			chan->Address_In_Pattern++;
			chan->Initial_Noise = module[chan->Address_In_Pattern];
		}
		else if(val == 0xf1)
		{
			Initialization_Of_Sample_Disabled = true;
		}
		else if(val == 0xf2)
		{
			Initialization_Of_Ornament_Disabled = true;
		}
		else if(val == 0xf3)
		{
			Initialization_Of_Sample_Disabled = true;
			Initialization_Of_Ornament_Disabled = true;
		}
		else if(val == 0xf4)
		{
			chan->Address_In_Pattern++;
			ASC.Delay = module[chan->Address_In_Pattern];
		}
		else if(val == 0xf5)
		{
			chan->Address_In_Pattern++;
			chan->Substruction_for_Ton_Sliding = -(signed char)(module[chan->Address_In_Pattern]) * 16;
			chan->Ton_Sliding_Counter = 255;
		}
		else if(val == 0xf6)
		{
			chan->Address_In_Pattern++;
			chan->Substruction_for_Ton_Sliding = (signed char)(module[chan->Address_In_Pattern]) * 16;
			chan->Ton_Sliding_Counter = 255;
		}
		else if(val == 0xf7)
		{
			chan->Address_In_Pattern++;
			Initialization_Of_Sample_Disabled = true;
			if(module[chan->Address_In_Pattern + 1] < 0x56)
				delta_ton = ASM_Table[chan->Note] + (chan->Current_Ton_Sliding / 16) - ASM_Table[module[chan->Address_In_Pattern + 1]];
			else
				delta_ton = chan->Current_Ton_Sliding / 16;
			delta_ton = delta_ton << 4;
			chan->Substruction_for_Ton_Sliding = -delta_ton / (signed char)(module[chan->Address_In_Pattern]);
			chan->Current_Ton_Sliding = delta_ton - delta_ton % (signed char)(module[chan->Address_In_Pattern]);
			chan->Ton_Sliding_Counter = (signed char)(module[chan->Address_In_Pattern]);
		}
		else if(val == 0xf8)
		{
			ay_writeay(AY_ENV_SHAPE, 8);
		}
		else if(val == 0xf9)
		{
			chan->Address_In_Pattern++;
			if(module[chan->Address_In_Pattern + 1] < 0x56)
			{
				delta_ton = ASM_Table[chan->Note] - ASM_Table[module[chan->Address_In_Pattern + 1]];
			}
			else
				delta_ton = chan->Current_Ton_Sliding / 16;
			delta_ton = delta_ton << 4;
			chan->Substruction_for_Ton_Sliding = -delta_ton / (signed char)(module[chan->Address_In_Pattern]);
			chan->Current_Ton_Sliding = delta_ton - delta_ton % (signed char)(module[chan->Address_In_Pattern]);
			chan->Ton_Sliding_Counter = (signed char)(module[chan->Address_In_Pattern]);

		}
		else if(val == 0xfa)
		{
			ay_writeay(AY_ENV_SHAPE, 10);
		}
		else if(val == 0xfb)
		{
			chan->Address_In_Pattern++;
			if((module[chan->Address_In_Pattern] & 32) == 0)
			{
				chan->Amplitude_Delay = module[chan->Address_In_Pattern] << 3;
				chan->Amplitude_Delay_Counter = chan->Amplitude_Delay;
			}
			else
			{
				chan->Amplitude_Delay = ((module[chan->Address_In_Pattern] << 3) ^ 0xf8) + 9;
				chan->Amplitude_Delay_Counter = chan->Amplitude_Delay;
			}
		}
		else if(val == 0xfc)
		{
			ay_writeay(AY_ENV_SHAPE, 12);
		}
		else if(val == 0xfe)
		{
			ay_writeay(AY_ENV_SHAPE, 14);
		}
		chan->Address_In_Pattern++;
	}
	chan->Note_Skip_Counter = chan->Number_Of_Notes_To_Skip;
}

void ASC_GetRegisters(AYSongInfo * info, ASC_Channel_Parameters * chan, unsigned char * TempMixer)
{
	unsigned char *module = info->module;
	signed char j;
	bool Sample_Says_OK_for_Envelope;
	if(chan->Sample_Finished || !chan->Sound_Enabled)
		chan->Amplitude = 0;
	else
	{
		if(chan->Amplitude_Delay_Counter != 0)
		{
			if(chan->Amplitude_Delay_Counter >= 16)
			{
				chan->Amplitude_Delay_Counter -= 8;
				if(chan->Addition_To_Amplitude < -15)
					chan->Addition_To_Amplitude++;
				else if(chan->Addition_To_Amplitude > 15)
					chan->Addition_To_Amplitude--;
			}
			else
			{
				if((chan->Amplitude_Delay_Counter & 1) != 0)
				{
					if(chan->Addition_To_Amplitude > -15)
						chan->Addition_To_Amplitude--;
				}
				else if(chan->Addition_To_Amplitude < 15)
					chan->Addition_To_Amplitude++;
				chan->Amplitude_Delay_Counter = chan->Amplitude_Delay;
			}
		}
		if((module[chan->Point_In_Sample] & 128) != 0)
			chan->Loop_Point_In_Sample = chan->Point_In_Sample;
		if((module[chan->Point_In_Sample] & 96) == 32)
			chan->Sample_Finished = true;
		chan->Ton_Deviation += (signed char)(module[chan->Point_In_Sample + 1]);
		*TempMixer |= (module[chan->Point_In_Sample + 2] & 9) << 3;
		if((module[chan->Point_In_Sample + 2] & 6) == 2)
			Sample_Says_OK_for_Envelope = true;
		else
			Sample_Says_OK_for_Envelope = false;
		if((module[chan->Point_In_Sample + 2] & 6) == 4)
		{
			if(chan->Addition_To_Amplitude > -15)
				chan->Addition_To_Amplitude--;
		}
		if((module[chan->Point_In_Sample + 2] & 6) == 6)
		{
			if(chan->Addition_To_Amplitude < 15)
				chan->Addition_To_Amplitude++;
		}
		chan->Amplitude = chan->Addition_To_Amplitude + (module[chan->Point_In_Sample + 2] >> 4);
		if((signed char)(chan->Amplitude) < 0)
			chan->Amplitude = 0;
		else if(chan->Amplitude > 15)
			chan->Amplitude = 15;
		chan->Amplitude = (chan->Amplitude * (chan->Volume + 1)) >> 4;
		if(Sample_Says_OK_for_Envelope && ((*TempMixer & 64) != 0))
			ay_writeay(AY_ENV_FINE, ay_readay(AY_ENV_FINE) + ((signed char)(module[chan->Point_In_Sample] << 3) / 8));
		else
			chan->Current_Noise += (signed char)(module[chan->Point_In_Sample] << 3) / 8;
		chan->Point_In_Sample += 3;
		if((module[chan->Point_In_Sample - 3] & 64) != 0)
		{
			if(!chan->Break_Sample_Loop)
				chan->Point_In_Sample = chan->Loop_Point_In_Sample;
			else if((module[chan->Point_In_Sample - 3] & 32) != 0)
				chan->Sample_Finished = true;
		}
		if((module[chan->Point_In_Ornament] & 128) != 0)
			chan->Loop_Point_In_Ornament = chan->Point_In_Ornament;
		chan->Addition_To_Note += module[chan->Point_In_Ornament + 1];
		chan->Current_Noise += (-(signed char)(module[chan->Point_In_Ornament] & 0x10)) | module[chan->Point_In_Ornament];
		chan->Point_In_Ornament += 2;
		if((module[chan->Point_In_Ornament - 2] & 64) != 0)
			chan->Point_In_Ornament = chan->Loop_Point_In_Ornament;
		if((*TempMixer & 64) == 0)
			ay_writeay(AY_NOISE_PERIOD, ((unsigned char)(chan->Current_Ton_Sliding >> 8) + chan->Current_Noise) & 0x1f);
		j = chan->Note + chan->Addition_To_Note;
		if(j < 0)
			j = 0;
		else if(j > 0x55)
			j = 0x55;
		chan->Ton = (ASM_Table[j] + chan->Ton_Deviation + (chan->Current_Ton_Sliding / 16)) & 0xfff;
		if(chan->Ton_Sliding_Counter != 0)
		{
			if((signed char)(chan->Ton_Sliding_Counter) > 0)
				chan->Ton_Sliding_Counter--;
			chan->Current_Ton_Sliding += chan->Substruction_for_Ton_Sliding;
		}
		if(chan->Envelope_Enabled && Sample_Says_OK_for_Envelope)
			chan->Amplitude |= 0x10;
	}
	*TempMixer = *TempMixer >> 1;
}

void ASC_Play_orig(AYSongInfo *info)
{
	unsigned short ascPatPt ;
	unsigned char *module = info->module;
	ASC1_File *header = (ASC1_File *)module;
	unsigned char TempMixer;

	if(--ASC.DelayCounter <= 0)
	{
		if(--ASC_A.Note_Skip_Counter < 0)
		{
			if(module[ASC_A.Address_In_Pattern] == 255)
			{
				if(++ASC.CurrentPosition >= header->ASC1_Number_Of_Positions)
					ASC.CurrentPosition = header->ASC1_LoopingPosition;
				ascPatPt = ASC1_PatternsPointers;
				//ASC_A.Address_In_Pattern = (*(unsigned short *)&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9]]) + ascPatPt;
				//ASC_B.Address_In_Pattern = (*(unsigned short *)&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9] + 2]) + ascPatPt;
				//ASC_C.Address_In_Pattern = (*(unsigned short *)&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9] + 4]) + ascPatPt;
				ASC_A.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9]]) + ascPatPt;
				ASC_B.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9] + 2]) + ascPatPt;
				ASC_C.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 9] + 4]) + ascPatPt;
				ASC_A.Initial_Noise = 0;
				ASC_B.Initial_Noise = 0;
				ASC_C.Initial_Noise = 0;
			}
			ASC_PatternInterpreter(info, &ASC_A, 0);
		}
		if(--ASC_B.Note_Skip_Counter < 0)
		{
			ASC_PatternInterpreter(info, &ASC_B, 0);
		}
		if(--ASC_C.Note_Skip_Counter < 0)
		{
			ASC_PatternInterpreter(info, &ASC_C, 0);
		}
		ASC.DelayCounter = ASC.Delay;
	}

	TempMixer = 0;
	ASC_GetRegisters(info, &ASC_A, &TempMixer);
	ASC_GetRegisters(info, &ASC_B, &TempMixer);
	ASC_GetRegisters(info, &ASC_C, &TempMixer);

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


void AS0_Play(AYSongInfo *info)
{
	unsigned short ascPatPt ;
	unsigned char *module = info->module;
	ASC0_File *header0 = (ASC0_File *)module;
	unsigned char TempMixer;

	if(--ASC.DelayCounter <= 0)
	{
		if(--ASC_A.Note_Skip_Counter < 0)
		{
			if(module[ASC_A.Address_In_Pattern] == 255)
			{
				if(++ASC.CurrentPosition >= header0->ASC0_Number_Of_Positions)
					ASC.CurrentPosition = 0;
				ascPatPt = ASC0_PatternsPointers;

				ASC_A.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 8]]) + ascPatPt;
				ASC_B.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 8] + 2]) + ascPatPt;
				ASC_C.Address_In_Pattern = ay_sys_getword(&module[ascPatPt + 6 * module[ASC.CurrentPosition + 8] + 4]) + ascPatPt;
				ASC_A.Initial_Noise = 0;
				ASC_B.Initial_Noise = 0;
				ASC_C.Initial_Noise = 0;
			}
			ASC_PatternInterpreter(info, &ASC_A, 1);
		}
		if(--ASC_B.Note_Skip_Counter < 0)
		{
			ASC_PatternInterpreter(info, &ASC_B, 1);
		}
		if(--ASC_C.Note_Skip_Counter < 0)
		{
			ASC_PatternInterpreter(info, &ASC_C, 1);
		}
		ASC.DelayCounter = ASC.Delay;
	}

	TempMixer = 0;
	ASC_GetRegisters(info, &ASC_A, &TempMixer);
	ASC_GetRegisters(info, &ASC_B, &TempMixer);
	ASC_GetRegisters(info, &ASC_C, &TempMixer);

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

void ASC_Play(AYSongInfo *info)
{

	if (pp==3)
		AS0_Play(info);
	else	  
		ASC_Play_orig(info);	

}

void ASC_GetInfo_orig(AYSongInfo * info, int ASC0)
{
	unsigned short pp;
	unsigned char np;
	short a1, a2, a3, a11, a22, a33;
	unsigned long j1, j2, j3;
	bool env1, env2, env3;
	long i, tm = 0;
	unsigned char b;
	unsigned char ascNumPos;
	unsigned short ascPatPt;
	unsigned char ascDelay;
	unsigned short ascLoopPos;

	unsigned char *module = info->module;
	ASC1_File *header = (ASC1_File *)module;
	ASC0_File *header0 = (ASC0_File *)module;


	if (!ASC0)
	{
		ascDelay = header->ASC1_Delay;
		ascLoopPos = header->ASC1_LoopingPosition;
		ascPatPt = ASC1_PatternsPointers;
		ascNumPos = header->ASC1_Number_Of_Positions;
	}
	else
	{
		ascDelay = header0->ASC0_Delay;
		ascLoopPos = 0;
		ascPatPt = ASC0_PatternsPointers;
		ascNumPos = header0->ASC0_Number_Of_Positions;
	}



	b = ascDelay;
	a1 = a2 = a3 = a11 = a22 = a33 = 0;
	env1 = env2 = env3 = false;
	for(i = 0; i < ascNumPos; i++)
	{
		// if(ascLoopPos == i)
		//   info->Loop = tm;

		if (ASC0)
		{  
			j1 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 8]]) + ascPatPt;
			j2 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 8] + 2]) + ascPatPt;
			j3 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 8] + 4]) + ascPatPt;
		}
		else
		{  
			j1 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 9]]) + ascPatPt;
			j2 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 9] + 2]) + ascPatPt;
			j3 = ay_sys_getword(&module[ascPatPt + 6 * module[i + 9] + 4]) + ascPatPt;
		}


		while(true)
		{
			a1--;
			if(a1 < 0)
			{
				if(module[j1] == 255)
					break;
				while(true)
				{
					unsigned char val = module[j1];
					if(val <= 0x55)
					{
						a1 = a11;
						j1++;
						if(env1)
							j1++;
						break;
					}
					else if((val >= 0x56) && (val <= 0x5f))
					{
						a1 = a11;
						j1++;
						break;
					}
					else if((val >= 0x60) && (val <= 0x9f))
					{
						a11 = val - 0x60;
					}
					else if(val == 0xe0)
					{
						env1 = true;
					}
					else if((val >= 0xe1) && (val <= 0xef))
					{
						env1 = false;
					}
					else if((val == 0xf0) || ((val >= 0xf5) && (val <= 0xf7)) || (val == 0xf9) || (val == 0xfb))
					{
						j1++;
					}
					else if(val == 0xf4)
					{
						j1++;
						b = module[j1];
					}
					j1++;
				}
			}

			a2--;
			if(a2 < 0)
			{
				while(true)
				{
					unsigned char val = module[j2];
					if(val <= 0x55)
					{
						a2 = a22;
						j2++;
						if(env2)
							j2++;
						break;
					}
					else if((val >= 0x56) && (val <= 0x5f))
					{
						a2 = a22;
						j2++;
						break;
					}
					else if((val >= 0x60) && (val <= 0x9f))
					{
						a22 = val - 0x60;
					}
					else if(val == 0xe0)
					{
						env2 = true;
					}
					else if((val >= 0xe1) && (val <= 0xef))
					{
						env2 = false;
					}
					else if((val == 0xf0) || ((val >= 0xf5) && (val <= 0xf7)) || (val == 0xf9) || (val == 0xfb))
					{
						j2++;
					}
					else if(val == 0xf4)
					{
						j2++;
						b = module[j2];
					}
					j2++;
				}
			}

			a3--;
			if(a3 < 0)
			{
				while(true)
				{
					unsigned char val = (unsigned char)module[j3];
					if(val <= 0x55)
					{
						a3 = a33;
						j3++;
						if(env3)
							j3++;
						break;
					}
					else if((val >= 0x56) && (val <= 0x5f))
					{
						a3 = a33;
						j3++;
						break;
					}
					else if((val >= 0x60) && (val <= 0x9f))
					{
						a33 = val - 0x60;
					}
					else if(val == 0xe0)
					{
						env3 = true;
					}
					else if((val >= 0xe1) && (val <= 0xef))
					{
						env3 = false;
					}
					else if((val == 0xf0) || ((val >= 0xf5) && (val <= 0xf7)) || (val == 0xf9) || (val == 0xfb))
					{
						j3++;
					}
					else if(val == 0xf4)
					{
						j3++;
						b = module[j3];
					}
					j3++;
				}
			}
			tm += b;
		}
	}

	info->len = tm;

	pp = ay_sys_getword(&module [2]);
	np = module [8];
	if((pp - np) == 72)
	{
		strncpy(info->Name, &module [pp - 44], 20);
		strncpy(info->Autor,&module [pp - 20], 20);
	}
}

void ASC_GetInfo(AYSongInfo * info)
{


	if (pp==3)   
		ASC_GetInfo_orig(info, 1);
	else
		ASC_GetInfo_orig(info, 0);

}


bool ASC1_Detect(unsigned char *module, unsigned long length)
{
	//INT
	int j;
	int j1;

	unsigned char j3;
	int delta;
	ASC1_File *header = (ASC1_File *)module;



	if(length < 9)
		return false;
	delta = ASC1_PatternsPointers - header->ASC1_Number_Of_Positions;
	if(delta < 9 || delta > 72)
		return false;
	if(ASC1_PatternsPointers> length)
		return false;
	if(ASC1_SamplesPointers> length)
		return false;
	if(ASC1_OrnamentsPointers> length)
		return false;



	j = ay_sys_getword(&module[ASC1_SamplesPointers]);
	if(j != 0x40)
		return false;
	j = ay_sys_getword(&module[ASC1_OrnamentsPointers]);
	if(j != 0x40)
		return false;



	j3 = 0;
	for(j1 = 0; j1 < header->ASC1_Number_Of_Positions; j1++)
		if(j3 < header->ASC1_Positions[j1])
			j3 = header->ASC1_Positions[j1];

	j = ay_sys_getword(&module[ASC1_PatternsPointers]);
	if(j != (j3 + 1) * 6)
		return false;



	j = ay_sys_getword(&module[ASC1_OrnamentsPointers + 0x40 - 2]);
	j += ASC1_OrnamentsPointers;
	while((j < length) && (j < 65535) && ((module[j] & 0x40) == 0))
		j += 2;

	if(j > 65534)
		return false;    

	if(j >= (length+512))
		return false;


	return true;
}


bool ASC0_Detect(unsigned char *module, unsigned long length)
{
	int j;
	int j1;
	unsigned char j3;
	//int delta;
	ASC0_File *header0 = (ASC0_File *)module;



	//if(length < 9)
	//    return false;

	// delta = ASC0_PatternsPointers - header0->ASC0_Number_Of_Positions;
	// if(delta < 9 || delta > 72)
	//    return false;

	//return 1;    

	if(ASC0_PatternsPointers> length)
		return false;
	if(ASC0_SamplesPointers> length)
		return false;
	if(ASC0_OrnamentsPointers> length)
		return false;



	j = ay_sys_getword(&module[ASC0_SamplesPointers]);
	if(j != 0x40)
		return false;
	j = ay_sys_getword(&module[ASC0_OrnamentsPointers]);
	if(j != 0x40)
		return false;



	j3 = 0;
	for(j1 = 0; j1 < header0->ASC0_Number_Of_Positions; j1++)
		if(j3 < header0->ASC0_Positions[j1])
			j3 = header0->ASC0_Positions[j1];

	j = ay_sys_getword(&module[ASC0_PatternsPointers]);
	if(j != (j3 + 1) * 6)
		return false;



	j = ay_sys_getword(&module[ASC0_OrnamentsPointers + 0x40 - 2]);
	j += ASC0_OrnamentsPointers;
	while((j < length) && (j < 65535) && ((module[j] & 0x40) == 0))
		j += 2;

	if(j > 65534)
		return false;    

	if(j >= (length+512))
		return false;

	pp=3;

	return true;
}




bool ASC_Detect(unsigned char *module, unsigned int length, AYSongInfo * s)
{
	pp =0;
	offset = 0;

	if(!ASC1_Detect(module, length))
		if(!ASC0_Detect(module, length))              
			return false;

	if (!pp)
		strcpy(s->player, "ASC Sound Master");	

	if (pp==3)
		strcpy(s->player, "AS0");        

	return true;

}





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








void PSG_GetInfo(AYSongInfo * info)
{
	unsigned int start;


	if (info->variant == 2)
	{
		memcpy(&info->len, &info->module[36], 2);
		strncpy(info->Name, &info->module[4], 32);

		return;
	}



	memcpy(&info->len, &info->module[4], 2);

	if (info->variant == 1)
		info->len /= 4;

	memcpy(&start, &info->module[6], 2);

	if (start == 58)
		FN(info);    
	else
	{
		strncpy(info->Name, &info->module[58], 32);
		strncpy(info->Autor, &info->module[58+32], 32);
	}            
}








///unsigned char c1, c2, c3;

char copy[16];

void ay_writeay(unsigned char reg, unsigned char val)
{
	if ((reg==0xff) && (val==0xff))
	{
		output(0xFFFD, 8); output(0xBFFD, copy[8]);  
		output(0xFFFD, 9); output(0xBFFD, copy[9]);  
		output(0xFFFD, 10); output(0xBFFD, copy[10]);  

		return;
	}

	copy[reg] = val;

	output(0xFFFD, reg);
	output(0xBFFD, val);
}



char ay_readay(unsigned char reg)
{
	return(copy[reg]);
}


typedef struct
{
	unsigned int SOURCE_POINTER;
	char mask;
	char buf;
	int r_r;
	unsigned int DECODER_BUFFER_POINTER;
	int addr ;
	unsigned char OUTPUT ;
	int NUM_B;
	char best_J;
	char best_I;
	char SSS;
	char SPACE;
	///17b
} global;

global g [13];







void PSG_Play(AYSongInfo * info)
{
	unsigned char i;
	int * a = (int *)16404;


	if (info->variant == 2)
	{
		for (i=0; i<20; i++)
		{
			info->pos = PSG2000_play(info->pos);
			delay (10);

			if ((*a)==1)				   			
				return;
			
			if ((*a)==2)				   			
			{
				tiho();
				return;
			}
		}

		return;
	}


	decode_lzss_step(g);

	if (g[9].OUTPUT & 32)
		ay_writeay(0, g[0].OUTPUT);

	if (g[9].OUTPUT & 64)
		ay_writeay(1, g[3].OUTPUT >> 4);

	if (g[9].OUTPUT & 128)
		ay_writeay(2, g[1].OUTPUT);    



	if (g[10].OUTPUT & 32)
		ay_writeay(3, g[4].OUTPUT >> 4);    

	if (g[10].OUTPUT & 64)
		ay_writeay(4, g[2].OUTPUT); 

	if (g[10].OUTPUT & 128)
		ay_writeay(5, g[4].OUTPUT%16);    



	if (g[12].OUTPUT & 1)
		ay_writeay(6, g[11].OUTPUT);    

	if (g[12].OUTPUT & 2)
		ay_writeay(7, g[5].OUTPUT); 

	if (g[12].OUTPUT & 4)
		ay_writeay(8, g[8].OUTPUT);    

	if (g[12].OUTPUT & 8)
		ay_writeay( 9, g[ 9].OUTPUT & 31);

	if (g[12].OUTPUT & 16)
		ay_writeay(10, g[10].OUTPUT & 31);    

	if (g[12].OUTPUT & 32)
		ay_writeay(11, g[6].OUTPUT); 

	if (g[12].OUTPUT & 64)
		ay_writeay(12, g[7].OUTPUT);  

	if (g[12].OUTPUT & 128)
		ay_writeay(13, g[3].OUTPUT%16);    

}


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





# define NUM_CH 13

void PSG_Init(AYSongInfo * info)
{
	unsigned char i;
	int F;
	int N; 



	if (info->variant == 2)
	{
		info->pos=D_16384 + 38;
		return;
	}


	memset (g, 0 , sizeof(global)*NUM_CH);

	for (i=0; i<NUM_CH; i++)
	{
		memcpy (&g[i].SOURCE_POINTER, &info->module[6 + i*4], 2);   
		g[i].SOURCE_POINTER+=D_16384;

		memcpy (&g[i].best_I, &info->module[8 + i*4], 1); 
		g[i].best_I /= 16;

		memcpy (&g[i].best_J, &info->module[8 + i*4], 1); 
		g[i].best_J %= 16;

		memcpy (&g[i].SPACE, &info->module[9 + i*4], 1); 

		F = ((1 << g[i].best_J) + 1);
		N = (1 << g[i].best_I);

		g[i].r_r = N - F;

		switch (g[i].best_I)
		{
		case 13:
			g[i].SSS = 31;
			break;

		case 12:
			g[i].SSS = 15;
			break;

		case 11:
			g[i].SSS = 7;
			break;

		case 10:
			g[i].SSS = 3;
			break;

		case 9:
			g[i].SSS = 1;
			break;

		case 8:
			g[i].SSS = 0;
			break;

		}
	}


	g[0].DECODER_BUFFER_POINTER = 49152;
	space_buf0(g[0].SPACE);
	space_buf1(g[0].DECODER_BUFFER_POINTER, (1 << g[0].best_I));

	for (i=1; i<=4; i++)
	{    
		g[i].DECODER_BUFFER_POINTER = g[i-1].DECODER_BUFFER_POINTER + (1 << g[i-1].best_I);
		space_buf0(g[i].SPACE);
		space_buf1(g[i].DECODER_BUFFER_POINTER, (1 << g[i].best_I));
	}

	for (i=5; i<=12; i++)
	{
		g[i].DECODER_BUFFER_POINTER = 49152 + (i-5)*2048; 
		space_buf0(g[i].SPACE);
		space_buf2(g[i].DECODER_BUFFER_POINTER, (1 << g[i].best_I)); 
	}
}







unsigned char X, Y;

void gotoxy(char x, char y)
{
	X=x;
	Y=y;

	if (X>31) X=31;
	if (Y>23) Y=23;
}


char putchar (char aa)
{
	if ((X>31) || (aa=='\n'))
	{
		X=0;
		Y++;

		if ((Y>23) || (aa=='\n')) return 1;
	}

	if ((aa >= 0x20) && (aa<=0x7f))
		Pr_Sym(Y*256+X, aa);
	else
		Pr_Sym(Y*256+X, '?');

	X++;



	return 0;
}



char pc_counter;
void printchar(char ** str, char c)
{
	char pcrv;


	char * str1 = (char *) str;

	if (str) 
	{
		str1[pc_counter++] = c;		
	}
	else 
	{
		pcrv = putchar((char)c);

		if (pcrv) return;
	}
}

int prints(char **out, char *string, int width, int pad)
{
	int pc = 0, padchar = ' ';
	int len;
	char *ptr;

	if (width > 0) {
		len = 0;

		for (ptr = string; *ptr; ++ptr) ++len;
		if (len >= width) width = 0;
		else width -= len;
		if (pad & PAD_ZERO) padchar = '0';
	}
	if (!(pad & PAD_RIGHT)) {
		for ( ; width > 0; --width) {
			printchar (out, padchar);
			++pc;
		}
	}
	for ( ; *string ; ++string) {
		printchar (out, *string);
		++pc;
	}
	for ( ; width > 0; --width) {
		printchar (out, padchar);
		++pc;
	}

	return pc;
}



int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)	
{
	char print_buf[PRINT_BUF_LEN];
	char *s;
	int t, neg = 0, pc = 0;
	unsigned int u = i;

	if (i == 0) {
		print_buf[0] = '0';
		print_buf[1] = '\0';
		return prints (out, print_buf, width, pad);
	}

	if (sg && b == 10 && i < 0) {
		neg = 1;
		u = -i;
	}

	s = print_buf + PRINT_BUF_LEN-1;
	*s = '\0';

	while (u) {
		t =  (u% b);


		if( t >= 10 )
			t += letbase - '0' - 10;
		*--s = t + '0';
		u = (u/ b);
	}

	if (neg) {
		if( width && (pad & PAD_ZERO) ) {
			printchar (out, '-');
			++pc;
			--width;
		}
		else {
			*--s = '-';
		}
	}

	return pc + prints (out, s, width, pad);
}


int print(char **out, const char *format, va_list args)
{
	int width, pad;
	int pc = 0;
	char scr[2];
	char *s;


	for (; *format != 0; ++format) {
		if (*format == '%') {
			++format;
			width = pad = 0;
			if (*format == '\0') break;
			if (*format == '%') goto out;
			if (*format == '-') {
				++format;
				pad = PAD_RIGHT;
			}
			while (*format == '0') {
				++format;
				pad |= PAD_ZERO;
			}
			for ( ; *format >= '0' && *format <= '9'; ++format) {
				width *= 10;
				width += *format - '0';
			}
			if( *format == 's' ) {
				s = (char *)va_arg( args, int );
				pc += prints (out, s?s:"(null)", width, pad);
				continue;
			}
			if( *format == 'd' ) {
				pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
				continue;
			}			

			if( *format == 'u' ) {
				pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
				continue;
			}

			if( *format == 'c' ) {
				scr[0] = (char)va_arg( args, int );
				scr[1] = '\0';
				pc += prints (out, scr, width, pad);
				continue;
			}			
		}
		else 
		{
out:
			printchar (out, *format);
			++pc;
		}
	}

	if (out) ((char *)out)[pc_counter] = '\0';

	va_end( args );
	return pc;
}

int printf(const char *format, ...)
{
	va_list args;

	va_start( args, format );
	return print( 0, format, args );
}

int sprintf(char *out, const char *format, ...)
{
	va_list args;

	pc_counter = 0;

	va_start( args, format );
	return print((char **)out, format, args );
}

vars_t * v;


void plays (void)
{

	//if (!ss)
	//	return;

	if (!ss->play)  
		return;

	ss->counter ++;

	if ((ss->counter<20) && (!v->flip_flop_p) && (v->play_mode!=1))
		return;

	switch (v->current_player)
	{
	case 0:
		PT1_Play(ss);
		break;

	case 1:
		PT2_Play(ss);
		break;

	case 2:
		PT3_Play(ss);
		break;

	case 3:
		STP_Play(ss);
		break;

	case 4:
		ASC_Play(ss);
		break;

	case 5:
		PSC_Play(ss);
		break;

	case 6:
		STC_Play(ss);
		break;

	case 7:
		SQT_Play(ss);
		break;      

	case 8:		
		if (ss->variant==1)
		{
			PSG_Play(ss); 	
			PSG_Play(ss);	
			PSG_Play(ss);
		}

		PSG_Play(ss);

		break;  
	}
}


char mode = 2;

void title1(char);

unsigned char II;

void Counters(void)
{
	plays();	
	II=1;	
}


void Copy_s(AYSongInfo *s, vars_t * pv)
{
	ss = s;
	v=pv;
}


void init (void)
{

	if (v->current_player == -1)
		return;

	Status("Initialising...", 0, 0, 1);

	switch (v->current_player)
	{
	case 0:
		PT1_Init(ss);
		break;

	case 1:
		PT2_Init(ss);
		break;

	case 2:
		PT3_Init(ss);
		break;

	case 3:
		STP_Init(ss);
		break;

	case 4:
		ASC_Init(ss);
		break;

	case 5:
		PSC_Init(ss);
		break;

	case 6:
		STC_Init(ss);
		break;

	case 7:
		SQT_Init(ss);
		break;

	case 8:
		PSG_Init(ss);
		break;

	}
}

void info (void)
{
	if (v->current_player == -1)
		return;

	Status("Get_info", 0, 0, 1);


	switch (v->current_player)
	{
	case 0:
		PT1_GetInfo(ss);
		break;

	case 1:
		PT2_GetInfo(ss);
		break;

	case 2:
		PT3_GetInfo(ss);
		break;

	case 3:
		STP_GetInfo(ss);    
		break;

	case 4:
		ASC_GetInfo(ss);    
		break;

	case 5:
		PSC_GetInfo(ss);    
		break;

	case 6:
		STC_GetInfo(ss);
		break;

	case 7:
		SQT_GetInfo(ss);   
		break;

	case 8:
		PSG_GetInfo(ss);   
		break;

	}

	ClearString (ss->Name, 32);
	ClearString (ss->Autor,32);

	title1(1);
	gotoxy (24, 0);
	printf ("%s", "--:--:--");	
}

void detect(void)
{

	char i;

	v->current_player = -1;


	for (i=0; i<NUM_PLAYERS; i++)
	{
		ss->module=(char *)D_16384; /// tut

		switch (i)
		{
		case 0:
			ss->detected=PT1_Detect(ss->module, ss->Length, ss);
			break;

		case 1:
			ss->detected=PT2_Detect(ss->module, ss->Length, ss);
			break;

		case 2:
			ss->detected=PT3_Detect(ss->module, ss->Length, ss);
			break;

		case 3:
			ss->detected=STP_Detect(ss->module, ss->Length, ss);
			break;

		case 4:
			ss->detected=ASC_Detect(ss->module, ss->Length, ss);
			break;

		case 5:
			ss->detected=PSC_Detect(ss->module, ss->Length, ss);  
			break;

		case 6:
			ss->detected=STC_Detect(ss->module, ss->Length, ss);
			break;

		case 7:
			ss->detected=SQT_Detect(ss->module, ss->Length, ss);
			break;

		case 8:
			ss->detected=PSG_Detect(ss->module, ss);
			break;
		}


		if (ss->detected)
		{
			v->current_player = i;
			return;
		}
	}



}




void title1(char force)
{   
	static char flipflop = 0;


	if (!ss)
		return;

	if (!ss->detected)                 
		return;   

	flipflop++;

	//gotoxy(0, 1);        

	if (flipflop&4)
	{
		if (mode == 1)
			return;

		mode  = 1;

		if (ss->Autor[0])
		{
			//printf ("%-32s", ss->Autor);
			if (ss->Name[0])
				printstring1(256, "                                ");
			printstring1(256, ss->Autor);
		}
	}


	if (!(flipflop&4) || force)
	{
		if (mode == 0)
			return;

		mode  = 0;

		if (ss->Name[0])
		{
			//printf ("%-32s", ss->Name);
			printstring1(256, "                                ");
			printstring1(256, ss->Name);
		}
	}    
}

void disker (char disk)
{
	di_();
	ss->counter = 0;
	mode = 2;
	read_d(disk, 0);
	ei_();
}

char state = 0;

void disker2(char disk1, char disk2)
{
	di_();
	ss->counter = 0;
	mode = 2;		        

	read_d(disk1, 3);
	read_d(disk2, 1);

	state = 0;			        
	ei_();
}




void o (void)
{

	unsigned char p7FFE;// -  Space...B 
	unsigned char pBFFE;// -  Enter...H 
	unsigned char pDFFE;// -  P...Y 
	unsigned char pEFFE;// -  0...6 
	unsigned char pF7FE;// -  1...5 
	unsigned char pFBFE;// -  Q...T 
	unsigned char pFDFE;// -  A...G 
	unsigned char pFEFE;// -  CS...V

	char first_d = 0;
	
	char sss = 0;
	char sec = 0;
	unsigned char min = 0;




	//ei_();

	while (1) 
	{

		if (!v->dntcounter)
		{
			p7FFE = input (0x7FFE);
			pBFFE = input (0xBFFE);
			pDFFE = input (0xDFFE);
			pEFFE = input (0xEFFE);

			pF7FE = input (0xF7FE);
			pFBFE = input (0xFBFE);
			pFDFE = input (0xFDFE);
			pFEFE = input (0xFEFE);  


			if (!(pDFFE&8))   // u
			{
				di_();
				tiho ();
				Shuffle();
				ei_();
				continue;
			}			

			if (!(p7FFE&2))
			{
				if (state == 0)
				{
					if (!(pFDFE&1))   // a  
					{
						first_d = 0;	
						state = 1;		
					}

					if (!(p7FFE&16))  // b
					{
						first_d = 1;
						state = 1;
					}

					if (!(pFEFE&8))   // c
					{
						first_d = 2;       
						state = 1;
					}

					if (!(pFDFE&4))   // d			        
					{
						first_d = 3;
						state = 1;
					}			       
				}

				if (state == 1)
				{
					if ((!(pFDFE& 1)) && (first_d != 0))  // +a  
						disker2(first_d, 0);

					if ((!(p7FFE&16)) && (first_d != 1))  // +b			       
						disker2(first_d, 1);			            

					if ((!(pFEFE& 8)) && (first_d != 2))  // +c			       
						disker2(first_d, 2);		            

					if ((!(pFDFE& 4)) && (first_d != 3))  // +d			        
						disker2(first_d, 3);		                     			   		        			        
				}

				continue;
			}                        
			else
				state = 0;


			if (!(pFDFE&1))   // a  
			{
				disker(0);
				continue;
			}

			if (!(p7FFE&16))  // b
			{
				disker(1);
				continue;
			}  

			if (!(pFEFE&8))   // c
			{
				disker(2);
				continue;
			}	        

			if (!(pFDFE&4))   // d			        
			{
				disker(3);
				continue;
			}



			if (!(pFBFE&8)) // r
			{			      
				di_();
				ss->counter = 0;
				mode = 2;
				Getnfiles();
				ei_();
				continue;   
			}			


			if (!(pBFFE&1))   // Enter
			{
				di_();
				ss->counter = 0;
				mode = 2;
				play(v->tek_file);
				ei_();
				continue;
			}


			if ( (!(pFEFE&1)) && (!(pEFFE&16)) )   // Down
			{
				di_();			
				curcor(1);	
				ei_();
				continue;
			}


			if ( (!(pFEFE&1)) && (!(pEFFE&8)) )   // Up
			{
				di_();
				curcor(-1);	
				ei_();
				continue;
			}

			if ( (!(pFEFE&1)) && (!(pEFFE&4)) )   // Right
			{
				di_();
				curcor(num_l);
				ei_();
				continue;	
			}

			if ( (!(pFEFE&1)) && (!(pF7FE&16)) )   // Left
			{
				di_();
				curcor(0-num_l);	
				ei_();
				continue;
			}

			if (!(pDFFE&1))   // p
			{
				di_();

				if (ss->play)
					stop();
				else  
					resume();

				v->dntcounter=5;

				ei_();

				continue;
			}



			if ( (!(p7FFE&8)) ||  (!(p7FFE&1)))   // n, space
			{
				di_();
				ss->counter = 0;
				v->depth =0;
				mode = 2;
				next();
				ei_();
				continue;
			}

			if (!(pBFFE&2))   // l
			{		
				di_();	
				l();
				ei_();
				continue;
			}

			if (!(pDFFE&2))   // o  
			{
				di_();			        
				sort();
				ei_();
				continue;
			}

			if ((!(pFEFE&1)) && (!(pEFFE&1)))   // back
			{	
				di_();
				v->depth =0; 
				mode = 2;    
				back();
				ei_();
				continue;
			}

		}


		if ((ss->counter >= ss->len) && (ss->play))  
		{
			if (v->play_mode == 1)
			{
				di_();
				mode = 2;
				re();								
				ei_();
			}  
			else  	  
				if (!v->play_mode)
				{	
					di_();			      
					ss->counter = 0;	
					v->depth =0;	
					mode = 2;  
					next();
					ei_();
				}
				else
					if (v->play_mode == 2)
					{
						ss->counter = 0;	

						v->flip_flop_p = 1 - v->flip_flop_p;

						if (!v->flip_flop_p)
						{ 	
							di_();						      
							v->depth = 0; 
							mode = 2;
							next();							
							ei_();
						}
						else
						{
							di_();
							mode = 2;
							re();	
							ei_();											
						}
					}
		}


		
		if (II)
		{
			if (v->dntcounter)  v->dntcounter--;

			if (ss->counter<2)
			{
				min = 0;
				sec = 1;
				sss = 0;
			}

			sss++;

			if (sss==50)
			{
				sss=0;

				if (!ss->slow)
				{
					di_();
					title1(0);
					ei_();
				}
				
				if ((ss->slow)<2)
				{
					di_();
					clock ();	
					ei_();
				}
			}

			if (ss->play) 
			{	
				if (!sss)
				{
					if ((ss->slow)<3)
					{
						di_();
						printstring1(512, d2s(min));
						printstring1(512+3, d2s(sec));	
						ei_();
					}

					sec++;
					
					if (sec==60)
					{ 
						sec = 0;
						min++;
					}	
				}
			}

			II=0;
		}
		
	}
}


