/*---------------------------------------------------------------------------
 * BMPSAVER
 * bsscr_u.c (2000/07/19 - 2000/12/16)
 * Copyright (c) 2000, Kazuhide Hatsuyama, All rights reserved.
 *   mail    : hat@lares.dti.ne.jp
 *   HomePage: http://www.lares.dti.ne.jp/~hat/
 *---------------------------------------------------------------------------*/

#define BIOS_INLINE

#include <sys/bios.h>

#include "bsscr_d.h"
#include "bmpsaver.h"

#define INVALID_COLOR	255
#define MAKE_COLOR(pal_no, col_no) \
		((bs_info.lcd>>(((bs_info.palette[pal_no]>>(col_no<<2))&7)<<2))&15)
#define GET_COLOR(font, x, y) \
	(((font[y]>>(14-x))&2)+((font[y]>>(7-x))&1))

/*--------------------------------------------------------------------*/
/* スクリーンの色を取得 */

#define bs_screen_get_screen_color(_scr, _x, _y) \
{ \
	int cx, cy, ox, oy; \
	int char_no, palette_no, hm, vm; \
	int col_no; \
 \
	cx = (_x&255)/8; \
	cy = (_y&255)/8; \
	ox = (_x&255)%8; \
	oy = (_y&255)%8; \
 \
	screen_get_char(_scr, cx, cy, 1, 1, &ch); \
	char_no		= (ch    )&0x1ff; \
	palette_no	= (ch>> 9)&15; \
	hm			= (ch>>14)&1; \
	vm			= (ch>>15)&1; \
 \
	if(hm) ox = 7-ox; \
	if(vm) oy = 7-oy; \
 \
	/* フォントデータから色を取得 */ \
	font_get_data(char_no, 1, &font); \
	col_no = GET_COLOR(font, ox, oy); \
 \
	/* パレット4-7 or 12-15 のカラー番号 0 は透明色 */ \
	if((palette_no&4)==0 || col_no!=0) { \
 		return MAKE_COLOR(palette_no, col_no); \
	} \
}

/*--------------------------------------------------------------------*/
/* 画面情報を取得 */
void bs_screen_init_info()
{
	unsigned long lval;
	unsigned short sval;
	int i, n;

	/* 画面 */
	bs_info.disp_ctrl = display_status();
	/* 色 */
	bs_info.lcd = lcd_get_color();
	for(i=0;i<16;i++) {
		bs_info.palette[i] = palette_get_color(i);
	}
	/* ボーダーカラー */
	bs_info.border_color = (bs_info.lcd>>((bs_info.disp_ctrl>>6)&0x1c))&15;
	/* スクロール */
	lval = screen_get_scroll(SCREEN1);
	bs_info.scr1_y = (lval>>8);
	bs_info.scr1_x = (lval   )&0xff;
	lval = screen_get_scroll(SCREEN2);
	bs_info.scr2_y = (lval>>8);
	bs_info.scr2_x = (lval   )&0xff;
	/* スプライトクリッピングウインドウ */
	lval = sprite_get_window();
	bs_info.sp_clip_h = (lval>>24);
	bs_info.sp_clip_w = (lval>>16)&0xff;
	bs_info.sp_clip_y = (lval>> 8)&0xff;
	bs_info.sp_clip_x = (lval    )&0xff;
	/* SCREEN2 クリッピングウインドウ */
	lval = screen2_get_window();
	bs_info.scr2_clip_h = (lval>>24);
	bs_info.scr2_clip_w = (lval>>16)&0xff;
	bs_info.scr2_clip_y = (lval>> 8)&0xff;
	bs_info.scr2_clip_x = (lval    )&0xff;
	/* スプライト情報 */
	if(bs_info.disp_ctrl&DCM_SPR) {
		n = bs_info.sp_end;
		for(i=bs_info.sp_start;i<n;i++) {
			sval = sprite_get_location(i);
			bs_info.sp[i].y = (sval>>8)&0xff;
			bs_info.sp[i].x = (sval   )&0xff;
			sval = sprite_get_char(i);
			bs_info.sp[i].ch			= (sval)&0x01ff;
			bs_info.sp[i].palette		= ((sval>> 9)&7)+8;
			bs_info.sp[i].ct			= (sval>>12)&1;
			bs_info.sp[i].pr			= (sval>>13)&1;
			bs_info.sp[i].hm			= (sval>>14)&1;
			bs_info.sp[i].vm			= (sval>>15)&1;
		}
	}
}

/*--------------------------------------------------------------------*/
/* ピクセルの色を取得 */
unsigned short bs_screen_get_color(int x, int y)
{
	static unsigned short font[8];
	static unsigned short ch; 
	int sp_clip, scr2_clip;
	int scr2_win;
	unsigned short sp_color;
	int xx, yy;
	int col_no;
	int i;

	/* クリップ領域外か？ */
	sp_clip = 0;
	if(x<bs_info.sp_clip_x || x>=bs_info.sp_clip_x+bs_info.sp_clip_w ||
	   y<bs_info.sp_clip_y || y>=bs_info.sp_clip_y+bs_info.sp_clip_h)
	{
		sp_clip = 1;
	}
	scr2_clip = 0;
	if(x<bs_info.scr2_clip_x || x>=bs_info.scr2_clip_x+bs_info.scr2_clip_w ||
	   y<bs_info.scr2_clip_y || y>=bs_info.scr2_clip_y+bs_info.scr2_clip_h)
	{
		scr2_clip = 1;
	}

	/*----- スプライト の色を取得 ----------------*/
	sp_color = INVALID_COLOR;
	if(bs_info.target&KH_BS_SPRITE && bs_info.disp_ctrl&DCM_SPR)
	{
		for(i=bs_info.sp_start;i<bs_info.sp_end;i++)
		{
			/* 座標(x, y)にスプライトがあるか？ */
			if((x<bs_info.sp[i].x || x>=bs_info.sp[i].x+8 ||
			   y<bs_info.sp[i].y || y>=bs_info.sp[i].y+8) &&
			   (x>=8 || x+256>=bs_info.sp[i].x+8)) continue;

			/* クリップウインドウ内か？ */
			if(bs_info.disp_ctrl&DCM_SPR_WIN && sp_clip!=bs_info.sp[i].ct) continue;

			/* まだスプライトの色が決まっていない場合 */
			if(bs_info.sp[i].pr || sp_color==INVALID_COLOR)
			{
				xx = (x-bs_info.sp[i].x)%8;
				yy = (y-bs_info.sp[i].y)%8;
				if(bs_info.sp[i].hm) xx = 7-xx;
				if(bs_info.sp[i].vm) yy = 7-yy;
				/* フォントデータから色を取得 */
				font_get_data(bs_info.sp[i].ch, 1, &font);
				col_no = GET_COLOR(font, xx, yy);
				/* パレット4-7 or 12-15 のカラー番号 0 は透明色 */
				if((bs_info.sp[i].palette&4)==0 || col_no!=0)
				{
					sp_color = MAKE_COLOR(bs_info.sp[i].palette, col_no);
					if(bs_info.sp[i].pr) return sp_color;
				}
			}
		}
	}

	/*----- SCREEN2 の色を取得 -------------------*/
	scr2_win = (bs_info.disp_ctrl>>4)&3;
	if(bs_info.target&KH_BS_SCREEN2 && bs_info.disp_ctrl&DCM_SCR2 &&
	   (!(scr2_win&2) || (scr2_win&1)==scr2_clip))
	{
		bs_screen_get_screen_color(SCREEN2, x+bs_info.scr2_x, y+bs_info.scr2_y);
	}

	/*----- SCREEN2が透明 かつ SCREEN2の下のスプライト有り -----*/
	if(sp_color!=INVALID_COLOR) return sp_color;

	/*----- SCREEN1 の色を取得 -------------------*/
	if(bs_info.target&KH_BS_SCREEN1 && bs_info.disp_ctrl&DCM_SCR1)
	{
		bs_screen_get_screen_color(SCREEN1, x+bs_info.scr1_x, y+bs_info.scr1_y);
	}

	/*----- 結局透明色ならBorderカラーを取得 -----*/
	return bs_info.border_color;
}

