/*	
 *	framds23.c
 *
 *	高速RAM転送候補：スキャンライン描画関数（Ｚ比較なし・1bitmaskテクスチャ）
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2008 Naoyuki Sawa
 *
 *	* Mon Aug  2 05:00:00 JST 2004 Naoyuki Sawa
 *	- clipren3.cから移動してきました。
 *	* Wed Jan 02 13:12:08 JST 2008 Naoyuki Sawa
 *	- draw_scanline_woz_1bitmask()をアセンブラ化しました。
 *	  既にアセンブラ化していたdraw_scanline_woz_2bitmask()を元にして、少し変更しただけです。
 */
#include "clip.h"

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

#ifdef REND_NOASM
void
draw_scanline_woz_1bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param)
{
	unsigned char* vptr;	/* カラーバッファポインタ     */
	int nx;			/* 現在のスキャンラインの長さ */
	int n;			/* 現在の辺の残りピクセル数   */
	RENDVERTEX cur;		/* 現在値                     */
	DDA s, t;		/* テクスチャ座標DDA          */
	const RENDVERTEX* tmp;
	int ofs;
	unsigned char sval, tval;

	/* 確実に 左:v0 -> v1:右 とします。 */
	if(v0->x > v1->x) {
		tmp = v0;
		      v0 = v1;
		           v1 = tmp;
	}

	/* 始点アドレスを求めます。 */
	ofs = param->surface_w * v0->y + v0->x;
	vptr = param->surface_vbuff + ofs;

	/* 主軸のDDAセットアップ。 */
	nx = v1->x - v0->x;
	if(nx == 0) return; /* 点なら描きません。 */

	/* 副軸のDDAセットアップ。 */
	DRAW_SCANLINE_SETUP(s);
	DRAW_SCANLINE_SETUP(t);

	/* DDAループ。 */
	n = nx;
	do {
		/* P/ECEは除算が遅いので、除算の要・不要を判定してから除算を行ったほうがまだマシです。
		 * テクスチャ座標がWrapしない場合のスキャンライン描画コードを展開すれば、さらに高速化できますが、
		 * コードサイズ増加との兼ね合いで、このあたりで妥協しました。
		 * 速度比較の参考数値: 常に除算(100%)->判定して除算(150%高速化)->コード展開(110%高速化)
		 */
		sval = (unsigned char)(cur.s >> 8); if(sval >= param->texture_w) sval %= param->texture_w;
		tval = (unsigned char)(cur.t >> 8); if(tval >= param->texture_h) tval %= param->texture_h;
		ofs = param->texture_w * tval + sval;
		if(param->texture_mask[ofs / 8] >> (7 - (ofs & 7)) & 1) {
			/* 1bitテクスチャなら、テクセル値によって 1:フェイスの前景色/0:フェイスの背景色 で描きます。 */
			*vptr = param->texture_buf[ofs / 8] >> (7 - (ofs & 7)) & 1 ? param->fore_color : param->back_color;
		}
		/* バッファポインタを進めます。 */
		vptr++;
		/* DDAステップ実行。 */
		DRAW_SCANLINE_STEP(s);
		DRAW_SCANLINE_STEP(t);
	} while(--n); /* 右端ピクセルは描かないので、プリデクリメントです。 */
}
#else /*REND_NOASM*/
/* * Wed Jan 02 13:12:08 JST 2008 Naoyuki Sawa
 * - draw_scanline_woz_1bitmask()をアセンブラ化しました。
 *   既にアセンブラ化していたdraw_scanline_woz_2bitmask()を元にして、少し変更しただけです。
 */
	asm("
	.code
	.align 1
	.global draw_scanline_woz_1bitmask
	;// IN:
	;// %r12     = v0
	;// %r13     = v1
	;// %r14     = param
draw_scanline_woz_1bitmask:
	;// USAGE:
	;// %r6      = cur.s
	;// %r7      = cur.t
	;// [%sp+ 0] = DDA.s
	;// [%sp+16] = DDA.t
	xsub	%sp, %sp, 32

	;// 確実に 左:v0 -> v1:右 とします。
	xld.uh	%r4, [%r12+0]				;// v0->x
	xld.uh	%r5, [%r13+0]				;// v1->x
	cmp	%r4, %r5
	xjrule	__draw_scanline_woz_1bitmask_swap
	xor	%r12, %r13
	xor	%r13, %r12
	xor	%r12, %r13
__draw_scanline_woz_1bitmask_swap:
	;// %r12 = v0
	;// %r13 = v1

	;// 始点アドレスを求めます。
	xld.uh	%r4, [%r14+0]				;// param->surface_w
	xld.w	%r5, [%r14+4]				;// param->surface_vbuff
	xld.uh	%r6, [%r12+0]				;// v0->x
	xld.uh	%r7, [%r12+2]				;// v0->y
	add	%r5, %r6
	mltu.h	%r4, %r7
	ld.w	%r4, %alr
	add	%r4, %r5
	;// %r4 = vptr
	;// %r6 = v0->x

	;// 主軸のDDAセットアップ。
	xld.uh	%r5, [%r13+0]				;// v1->x
	sub	%r5, %r6
	xjreq	__draw_scanline_woz_1bitmask_ret
	;// %r5 = nx

	;// 副軸のDDAセットアップ。
	;// (DDA.s)
	xld.uh	%r6,  [%r12+6]				;// v0->s => cur.s
	xld.uh	%r10, [%r13+6]				;// v1->s
	sub	%r10, %r6
	xjruge.d __draw_scanline_woz_1bitmask_setup_s
	ld.w	%r11, 1					; *delay*
	not	%r10, %r10
	xadd	%r10, %r10, 1
	xld.w	%r11, -1
__draw_scanline_woz_1bitmask_setup_s:
	xsll	%r10, 16
	ld.w	%alr, %r10
	div0u	%r5
	div1	%r5					;//  1
	div1	%r5					;//  2
	div1	%r5					;//  3
	div1	%r5					;//  4
	div1	%r5					;//  5
	div1	%r5					;//  6
	div1	%r5					;//  7
	div1	%r5					;//  8
	div1	%r5					;//  9
	div1	%r5					;// 10
	div1	%r5					;// 11
	div1	%r5					;// 12
	div1	%r5					;// 13
	div1	%r5					;// 14
	div1	%r5					;// 15
	div1	%r5					;// 16
	ld.w	%r10, %ahr
	add	%r10, %r10
	xld.w	[%sp+ 0], %r10				;// s.n * 2
	not	%r10, %r5
	xadd	%r10, %r10, 1
	xld.w	[%sp+ 4], %r10				;// s.d
	ld.w	%r10, %alr
	mlt.h	%r10, %r11
	ld.w	%r10, %alr
	xld.w	[%sp+ 8], %r10				;// s.u
	xld.w	[%sp+12], %r11				;// s.v
	;// %r6      = cur.s
	;// [%sp+ 0] = s.n * 2
	;// [%sp+ 4] = s.d
	;// [%sp+ 8] = s.u
	;// [%sp+12] = s.v
	;
	;// (DDA.t)
	xld.uh	%r7,  [%r12+8]				;// v0->t => cur.t
	xld.uh	%r10, [%r13+8]				;// v1->t
	sub	%r10, %r7
	xjruge.d __draw_scanline_woz_1bitmask_setup_t
	ld.w	%r11, 1					; *delay*
	not	%r10, %r10
	xadd	%r10, %r10, 1
	xld.w	%r11, -1
__draw_scanline_woz_1bitmask_setup_t:
	xsll	%r10, 16
	ld.w	%alr, %r10
	div0u	%r5
	div1	%r5					;//  1
	div1	%r5					;//  2
	div1	%r5					;//  3
	div1	%r5					;//  4
	div1	%r5					;//  5
	div1	%r5					;//  6
	div1	%r5					;//  7
	div1	%r5					;//  8
	div1	%r5					;//  9
	div1	%r5					;// 10
	div1	%r5					;// 11
	div1	%r5					;// 12
	div1	%r5					;// 13
	div1	%r5					;// 14
	div1	%r5					;// 15
	div1	%r5					;// 16
	ld.w	%r10, %ahr
	add	%r10, %r10
	xld.w	[%sp+16], %r10				;// t.n * 2
	not	%r10, %r5
	xadd	%r10, %r10, 1
	xld.w	[%sp+20], %r10				;// t.d
	ld.w	%r10, %alr
	mlt.h	%r10, %r11
	ld.w	%r10, %alr
	xld.w	[%sp+24], %r10				;// t.u
	xld.w	[%sp+28], %r11				;// t.v
	;// %r7      = cur.t
	;// [%sp+16] = t.n * 2
	;// [%sp+20] = t.d
	;// [%sp+24] = t.u
	;// [%sp+28] = t.v

	;// DDAループ。
	ld.w	%r10, %r5
	add	%r10, %r10
	xld.uh	%r15, [%r14+24]				;// %r15[0:7] = fore_color, %r15[8:15] = back_color
__draw_scanline_woz_1bitmask_loop:
	;// %r5  = n
	;// %r10 = nx * 2
	;// %r15 = {fore_color,back_color}

	;// テクスチャオフセット計算。
	xld.uh	%r11, [%r14+14]				;// param->texture_h
	ld.w	%r12, %r7				;// tval
	xsrl	%r12, 8
	cmp	%r12, %r11
	xjrult	__draw_scanline_woz_1bitmask_wrap_t
	xrr	%r12, 8
	ld.w	%alr, %r12
	div0u	%r11
	div1	%r11					;// 1
	div1	%r11					;// 2
	div1	%r11					;// 3
	div1	%r11					;// 4
	div1	%r11					;// 5
	div1	%r11					;// 6
	div1	%r11					;// 7
	div1	%r11					;// 8
	ld.w	%r12, %ahr
__draw_scanline_woz_1bitmask_wrap_t:
	;// %r12 = tval
	;
	xld.uh	%r11, [%r14+12]				;// param->texture_w
	ld.w	%r13, %r6				;// sval
	xsrl	%r13, 8
	cmp	%r13, %r11
	xjrult	__draw_scanline_woz_1bitmask_wrap_s
	xrr	%r13, 8
	ld.w	%alr, %r13
	div0u	%r11
	div1	%r11					;// 1
	div1	%r11					;// 2
	div1	%r11					;// 3
	div1	%r11					;// 4
	div1	%r11					;// 5
	div1	%r11					;// 6
	div1	%r11					;// 7
	div1	%r11					;// 8
	ld.w	%r13, %ahr
__draw_scanline_woz_1bitmask_wrap_s:
	;// %r13 = sval
	;// %r11 = texture_w
	;
	mltu.h	%r11, %r12
	ld.w	%r11, %alr
	add	%r11, %r13
	;// %r11 = ofs

	;// マスクテスト。
	xld.w	%r12, [%r14+20]				;// param->texture_mask
	ld.w	%r13, %r11
	xsrl	%r13, 3
	add	%r12, %r13
	xld.ub	%r12, [%r12]
	;
	not	%r13, %r11
	xand	%r13, %r13, 7
	srl	%r12, %r13				;// %r13=0〜7なのでxsrlにする必要なし。xsrlにすると余計なコードが生成されて遅くなる。
	xand	%r12, %r12, 1
	xjreq	__draw_scanline_woz_1bitmask_skip

	;// 1bitテクスチャなら、テクセル値によって 1:フェイスの前景色/0:フェイスの背景色 で描きます。
	xld.w	%r12, [%r14+16]				;// param->texture_buf
	ld.w	%r13, %r11
	xsrl	%r13, 3
	add	%r12, %r13
	xld.ub	%r12, [%r12]
	;
	not	%r13, %r11
	xand	%r13, %r13, 7
	srl	%r12, %r13				;// %r13=0〜7なのでxsrlにする必要なし。xsrlにすると余計なコードが生成されて遅くなる。
	xand	%r12, %r12, 1
	;
	jrne.d	3					;// %r12 = (%r12 & 1) ? fore_color : back_color
	 ld.w	%r12, %r15				;// *delay*
	 srl	%r12, 8
	;
	xld.b	[%r4], %r12				;// *vptr
__draw_scanline_woz_1bitmask_skip:

	;// DDAステップ実行。
	;// (DDA.s)
	xld.w	%r11, [%sp+ 0]				;// s.n * 2
	xld.w	%r12, [%sp+ 4]				;// s.d
	xld.w	%r13, [%sp+ 8]				;// s.u
	add	%r12, %r11
	xjruge.d __draw_scanline_woz_1bitmask_step_s	;// !C条件
	add	%r6,  %r13				; *delay*
	xld.w	%r13, [%sp+12]				;// s.v
	sub	%r12, %r10
	add	%r6,  %r13
__draw_scanline_woz_1bitmask_step_s:
	xld.w	[%sp+ 4], %r12				;// s.d
	;
	;// (DDA.t)
	xld.w	%r11, [%sp+16]				;// t.n * 2
	xld.w	%r12, [%sp+20]				;// t.d
	xld.w	%r13, [%sp+24]				;// t.u
	add	%r12, %r11
	xjruge.d __draw_scanline_woz_1bitmask_step_t	;// !C条件
	add	%r7,  %r13				; *delay*
	xld.w	%r13, [%sp+28]				;// t.v
	sub	%r12, %r10
	add	%r7,  %r13
__draw_scanline_woz_1bitmask_step_t:
	xld.w	[%sp+20], %r12				;// t.d

	xsub	%r5, %r5, 1
	xjrne.d	__draw_scanline_woz_1bitmask_loop
	add	%r4, 1					; *delay*

__draw_scanline_woz_1bitmask_ret:
	xadd	%sp, %sp, 32
	ret
	");
#endif /*REND_NOASM*/

