/*	
 *	framds21.c
 *
 *	高速RAM転送候補：スキャンライン描画関数（Ｚ比較なし・テクスチャなし）
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2008 Naoyuki Sawa
 *
 *	* Mon Aug  2 05:00:00 JST 2004 Naoyuki Sawa
 *	- clipren3.cから移動してきました。
 *	* Sat Aug 25 23:05:34 JST 2007 Naoyuki Sawa
 *	- アセンブラ化しました。
 *	* Tue Jan 01 21:51:54 JST 2008 Naoyuki Sawa
 *	- テクスチャ無しポリゴンの描画色を、背景色でなく、前景色に変更しました。
 *	  clipren3.cの2008/01/01の変更コメントを参照してください。
 *	- DSLPARAM構\造体の、fore_colorとback_colorの順序の入れ替えに追従しました。
 *	  cliprend.hの2008/01/01の変更コメントを参照してください。
 *	- 下のアセンブラ版も、C言語版と同様に修正しました。(変更コメントは省略)
 *	  結局、上記二点の変更が相殺して、オフセットの変更は不要でした。
 *	  コメントをback_color→fore_colorに変更しただけで、コードはそのままです。
 *	* Mon Mar 31 12:02:19 JST 2008 Naoyuki Sawa
 *	- 省メモリ化の改良を行いました。
 *	  詳しくは、framdprm.cの2008/03/31のコメントを参照してください。
 */
#include "clip.h"

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

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

	/* 確実に 左: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ループ。 */
	n = nx;
	do {
//{{2008/01/01:変更
//		/* テクスチャ無しなら、フェイスの背景色で描きます。 */
//		*vptr = param->back_color;
//↓ * Tue Jan 01 21:51:54 JST 2008 Naoyuki Sawa
//↓ - テクスチャ無しポリゴンの描画色を、背景色でなく、前景色に変更しました。
//↓   clipren3.cの2008/01/01の変更コメントを参照してください。
//↓ - DSLPARAM構\造体の、fore_colorとback_colorの順序の入れ替えに追従しました。
//↓   cliprend.hの2008/01/01の変更コメントを参照してください。
//↓ - 下のアセンブラ版も、C言語版と同様に修正しました。(変更コメントは省略)
//↓   結局、上記二点の変更が相殺して、オフセットの変更は不要でした。
//↓   コメントをback_color→fore_colorに変更しただけで、コードはそのままです。
		/* テクスチャ無しなら、フェイスの背景色で描きます。 */
		*vptr = param->fore_color;
//}}2008/01/01:変更
		/* バッファポインタを進めます。 */
		vptr++;
	} while(--n); /* 右端ピクセルは描かないので、プリデクリメントです。 */
}
#else /*REND_NOASM*/
//{{2008/03/31:省メモリ化の改良に伴い削除
//	asm("
//	.code
//	.align 1
//	.global draw_scanline_woz_color
//	;// IN:
//	;// %r12     = v0
//	;// %r13     = v1
//	;// %r14     = param
//draw_scanline_woz_color:
//	;// USAGE:
//	;// none
//
//	;// 確実に 左:v0 -> v1:右 とします。
//	xld.uh	%r4, [%r12+0]				;// v0->x
//	xld.uh	%r5, [%r13+0]				;// v1->x
//	cmp	%r4, %r5
//	xjrule	__draw_scanline_woz_color_swap
//	xor	%r12, %r13
//	xor	%r13, %r12
//	xor	%r12, %r13
//__draw_scanline_woz_color_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
//
//	xld.ub	%r12, [%r14+24]				;// param->fore_color
//	;// %r12 = fore_color
//
//	;// 主軸のDDAセットアップ。
//	xld.uh	%r5, [%r13+0]				;// v1->x
//	xjp.d	__draw_scanline_woz_color_next
//	sub	%r5, %r6				; *delay*
//	;// %r5     = n
//	;// %psr(Z) = n==0
//
//	;// DDAループ。
//__draw_scanline_woz_color_loop:
//	ld.b	[%r4]+, %r12				;// *vptr++
//	;// 初回はここから始まります。
//	;// ・n==0ならば、何も描かずに抜けます。
//	;//   n=(n-1)になりますが、ダミー動作です。
//	;// ・n!=0ならば、n=(n-1)、フラグに(n-1)==0を反映して、ループします。
//	;// 2回目にここへ来たときも、フラグが維持されていることを利用します。
//	;// ループカウンタとフラグは前のループの遅延スロットで先に変化させておき、
//	;// 次のループでその結果を参照するわけです。
//__draw_scanline_woz_color_next:
//	xjrne.d	__draw_scanline_woz_color_loop
//	sub	%r5, 1					; *delay*
//	;// %r5     = (n-1)
//	;// %psr(Z) = (n-1)==0
//
//	ret
//	");
//}}2008/03/31:省メモリ化の改良に伴い削除
//↓* Mon Mar 31 12:02:19 JST 2008 Naoyuki Sawa
//↓- 省メモリ化の改良を行いました。
//↓  詳しくは、framdprm.cの2008/03/31のコメントを参照してください。
asm("
	.code
	.align	1
	.global	draw_scanline_woz_color
	;// %r12 := v0
	;// %r13 := v1
	;// %r14 := param
draw_scanline_woz_color:
	ld.uh	%r4, [%r12]+			; %r4  := v0->x
	ld.uh	%r5, [%r12]			; %r5  := v0->y
	ld.uh	%r6, [%r13]			; %r6  := v1->x
	ld.w	%r7, [%r14]+			; %r7  := {surface_w,surface_h}
	ld.w	%r10, [%r14]			; %r10 := surface_vbuff
	cmp	%r4, %r6
	jrle.d	5				; if(v0->x > v1->x)
	add	%r14, 20			; %r14 := &param->fore_color			*delay*
	 xor	%r4, %r6			;   %r4  :=                 (v0->x ^ v1->x)
	 xor	%r6, %r4			;   %r6  := v0->x = v1->x ^ (v0->x ^ v1->x)
	 xor	%r4, %r6			;   %r4  := v1->x =         (v0->x ^ v1->x) ^ v0->x
	ld.ub	%r11, [%r14]			; %r11 := fore_color
	;// %r4  := v0->x
	;// %r5  := v0->y
	;// %r6  := v1->x
	;// %r7  := {surface_w,surface_h}	(surface_hはmlt.hによって無視されます)
	;// %r10 := surface_vbuff
	;// %r11 := fore_color

	;// 始点アドレスを求めます。
	mlt.h	%r5, %r7			; %alr :=       surface_w * v0->y
	ld.w	%r9, %alr			; %r9  :=       surface_w * v0->y
	add	%r9, %r4			; %r9  := ofs = surface_w * v0->y + v0->x
	add	%r10, %r9			; %r10 := vptr = surface_vbuff + ofs
	;// %r4  := v0->x
	;// %r6  := v1->x
	;// %r10 := vptr
	;// %r11 := fore_color

	;// 主軸のDDAセットアップ。
	jp.d	draw_scanline_woz_color_NEXT
	sub	%r6, %r4			; %r6  := n = v1->x - v0->x			*delay*
	;// %r6     := n
	;// %r10    := vptr
	;// %r11    := fore_color
	;// %psr(Z) := n==0

	;// DDAループ。
draw_scanline_woz_color_LOOP:
	ld.b	[%r10]+, %r11			; *vptr = fore_color
draw_scanline_woz_color_NEXT:
	;// 初回はここから始まります。
	;// ・n==0ならば、何も描かずに抜けます。
	;//   n=(n-1)になりますが、ダミー動作です。
	;// ・n!=0ならば、n=(n-1)、フラグに(n-1)==0を反映して、ループします。
	;// 2回目にここへ来たときも、フラグが維持されていることを利用します。
	;// ループカウンタとフラグは前のループの遅延スロットで先に変化させておき、
	;// 次のループでその結果を参照するわけです。
	jrne.d	draw_scanline_woz_color_LOOP
	sub	%r6, 1				;						*delay*
	;// %r6     := (n-1)
	;// %r10    := vptr
	;// %r11    := fore_color
	;// %psr(Z) := (n-1)==0
	ret
");
#endif /*REND_NOASM*/
