/*	
 *	framds15.c
 *
 *	高速RAM転送候補：スキャンライン描画関数（Ｚ比較あり・2bitmaskテクスチャ）
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2003 Naoyuki Sawa
 *
 *	* Tue Apr  2 05:53:00 JST 2003 Naoyuki Sawa
 *	- cliprend.cから移動してきました。
 */
#include "clip.h"

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

#ifdef REND_NOASM
void
draw_scanline_wz_2bitmask(const RENDVERTEX* v0, const RENDVERTEX* v1, DSLPARAM* param)
{
	unsigned char* vptr;	/* カラーバッファポインタ     */
	unsigned char* zptr;	/* Ｚバッファポインタ         */
	int nx;			/* 現在のスキャンラインの長さ */
	int n;			/* 現在の辺の残りピクセル数   */
	RENDVERTEX cur;		/* 現在値                     */
	DDA z;			/* Ｚ値DDA                    */
	DDA s, t;		/* テクスチャ座標DDA          */
	const RENDVERTEX* tmp;
	int ofs;
	unsigned char zval;
	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;
	zptr = param->surface_zbuff + ofs;

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

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

	/* DDAループ。 */
	n = nx;
	do {
		/* Ｚ比較。 */
		zval = (unsigned char)(cur.z >> 8);
		if(zval <= *zptr) {
			/* 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) {
				/* 2bitテクスチャなら、テクセル値をそのまま描きます。 */
				*vptr = param->texture_buf[ofs / 4] >> (3 - (ofs & 3)) * 2 & 3;
				*zptr = zval;
			}
		}
		/* バッファポインタを進めます。 */
		vptr++;
		zptr++;
		/* DDAステップ実行。 */
		DRAW_SCANLINE_STEP(z);
		DRAW_SCANLINE_STEP(s);
		DRAW_SCANLINE_STEP(t);
	} while(--n); /* 右端ピクセルは描かないので、プリデクリメントです。 */
}
#else /*REND_NOASM*/
	asm("
	.code
	.align 1
	.global draw_scanline_wz_2bitmask
	;// IN:
	;// %r12     = v0
	;// %r13     = v1
	;// %r14     = param
draw_scanline_wz_2bitmask:
	;// USAGE:
	;// %r0      = cur.z
	;// %r1      = cur.s
	;// %r2      = cur.t
	;// [%sp+ 0] = DDA.z
	;// [%sp+16] = DDA.s
	;// [%sp+32] = DDA.t
	pushn %r2
	xsub %sp, %sp, 48

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

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

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

	;// 副軸のDDAセットアップ。
	;// (DDA.z)
	xld.uh %r0, [%r12+4]	;// v0->z => cur.z
	xld.uh %r4, [%r13+4]	;// v1->z
	sub %r4, %r0
	xld.w %r5, 1
	xjruge __draw_scanline_wz_2bitmask_setup_z
	not %r4, %r4
	xadd %r4, %r4, 1
	xld.w %r5, -1
__draw_scanline_wz_2bitmask_setup_z:
	xsll %r4, 16
	ld.w %alr, %r4
	div0u %r15
	div1 %r15		;//  1
	div1 %r15		;//  2
	div1 %r15		;//  3
	div1 %r15		;//  4
	div1 %r15		;//  5
	div1 %r15		;//  6
	div1 %r15		;//  7
	div1 %r15		;//  8
	div1 %r15		;//  9
	div1 %r15		;// 10
	div1 %r15		;// 11
	div1 %r15		;// 12
	div1 %r15		;// 13
	div1 %r15		;// 14
	div1 %r15		;// 15
	div1 %r15		;// 16
	ld.w %r4, %ahr
	add %r4, %r4
	xld.w [%sp+ 0], %r4	;// z.n * 2
	not %r4, %r15
	xadd %r4, %r4, 1
	xld.w [%sp+ 4], %r4	;// z.d
	ld.w %r4, %alr
	mlt.h %r4, %r5
	ld.w %r4, %alr
	xld.w [%sp+ 8], %r4	;// z.u
	xld.w [%sp+12], %r5	;// z.v
	;// %r0      = cur.z
	;// [%sp+ 0] = z.n * 2
	;// [%sp+ 4] = z.d
	;// [%sp+ 8] = z.u
	;// [%sp+12] = z.v
	;
	;// (DDA.s)
	xld.uh %r1, [%r12+6]	;// v0->s => cur.s
	xld.uh %r4, [%r13+6]	;// v1->s
	sub %r4, %r1
	xld.w %r5, 1
	xjruge __draw_scanline_wz_2bitmask_setup_s
	not %r4, %r4
	xadd %r4, %r4, 1
	xld.w %r5, -1
__draw_scanline_wz_2bitmask_setup_s:
	xsll %r4, 16
	ld.w %alr, %r4
	div0u %r15
	div1 %r15		;//  1
	div1 %r15		;//  2
	div1 %r15		;//  3
	div1 %r15		;//  4
	div1 %r15		;//  5
	div1 %r15		;//  6
	div1 %r15		;//  7
	div1 %r15		;//  8
	div1 %r15		;//  9
	div1 %r15		;// 10
	div1 %r15		;// 11
	div1 %r15		;// 12
	div1 %r15		;// 13
	div1 %r15		;// 14
	div1 %r15		;// 15
	div1 %r15		;// 16
	ld.w %r4, %ahr
	add %r4, %r4
	xld.w [%sp+16], %r4	;// s.n * 2
	not %r4, %r15
	xadd %r4, %r4, 1
	xld.w [%sp+20], %r4	;// s.d
	ld.w %r4, %alr
	mlt.h %r4, %r5
	ld.w %r4, %alr
	xld.w [%sp+24], %r4	;// s.u
	xld.w [%sp+28], %r5	;// s.v
	;// %r1      = cur.s
	;// [%sp+16] = s.n * 2
	;// [%sp+20] = s.d
	;// [%sp+24] = s.u
	;// [%sp+28] = s.v
	;
	;// (DDA.t)
	xld.uh %r2, [%r12+8]	;// v0->t => cur.t
	xld.uh %r4, [%r13+8]	;// v1->t
	sub %r4, %r2
	xld.w %r5, 1
	xjruge __draw_scanline_wz_2bitmask_setup_t
	not %r4, %r4
	xadd %r4, %r4, 1
	xld.w %r5, -1
__draw_scanline_wz_2bitmask_setup_t:
	xsll %r4, 16
	ld.w %alr, %r4
	div0u %r15
	div1 %r15		;//  1
	div1 %r15		;//  2
	div1 %r15		;//  3
	div1 %r15		;//  4
	div1 %r15		;//  5
	div1 %r15		;//  6
	div1 %r15		;//  7
	div1 %r15		;//  8
	div1 %r15		;//  9
	div1 %r15		;// 10
	div1 %r15		;// 11
	div1 %r15		;// 12
	div1 %r15		;// 13
	div1 %r15		;// 14
	div1 %r15		;// 15
	div1 %r15		;// 16
	ld.w %r4, %ahr
	add %r4, %r4
	xld.w [%sp+32], %r4	;// t.n * 2
	not %r4, %r15
	xadd %r4, %r4, 1
	xld.w [%sp+36], %r4	;// t.d
	ld.w %r4, %alr
	mlt.h %r4, %r5
	ld.w %r4, %alr
	xld.w [%sp+40], %r4	;// t.u
	xld.w [%sp+44], %r5	;// t.v
	;// %r2      = cur.t
	;// [%sp+32] = t.n * 2
	;// [%sp+36] = t.d
	;// [%sp+40] = t.u
	;// [%sp+44] = t.v

	;// DDAループ。
	ld.w %r7, %r15
	add %r15, %r15
__draw_scanline_wz_2bitmask_loop:
	;// %r7  = n
	;// %r15 = nx * 2

	;// Ｚ比較。
	ld.uh %r4, %r0		;// zval
	xsrl %r4, 8
	xld.ub %r5, [%r11]	;// *zptr
	cmp %r4, %r5
	xjrugt __draw_scanline_wz_2bitmask_skip
	;// %r4 = zval

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

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

	;// 2bitテクスチャなら、テクセル値をそのまま描きます。 */
	xld.w %r5, [%r14+16]	;// param->texture_buf
	ld.w %r6, %r12
	xsrl %r6, 2
	add %r5, %r6
	xld.ub %r5, [%r5]
	;
	not %r6, %r12
	xand %r6, %r6, 3
	add %r6, %r6
	srl %r5, %r6		;// %r6={0|2|4|6}なのでxsrlにする必要なし。xsrlにすると余計なコードが生成されて遅くなる。
	xand %r5, %r5, 3
	;
	xld.b [%r10], %r5	;// *vptr
	xld.b [%r11], %r4	;// *zptr
__draw_scanline_wz_2bitmask_skip:

	;// バッファポインタを進めます。
	xadd %r10, %r10, 1
	xadd %r11, %r11, 1

	;// DDAステップ実行。
	;// (DDA.z)
	xld.w %r4, [%sp+ 8]	;// z.u
	add %r0, %r4
	xld.w %r4, [%sp+ 4]	;// z.d
	xld.w %r5, [%sp+ 0]	;// z.n * 2
	add %r4, %r5
	xjruge __draw_scanline_wz_2bitmask_step_z ;// !C条件
	xld.w %r5, [%sp+12]	;// z.v
	add %r0, %r5
	sub %r4, %r15
__draw_scanline_wz_2bitmask_step_z:
	xld.w [%sp+ 4], %r4	;// z.d
	;
	;// (DDA.s)
	xld.w %r4, [%sp+24]	;// s.u
	add %r1, %r4
	xld.w %r4, [%sp+20]	;// s.d
	xld.w %r5, [%sp+16]	;// s.n * 2
	add %r4, %r5
	xjruge __draw_scanline_wz_2bitmask_step_s ;// !C条件
	xld.w %r5, [%sp+28]	;// s.v
	add %r1, %r5
	sub %r4, %r15
__draw_scanline_wz_2bitmask_step_s:
	xld.w [%sp+20], %r4	;// s.d
	;
	;// (DDA.t)
	xld.w %r4, [%sp+40]	;// t.u
	add %r2, %r4
	xld.w %r4, [%sp+36]	;// t.d
	xld.w %r5, [%sp+32]	;// t.n * 2
	add %r4, %r5
	xjruge __draw_scanline_wz_2bitmask_step_t ;// !C条件
	xld.w %r5, [%sp+44]	;// t.v
	add %r2, %r5
	sub %r4, %r15
__draw_scanline_wz_2bitmask_step_t:
	xld.w [%sp+36], %r4	;// t.d

	xsub %r7, %r7, 1
	xjrne __draw_scanline_wz_2bitmask_loop

__draw_scanline_wz_2bitmask_ret:
	xadd	%sp, %sp, 48
	popn	%r2
	ret
	");
#endif /*REND_NOASM*/
