
//ֽ

//ʼ汾: 201212 (ڹҼѧԺ ƽֲ)

//޸: 2013720 ӷЧ,֮ϿһСʱ

//޸: 2014629 ѲͨΪ̬ɨ, ֶ֧ͨ, ʽ

//޸: 20141125
//ʵƵ, һָŶͨ, һʼ뵽еͨϵͬһ, 
//ÿֽͨ(뵽), ǻǰĿǰĸֿͨ, Ȼڼһۺϵ,
//ͨĿ, Լͨͷ(Ҳ).
//Ŀǰʱ޷ڳָһΪ(ֻ泣), дһʱĺ,
//÷һ, ʵռͨͷһ, Ȼ󷵻.
//ǵһҲû!!!
//ǸͷѾֹ,  иڶ, ú׼...
//ղźȻͷԭ:
//ĳ:
//void play0( [int16*?] p )
//Ӧ:
//void play0( [->int16*?] p )

//ע: 201558
//һ, Ų, һž... Ҳԭ, 
// ϲ base code ֮, , ϸûⰡ.
//Ūһ, ȻоϤ! , Ƕջ!!! ǸϽ OS еĶջռ
// 200 Ϊ 300, һԻǲ! Ȼ侲, , ж϶ջ, ÿжϺ
//ջߴ̫С... ҵǸؼ, 100ĳ200, һOK!

unit music
{
	//[i] var_uint8 OS_time;
	uint8 OS_time;

	//[i] var_uint8 OS_EventFlag;
	public uint8 OS_EventFlag;
	//[i] event trig1_event;
	//[i] event trig2_event;

	//[i] var_int32 CurrentTone1;
	public int32 CurrentTone1;
	//[i] var_int32 CurrentTone2;
	public int32 CurrentTone2;
	
	const int8 NUMBER = 4;
	[bool*NUMBER] is_play;
	[uint8*NUMBER] breakTime;
	[bool*NUMBER] liaison;
	[int8*NUMBER] volume;
	[uint8*NUMBER] tick_ms_count;
	[uint8*NUMBER] tick_ms;
	[uint8*NUMBER] time;
	[uint16*NUMBER] index;
	[->[uint8*?]*NUMBER] music_list;
	
	//[i] linkinterface_tone tone;
	link unit tone {}
	
	int8 Index;
	bool Break;
	
	//---------------------------------------------------
	//[i] function_void OS_init;
	void OS_init()
	{
		OS_time = 1;
		OS_EventFlag = 0;
		
		for( int8 i = 0; i < NUMBER; i + 1 ) {
			is_play[i] = false;
			tick_ms_count[i] = 0;
			tick_ms[i] = 20;
			index[i] = 0;
			time[i] = 0;
			volume[i] = 127;
			liaison[i] = false;
			breakTime[i] = 0;
		}
		Index = 0;
		Break = false;
	}
	//---------------------------------------------------
	//[i] function_void play0 music;
	void play0( [->int16*?] p )
	{
		stop();
		
		->[int16*?] pn -> p;
		int16 n = pn[0];
		for( int16 i = 0; i < n; i + 1 ) {
			play( i, p[i+1] );
		}
	}
	//---------------------------------------------------
	//[i] function_void stop;
	void stop()
	{
		tone.stop( 0, 0 );
		tone.stop( 1, 0 );
		is_play[0] = false;
		is_play[1] = false;
	}
	//---------------------------------------------------
	void play( int16 c, [uint8*?] p )
	{
		volume[c] = 127;
		tick_ms_count[c] = 0;
		tick_ms[c] = 20;
		time[c] = 1;
		music_list[c] -> p;
		index[c] = 0;
		is_play[c] = true;
	}
	//---------------------------------------------------
	//[i] function_void OS_run;
	void OS_run()
	{
		if( Break ) { Break = false; goto B; }
		for( Index = 0; Index < NUMBER; Index + 1 ) {
			if( is_play[Index] ) {
				//Сʱֵʱ
				tick_ms_count[Index] + 1;
				if( tick_ms_count[Index] == tick_ms[Index] ) {
					tick_ms_count[Index] = 0;
					//ʱֵݼ,жʱֵǷ񵽴
					time[Index] - 1;
					if( time[Index] == 0 ) {
						B:
						if( tone.isBusy ) {
							Break = true;
							//tone.isNeed = true;
							return;
						}
						//tone.isNeed = false;
						is_play[Index] = decode(
							Index + 1,
							music_list[Index],
							index[Index],
							time[Index],
							tick_ms[Index],
							volume[Index],
							liaison[Index],
							breakTime[Index]
						);
					}
				}
			}
		}
	}
	//---------------------------------------------------
	//ݽ
	//ִָֺ
	bool decode(
		int8 c,
		[uint8*?] music_list0,
		uint16 index0*,
		uint8 time0*,
		uint8 tick_ms0*,
		int8 vol*,
		bool liaison0*,
		uint8 breakTime0* )
	{
		bool is_play0 = true;
		forever {
			uint8 d = music_list0[index0];
			if( d == 0xFF || d == 0 ) {
				is_play0 = false;
				tone.stop( c, 0 );
				break;
			}
			if( d == 0xFD ) {
				index0 + 1;
				continue;
			}
			if( d == 0xFA ) {
				index0 + 1;
				d = music_list0[index0];
				tick_ms0 = tone.switch_time( d );
				index0 + 1;
				continue;
			}
			if( d == 0xF9 ) {
				index0 + 2;
				continue;
			}
			if( d == 0xF6 ) {
				index0 + 1;
				vol = (int)music_list0[index0];
				index0 + 1;
				continue;
			}
			if( d == 0xF8 ) {
				index0 + 1;
				//X = music_list0 index0;  //ÿСʱֵ
				index0 + 1;
				//X = music_list0 index0;  //
				index0 + 1;
				continue;
			}
			if( d == 0xFE ) {
				if( !liaison0 ) {
					if( breakTime0 == 0 ) tone.stop( c, 0 );
					if( breakTime0 < 1 ) {
						//breakTime0 + 1;
						//time0 = 1;
						//break;
					} else {
						breakTime0 = 0;
					}
				}
				index0 + 1;
				d = music_list0[index0];
				if( d != 0 ) {
					tone.play( c, (int)d, vol );
					if( c == 1 ) {
						OS_EventFlag.0(bit) = 1;
						CurrentTone1 = (int)d;
					}
					if( c == 2 ) {
						OS_EventFlag.1(bit) = 1;
						CurrentTone2 = (int)d;
					}
				} else {
					tone.stop( c, 0 );
				}
				index0 + 1;
				continue;
			}
			if( d == 0xFC ) {
				index0 + 1;
				d = music_list0[index0];
				time0 = d;
				index0 + 1;
				break;
			}
			if( d == 0xF5 ) {
				liaison0 = true;
				index0 + 1;
				continue;
			}
			if( d == 0xF4 ) {
				liaison0 = false;
				index0 + 1;
				continue;
			}
			break;
		}
		return is_play0;
	}
}




