/*	
 *	clipt18i.h
 *
 *	P/ECE TMS9918(A) Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Tue Jan 4 20:23:00 JST 2005 Naoyuki Sawa
 *	- 作成開始。
 */

/****************************************************************************
 *
 ****************************************************************************/

#ifdef TMS9918_SPRITE_IMPLEMENT

/* * スプライト描画ルーチンの共通の定義です。
 * - スプライト描画ルーチンは {8x8標準、8x8拡大、16x16標準、16x16拡大} の四種類ありますが、内容はほとんど同じです。
 *   管理を簡単にするために、このインクルードファイルで共通の定義を行い、インクルードして複製を作ることにしました。
 * - clipt18.cまたはframt18.cからインクルードして使います。
 *   ほとんどのゲームは16x16標準モードだけを利用しているので、高速RAMに転送するのは16x16標準版だけでいいと思います。
 *   16x16標準版の定義のみframt18.cにインクルードし、その他の3種類はclipt18.cにインクルードしてください。
 */

#define SIZE_MAG (SIZE * MAG)
#if(MAG == 1)
#define PSET do { *p = c; } while(0)
#else /*MAG == 1*/
#define PSET do { p[0] = p[1] = p[256] = p[257] = c; } while(0)
#endif /*MAG == 1*/

	unsigned char* reg  = tms9918->reg;
	unsigned char* vram = tms9918->vram;
	//
	int sprite;
	int x;
	int y;
	int code;
	int c;
	int side; /* SIZE=16時のみ有意 */
	int line;
	int i;
	int v;
	const unsigned char* attribute_table;
	const unsigned char* pattern_generator;
	const unsigned char* pattern;
	unsigned char* p;

	/* テーブルアドレスを取得します。 */
	attribute_table   = &vram[(reg[5] & 0x7f) <<  7]; /* 128B境界に整列 */
	pattern_generator = &vram[(reg[6] & 0x07) << 11]; /*  2KB境界に整列 */

	/* 32枚のスプライトについて... */
	for(sprite = 0; sprite < 32; sprite++) {

		/* X座標、Y座標、パターン番号、EarlyClockとカラーコードを取得します。 */
		y    = *attribute_table++;
		x    = *attribute_table++;
		code = *attribute_table++;
		c    = *attribute_table++;

		/* Y座標が画面下に外れていたら... */
		if(y >= 192) {
			if(y > 256 - SIZE_MAG) {
				/* 画面上端をまたぐ描画です。 */
				y -= 256;
			} else if(y == 208/*仕様*/) {
				/* これ以降のスプライトを表示しません。 */
				break;
			} else {
				/* 完全に画面外です。 */
				continue;
			}
		}

		/* EarlyClockとカラーコード以外を確実にクリアします。 */
		c &= 0x8f;

		/* EarlyClock=1ならば、32ピクセル左へずらします。 */
		if(c > 15) {
			c &= 15;
			x -= 32;
			if(x <= 0 - SIZE_MAG) {
				/* 完全に画面外です。 */
				continue;
			}
		}

		/* カラーコード0:透明色による描画は無意味なので飛ばします。 */
		if(!c) {
			continue;
		}

#ifdef TMS9918_GRAYSCALE
		/* グレイスケール時は、カラーをグレイスケールに変換します。 */
		c = tms9918_grayscale_table[c];
#endif /*TMS9918_GRAYSCALE*/

#if(SIZE == 16)
		/* Size1モードでは、開始パターン番号を4の倍数に整列します。 */
		code &= ~3;
#endif /*SIZE == 16*/

		/* パターンデータの先頭アドレスを求めます。 */
		pattern = pattern_generator + code * 8;

		/* 転送先矩形の左上原点アドレスを求めます。 */
		p = vbuff + y * 256 + x;

		if((x >= 0) && (x <= 256 - SIZE_MAG) && (y >= 0) && (y <= 192 - SIZE_MAG)) {
			/* クリッピング不要。 */
			for(side = 0; side < SIZE; side += 8) { /* SIZE=16時のみ有意 */
				for(line = 0; line < SIZE; line++) {
					v = *pattern++;
					if(v & 0x80) PSET; p += MAG;
					if(v & 0x40) PSET; p += MAG;
					if(v & 0x20) PSET; p += MAG;
					if(v & 0x10) PSET; p += MAG;
					if(v & 0x08) PSET; p += MAG;
					if(v & 0x04) PSET; p += MAG;
					if(v & 0x02) PSET; p += MAG;
					if(v & 0x01) PSET; p += MAG;
					p += (256 - 8) * MAG;
				}
				p -= (256 * SIZE - 8) * MAG;
			}
		} else {
			/* クリッピング必要。 */
			for(side = 0; side < SIZE; side += 8) { /* SIZE=16時のみ有意 */
				for(line = 0; line < SIZE; line++) {
					v = *pattern++;
					for(i = 0; i < 8; i++) {
						if((v & 0x80) && (x >= 0) && (x <= 255) && (y >= 0) && (y <= 191)) {
							PSET;
						}
						v <<= 1;
						x += MAG;
						p += MAG;
					}
					x -= 8 * MAG;
					y += 1 * MAG;
					p += (256 - 8) * MAG;
				}
				x +=    8 * MAG;
				y -= SIZE * MAG;
				p -= (256 * SIZE - 8) * MAG;
			}
		}
	}

#undef SIZE_MAG
#undef PSET

#endif /*TMS9918_SPRITE_IMPLEMENT*/

/****************************************************************************
 *
 ****************************************************************************/
