#include <sys/bios.h>
#include <sys/service.h>
#include <stdlib.h>
#include <sys/il_sound.h>


#define DIR_RD 0
#define DIR_RU 1
#define DIR_LD 2
#define DIR_LU 3

unsigned short bran[]={
	0,0,0,0,0,0,0,0
};

unsigned short ball[]={
	0x1818,0x3c3c,0x6666,0xc3c3,
	0xc3c3,0x6666,0x3c3c,0x1818
};

unsigned short bar[]={
	0x0f0f,0x0f0f,0x0f0f,0x0f0f,
	0x0f0f,0x0f0f,0x0f0f,0x0f0f
};

unsigned short bl1[]={
	0x0000,0xfefe,0xfefe,0xfe06,
	0xfe06,0xfe06,0xfe06,0xfe06
};

unsigned short bl2[]={
	0x7f60,0x7f60,0x7f60,0x7f60,
	0x7f60,0x7f60,0x7f60,0x7f60
};

static int bar_x=0,bar_y=60,ball_x=150,ball_y=68;
static int dir=DIR_RD;

static int dx[4][7]={
	1,1,1,1,1,1,0,
	1,1,1,1,1,1,1,
	1,1,1,1,1,1,1,
	1,1,1,1,1,0,0
};
static int dy[4][7]={
	0,0,0,0,1,1,1,
	0,0,1,1,1,1,1,
	0,1,1,1,1,1,1,
	0,0,0,1,1,1,1
};

SoundIL soundIL;
extern BYTE *_heap;

struct block{
	int life;
	int ls;
	int rs;
	int ts;
	int bs;
	int bx;
	int by;
} blk[18];

void b_init(){
	int ib,jb,b0,bx,by,bc;
	
	for(ib=0;ib<6;ib++){
	for(jb=0;jb<3;jb++){
		blk[jb*6+ib].life=1;
		blk[jb*6+ib].ls=0;
		blk[jb*6+ib].rs=0;
		blk[jb*6+ib].ts=0;
		blk[jb*6+ib].bs=0;
		if(jb==0) blk[ib].bs=1;
		if(jb==2) blk[ib+12].ts=1;
		
		b0=jb*36+ib*6+4;
		bx=160+jb*16;
		by=ib*24;
		blk[jb*6+ib].bx=bx;
		blk[jb*6+ib].by=by;
		bc=0x0200*jb;
		sprite_set_char(b0, 0x6803+bc);
		sprite_set_char(b0+1, 0x2804+bc);
		sprite_set_char(b0+2, 0xe803+bc);
		sprite_set_char(b0+3, 0x2803+bc);
		sprite_set_char(b0+4, 0x6804+bc);
		sprite_set_char(b0+5, 0xa803+bc);
    	sprite_set_location(b0,bx,by);
    	sprite_set_location(b0+1,bx,by+8);
    	sprite_set_location(b0+2,bx,by+16);
    	sprite_set_location(b0+3,bx+8,by);
    	sprite_set_location(b0+4,bx+8,by+8);
    	sprite_set_location(b0+5,bx+8,by+16);
	}
	}
    sprite_set_range(0, b0+6);
}

void opening(){
	screen_fill_char(SCREEN1,0,0,32,32,0);
	se_play(_heap,0);
	screen_fill_char(SCREEN2,0,0,32,32,0);
	
	sprite_set_location(0,0,200);
	sprite_set_location(1,0,200);
	sprite_set_location(2,0,200);
	sprite_set_location(3,0,200);
	
	sys_wait(150);
	
	
	
}

void s_init(){
	if(open_sound_il(&soundIL) != E_FS_SUCCESS){
		return;
	}
	sounddrv_init();
	sound_open();
	parse_mml(_heap,"CDFF##E##AB##G/",4);
}




void g_init(){

    display_control(DCM_SCR1|DCM_SPR|DCM_SCR2|DCM_SCR2_WIN_INSIDE );

	font_set_colordata(0,1,bran);
	font_set_colordata(1,1,ball);
	font_set_colordata(2,1,bar);
	font_set_colordata(3,1,bl1);
	font_set_colordata(4,1,bl2);
    
	palette_set_color(11,0x7120);
	palette_set_color(12,0x5120);
	palette_set_color(13,0x5220);
	palette_set_color(14,0x5320);
	
	lcd_set_color(0x6420,0xfca8);
	
    sprite_set_char(0, 0x2601);
    sprite_set_char(1, 0x2802);
    sprite_set_char(2, 0x2802);
    sprite_set_char(3, 0x2802);
    
    screen_set_scroll(SCREEN1,0,0);
    screen_set_scroll(SCREEN2,0,0);
    
    /*text_set_screen(SCREEN1);*/

    text_window_init(0,17,28,1,300);
}

void ty_conv(unsigned char far *dat){
	unsigned char dum[8];
	int i,j,mask1,mask2;
	for(i=0;i<8;i++){
		dum[i]=*(dat+i);
	}
	mask1=0x80;
	for(i=0;i<8;i++){
		*(dat+i)=0;
		mask2=0x80;
		for(j=8;j>0;j--){
			if(dum[j-1]&mask1){
				*(dat+i)+=mask2;
			}
			mask2/=2;
		}
		mask1/=2;
	}
}

void c_init(){

    unsigned char data[8];
    int i,code=0x0030;

    for(i=0;i<10;i++){
		text_get_fontdata(code+i, data);
		ty_conv(data);
		font_set_monodata(230+i, 1, data);
    }
}

void move_bar(){
	int kc;
	kc=key_press_check();
	if(kc==KEY_START){
		bios_exit();
	}
	if((kc & 0x00f0) != 0){
		if(bar_y < 119) bar_y++;
	}
	if((kc & 0x0f00) != 0){
		if(bar_y > 0) bar_y--;
	}

    sprite_set_location(1,bar_x,bar_y);
    sprite_set_location(2,bar_x,bar_y+8);
    sprite_set_location(3,bar_x,bar_y+16);

}

void side_check(int bi){
	if((bi%6)!=0){
		blk[bi-1].rs=1;
	}
	if((bi%6)!=5){
		blk[bi+1].ls=1;
	}
	if((bi/6)!=0){
		blk[bi-6].ts=1;
	}
	if((bi/6)!=2){
		blk[bi+6].bs=1;
	}
}

void next_ball(){
	static int ball_count=1;
	if(ball_count >2){
		se_play(_heap,0);
		sys_wait(150);
		bios_exit();
	}

	ball_x=150;
	ball_y=68;
	dir=DIR_RD;
	sprite_set_location(0,ball_x,ball_y);
	ball_count++;

}


void block_check(){
	int ib,jb,bc,b0,kb;
	
	for(ib=0;ib<6;ib++){
	for(jb=0;jb<3;jb++){
		bc=jb*6+ib;
		if(blk[bc].life==1){
			if((blk[bc].rs==1)&&((ball_y<=(blk[bc].by+24))&&(ball_y>=(blk[bc].by+22)))&&
			((ball_x<=(blk[bc].bx+24))&&(ball_x>=(blk[bc].bx-8)))&&
			((dir==DIR_LD)||(dir==DIR_LU))){
				if(dir==DIR_LU) dir=DIR_RU;
				else dir=DIR_RD;
				se_play(_heap,3);
				blk[bc].life=0 ;
				b0=jb*36+ib*6+4;
				for(kb=0;kb<6;kb++){
    				sprite_set_location(b0+kb,0,200);
    			}
    			side_check(bc);
				return;
			}
			if((blk[bc].ls==1)&&((ball_y>=(blk[bc].by))&&(ball_y<=(blk[bc].by+2)))&&
			((ball_x<=(blk[bc].bx+24))&&(ball_x>=(blk[bc].bx-8)))&&
			((dir==DIR_RD)||(dir==DIR_RU))){
				if(dir==DIR_RD) dir=DIR_LD;
				else dir=DIR_LU;
				se_play(_heap,3);
				blk[bc].life=0 ;
				b0=jb*36+ib*6+4;
				for(kb=0;kb<6;kb++){
    				sprite_set_location(b0+kb,0,200);
    			}
    			side_check(bc);
				return;
			}
			if((blk[bc].bs==1)&&((ball_x>=(blk[bc].bx-8))&&(ball_x<=(blk[bc].bx-6)))&&
			(ball_y<=(blk[bc].by+20))&&(ball_y>=(blk[bc].by-4))&&
			((dir==DIR_LU)||(dir==DIR_RU))){
				if(dir==DIR_RU) dir=DIR_RD;
				else dir=DIR_LD;
				se_play(_heap,3);
				blk[bc].life=0 ;
				b0=jb*36+ib*6+4;
				for(kb=0;kb<6;kb++){
    				sprite_set_location(b0+kb,0,200);
    			}
    			side_check(bc);
				return;
			}
			if((blk[bc].ts==1)&&((ball_x>=(blk[bc].bx+14))&&(ball_x<=(blk[bc].bx+16)))&&
			(ball_y<=(blk[bc].by+20))&&(ball_y>=(blk[bc].by-4))&&
			((dir==DIR_LD)||(dir==DIR_RD))){
				if(dir==DIR_RD) dir=DIR_RU;
				else dir=DIR_LU;
				se_play(_heap,3);
				blk[bc].life=0 ;
				b0=jb*36+ib*6+4;
				for(kb=0;kb<6;kb++){
    				sprite_set_location(b0+kb,0,200);
    			}
    			side_check(bc);
				return;
			}
			
			
			
			
		}
	}
	}
}
void direction_change(){

	if((ball_y <= 0) && ((dir==DIR_LD) || (dir==DIR_LU))){
		if(dir==DIR_LD){
			dir=DIR_RD;
		}
		else{
			dir=DIR_RU;
		}
		se_play(_heap,1);
		return;
	}
	if((ball_y >= 136) && ((dir==DIR_RD) || (dir==DIR_RU))){
		if(dir==DIR_RD){
			dir=DIR_LD;
		}
		else{
			dir=DIR_LU;
		}
		se_play(_heap,1);
		return;
	}
	if((ball_x >= 216) && ((dir==DIR_RU) || (dir==DIR_LU))){
		if(dir==DIR_RU){
			dir=DIR_RD;
		}
		else{
			dir=DIR_LD;
		}
		se_play(_heap,1);
		return;
	}
	if(((ball_x == 8) || (ball_x == 7) || (ball_x == 6)) &&
		((dir==DIR_RD) || (dir==DIR_LD)) && (((ball_y > (bar_y-8)) &&
		(ball_y < (bar_y+24))))){
		if(dir==DIR_RD){
			dir=DIR_RU;
		}
		else{
			dir=DIR_LU;
		}
		se_play(_heap,1);
		return;
	}
	block_check();

}
void location_ball(){
	static int step=0,dirdir=1;
	int cc;
	
	if(step > 3){
		step=0;
	}
	switch (dir) {
		case DIR_RU:
			ball_x=ball_x+dx[step][dirdir];
			ball_y=ball_y+dy[step][dirdir];
	    	break;
		case DIR_RD:
			ball_x=ball_x-dx[step][dirdir];
			ball_y=ball_y+dy[step][dirdir];
	    	break;
		case DIR_LU:
			ball_x=ball_x+dx[step][dirdir];
			ball_y=ball_y-dy[step][dirdir];
	    	break;
		case DIR_LD:
			ball_x=ball_x-dx[step][dirdir];
			ball_y=ball_y-dy[step][dirdir];
	    	break;
		default:
	    	break;
	}
	if((ball_x == 8) || (ball_x == 7) || (ball_x == 6)){
		if(dir == DIR_LD){
			switch (cc=(ball_y+8-bar_y)/8) {
				case 0:
					dirdir=dirdir+2;
	    			break;
				case 1:
					dirdir++;
	    			break;
				case 2:
	    			break;
				case 3:
					dirdir--;
	    			break;
				case 4:
					dirdir=dirdir-2;
	    			break;
				default:
	    			break;
	    	}
	    }
		if(dir == DIR_RD){
			switch (cc=(ball_y+8-bar_y)/8) {
				case 0:
					dirdir=dirdir-2;
	    			break;
				case 1:
					dirdir--;
	    			break;
				case 2:
	    			break;
				case 3:
					dirdir++;
	    			break;
				case 4:
					dirdir=dirdir+2;
	    			break;
				default:
	    			break;
	    	}
	    }
		if(dirdir > 6){
			dirdir=6;
		}
		if(dirdir < 0){
			dirdir=1;
		}
		text_put_numeric(10,0,3,NUM_SIGNED,bar_y);
		text_put_numeric(15,0,3,NUM_SIGNED,ball_y);
		text_put_numeric(20,0,3,NUM_SIGNED,cc);
		/*key_wait();*/
	}
	text_put_numeric(0,0,3,NUM_SIGNED,dirdir);
	step++;
}

void move_ball(){
	
	direction_change();
	location_ball();
    sprite_set_location(0,ball_x,ball_y);

	if(ball_x <= 0){
		se_play(_heap,2);
		sys_wait(150);
		next_ball();
		/*bios_exit();*/
	}
}


void draw_number3(int screen,int x,int y,int tate_yoko,int number){
	int a1,a2,a3;
	a1=(number/100)%10+230;
	a2=(number/10)%10+230;
	a3=number%10+230;
	if(tate_yoko==0){
		screen_set_char(screen, x, y, 1, 1, &a1);
		screen_set_char(screen, x+1, y, 1, 1, &a2);
		screen_set_char(screen, x+2, y, 1, 1, &a3);
	}
	else{
		screen_set_char(screen, x, y, 1, 1, &a1);
		screen_set_char(screen, x, y+1, 1, 1, &a2);
		screen_set_char(screen, x, y+2, 1, 1, &a3);
	}
}

void score(){
	int data,ib,jb,end_life;
	data=0;
	end_life=0;
	for(ib=0;ib<6;ib++){
	for(jb=0;jb<3;jb++){
		data+=(blk[jb*6+ib].life)*10*(jb+1);
		end_life+=blk[jb*6+ib].life;
	}
	}
	data=360-data;
	draw_number3(SCREEN2,27,14,1,data);
	if(end_life==0){
		se_play(_heap,0);
		sys_wait(150);
		bios_exit();
	}
}	
void main(int argc, char near *argv[]) {
	unsigned int i=0;	
	g_init();
	s_init();
	b_init();
	c_init();
	opening();
	while(1){
		i++;
		if(1){
			move_bar();
		}
		if(2){
			move_ball();
		}
		if(i%10 == 0){
			score();
		}
    	if(i%2 == 0) {
    		sys_wait(1);
    	}
    }
}

