;	
;	framdmva.s
;
;	P/ECE DMG-Video Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Fri Feb 18 20:18:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;	* Tue Mar 10 20:00:00 JST 2005 Naoyuki Sawa
;	- dmgvideo_draw_chr()の描画処理が間違っていたのを修正しました。
;	  画面情報に一部はみ出たセルを描くときに、セルの下半分ではなく上半分を描いてしまっていました。
;
;#include "clipdmva.h"
;/	
;/	clipdmva.h
;/
;/	P/ECE DMG-Video Emulator
;/
;/	CLiP - Common Library for P/ECE
;/	Copyright (C) 2001-2005 Naoyuki Sawa
;/
;/	* Fri Feb 18 20:18:00 JST 2005 Naoyuki Sawa
;/	- 作成開始。
;/

;/ このファイルはC/アセンブラソース両方から参照します。
;/ C言語特有の定義を含めてはいけません。

;/ このシンボルを定義すると、アセンブラコードを使用します。
;/ このシンボルを定義しなければ、Ｃ言語コードを使用します。
;#define DMGVIDEO_ASM
;#ifdef DMGVIDEO_ASM

	.code
	.align 1

;****************************************************************************
;	
;****************************************************************************

;
;	DMGVIDEO構造体
;
				; typedef struct _DMGVIDEO {
;#define MEM		 0	; 	unsigned char* mem;			/* + 0, 4: メインメモリの先頭アドレス */
;#define VBUFF		 4	; 	unsigned char* vbuff/*[160*144]*/;	/* + 4, 4: 現在フレームの描画ターゲット (NULL:実描画無し) */
;#define CLUT		 8	; 	unsigned char clut[4 * 3];		/* + 8,12:パレット ([0..3]=BGP,[4..7]=OBP0,[8..11]=OBP1) */
;#define SCAN_START	20	; 	unsigned char scan_start;		/* +20, 1: 走査区間の開始ライン */
;#define SCAN_END	21	; 	unsigned char scan_end;			/* +21, 1: 走査区間の終了ライン */
				; 	//					/* +22, 2: (パディング) */
;#define SIZEOF_DMGVIDEO	24	; } DMGVIDEO;					/* =24 */

;****************************************************************************
;	
;****************************************************************************

	.global	dmgvideo_reduce
dmgvideo_reduce:
	ld.w	%r10,0x8	; 	xld.w	%r10, 8				; z = 8
dmgvideo_reduce_DO_Z:				; do {
	;
	ld.w	%r11,0xb	; 	xld.w	%r11, 11			; y = 11
	ld.w	%r15,0x1	; 	xld.w	%r15, 1				; i = 1
dmgvideo_reduce_DO_Y:				; do {
	;
	ext	0x0		; 	xld.w	%r14, 32			; x = 32
	ld.w	%r14,0x20
	sub	%r15,0x1	; 	xsub	%r15, %r15, 1			; if(--i) goto DO_X1
	jrne	dmgvideo_reduce_DO_X1	; 	xjrne	dmgvideo_reduce_DO_X1
	;
dmgvideo_reduce_DO_X0:
	ld.ub	%r4, [%r13]+			; %r4    =  src[0]
	ld.ub	%r5, [%r13]+			; %r5    =  src[1]
	ld.ub	%r6, [%r13]+			; %r6    =  src[2]
	ld.b	[%r12]+, %r4			; dst[0] =  src[0]
	ld.b	[%r12]+, %r5			; dst[1] =  src[1]
	ld.b	[%r12]+, %r6			; dst[2] =  src[2]
	ld.ub	%r4, [%r13]+			; %r4    =  src[3]
	ld.ub	%r5, [%r13]+			; %r5    =  src[4]
	add	%r4,0x1		; 	xadd	%r4, %r4, 1			; %r4    =  src[3]       +1 *anti-interlock*
	add	%r4, %r5			; %r4    =  src[3]+src[4]+1
	srl	%r4,0x1		; 	xsrl	%r4, 1				; %r4    = (src[3]+src[4]+1)>>1
	ld.b	[%r12]+, %r4			; dst[3] = (src[3]+src[4]+1)>>1
	;
	sub	%r14,0x1	; 	xsub	%r14, %r14, 1			; } while(x)
	jrne	dmgvideo_reduce_DO_X0	; 	xjrne	dmgvideo_reduce_DO_X0
	jp.d	dmgvideo_reduce_LOOP_Y	; 	xjp.d	dmgvideo_reduce_LOOP_Y
	ld.w	%r15, 3				; i = 3 *delay*
	;
dmgvideo_reduce_DO_X1:				; do {
	ext	0xa0		; 	xld.ub	%r4, [%r13+0xa0]			; %r4    =         src[160]
	ld.ub	%r4,[%r13]
	 ld.ub	%r5, [%r13]+			; %r5    =  src[0]
	add	%r4,0x1		; 	xadd	%r4, %r4, 1			; %r4    =         src[160]+1 *anti-interlock*
	add	%r4, %r5			; %r4    =  src[0]+src[160]+1
	srl	%r4,0x1		; 	xsrl	%r4, 1				; %r4    = (src[0]+src[160]+1)>>1
	ld.b	[%r12]+, %r4			; dst[0] = (src[0]+src[160]+1)>>1
	ext	0xa0		; 	xld.ub	%r4, [%r13+0xa0]			; %r4    =         src[161]
	ld.ub	%r4,[%r13]
	 ld.ub	%r5, [%r13]+			; %r5    =  src[1]
	add	%r4,0x1		; 	xadd	%r4, %r4, 1			; %r4    =         src[161]+1 *anti-interlock*
	add	%r4, %r5			; %r4    =  src[1]+src[161]+1
	srl	%r4,0x1		; 	xsrl	%r4, 1				; %r4    = (src[1]+src[161]+1)>>1
	ld.b	[%r12]+, %r4			; dst[1] = (src[1]+src[161]+1)>>1
	ext	0xa0		; 	xld.ub	%r4, [%r13+0xa0]			; %r4    =         src[162]
	ld.ub	%r4,[%r13]
	 ld.ub	%r5, [%r13]+			; %r5    =  src[2]
	add	%r4,0x1		; 	xadd	%r4, %r4, 1			; %r4    =         src[162]+1 *anti-interlock*
	add	%r4, %r5			; %r4    =  src[2]+src[162]+1
	srl	%r4,0x1		; 	xsrl	%r4, 1				; %r4    = (src[2]+src[162]+1)>>1
	ld.b	[%r12]+, %r4			; dst[2] = (src[2]+src[162]+1)>>1
	ext	0xa0		; 	xld.ub	%r4, [%r13+0xa0]			; %r4    =                src[163]
	ld.ub	%r4,[%r13]
	 ld.ub	%r5, [%r13]+			; %r5    =  src[3]
	ext	0xa0		; 	xld.ub	%r6, [%r13+0xa0]			; %r6    =                         src[164]
	ld.ub	%r6,[%r13]
	 ld.ub	%r7, [%r13]+			; %r7    =         src[4]
	add	%r4,0x2		; 	xadd	%r4, %r4, 2			; %r4    =                src[163]         +2
	add	%r4, %r5			; %r4    =  src[3]       +src[163]         +2
	add	%r4, %r6			; %r4    =  src[3]       +src[163]+src[164]+2
	add	%r4, %r7			; %r4    =  src[3]+src[4]+src[163]+src[164]+2
	srl	%r4,0x2		; 	xsrl	%r4, 2				; %r4    = (src[3]+src[4]+src[163]+src[164]+2)>>2
	ld.b	[%r12]+, %r4			; dst[3] = (src[3]+src[4]+src[163]+src[164]+2)>>2
	;
	sub	%r14,0x1	; 	xsub	%r14, %r14, 1			; } while(x)
	jrne	dmgvideo_reduce_DO_X1	; 	xjrne	dmgvideo_reduce_DO_X1
	ext	0x2		; 	xadd	%r13, %r13, 160			; src += 160
	add	%r13,0x20
	;
dmgvideo_reduce_LOOP_Y:
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1			; } while(y)
	jrne	dmgvideo_reduce_DO_Y	; 	xjrne	dmgvideo_reduce_DO_Y
	;
	sub	%r10,0x1	; 	xsub	%r10, %r10, 1			; } while(z)
	jrne	dmgvideo_reduce_DO_Z	; 	xjrne	dmgvideo_reduce_DO_Z
	ret

;****************************************************************************
;	
;****************************************************************************

	.global	dmgvideo_draw_chr
dmgvideo_draw_chr:
	ext	dmgvideo+0x0@h	; 	xld.w	%r7, dmgvideo			; %r7 = dmgvideo
	ext	dmgvideo+0x0@m
	ld.w	%r7,dmgvideo+0x0@l
	;
	ext	0x14		; 	xld.ub	%r4, [%r7+0x14]		; %r4 = scan_start
	ld.ub	%r4,[%r7]
	ext	0x15		; 	xld.ub	%r5, [%r7+0x15]		; %r5 = scan_end
	ld.ub	%r5,[%r7]
	;
	sub	%r4, 8				; if(ypos <= scan_start-8) goto EXIT
	cmp	%r13, %r4
	jrle.d	dmgvideo_draw_chr_EXIT	; 	xjrle.d	dmgvideo_draw_chr_EXIT
	add	%r4, 8				; *delay*
	cmp	%r13, %r5			; if(ypos >= scan_end) goto EXIT
	jrge	dmgvideo_draw_chr_EXIT	; 	xjrge	dmgvideo_draw_chr_EXIT
	cmp	%r12,0x38	; 	xcmp	%r12, -8			; if(xpos <= 0-8) goto EXIT
	jrle	dmgvideo_draw_chr_EXIT	; 	xjrle	dmgvideo_draw_chr_EXIT
	ext	0x2		; 	xcmp	%r12, 160			; if(xpos >= 160) goto EXIT
	cmp	%r12,0x20
	jrge	dmgvideo_draw_chr_EXIT	; 	xjrge	dmgvideo_draw_chr_EXIT
	;
	ld.w	%r9,[%r7]	; 	xld.w	%r9, [%r7+0x0]			; %r14 = pattern = &mem[0x8000|code<<4]
	sll	%r14,0x4	; 	xsll	%r14, 4
	ext	0x200		; 	xoor	%r14, %r14, 0x8000
	or	%r14,0x0
	add	%r14, %r9
	;
	ext	0x4		; 	xld.w	%r6, [%r7+0x4]		; %r6 = vbuff
	ld.w	%r6,[%r7]
	add	%r7,0x8		; 	xadd	%r7, %r7, 8			; %r7 = clut
	;
	sla	%r13,0x5	; 	xsla	%r13, 5				; vbuff += ypos * 160 + xpos
	add	%r6, %r13			;                 ~~~(32+128)
	sla	%r13,0x2	; 	xsla	%r13, 0x2
	add	%r6, %r13
	sra	%r13,0x7	; 	xsra	%r13, 7
	add	%r6, %r12
	;
	sll	%r15,0x2	; 	xsll	%r15, 2				; clut += palno << 2
	add	%r7, %r15
	;
	cmp	%r13, %r4			; if(ypos < scan_start) goto CLIP
	jrlt	dmgvideo_draw_chr_CLIP	; 	xjrlt	dmgvideo_draw_chr_CLIP
	sub	%r5, 8				; if(ypos > scan_end-8) goto CLIP
	cmp	%r13, %r5
	jrgt.d	dmgvideo_draw_chr_CLIP	; 	xjrgt.d	dmgvideo_draw_chr_CLIP
	add	%r5, 8				; *delay*
	ext	0x2		; 	xcmp	%r12, 0x98			; if(xpos < 0 || xpos > 160-8) goto CLIP
	cmp	%r12,0x18
	jrugt	dmgvideo_draw_chr_CLIP	; 	xjrugt	dmgvideo_draw_chr_CLIP
	;--------------------------------------------------------------------
dmgvideo_draw_chr_FAST:
	ld.w	%r13,0x8	; 	xld.w	%r13, 8				; %r13 = y = 8
dmgvideo_draw_chr_FAST_DO_Y:			; do {
	;
	ld.ub	%r10, [%r14]+			;   %r10 = *pattern++ (lobit = 00000000 00000000 00000000 abcdefgh)
	ld.ub	%r11, [%r14]+			;   %r11 = *pattern++ (hibit = 00000000 00000000 00000000 ABCDEFGH)
	rr	%r10, 8				;   lobit = abcdefgh 00000000 00000000 00000000
	rr	%r11, 7				;   hibit = BCDEFGH0 00000000 00000000 0000000A
	;
	ld.w	%r12,0x8	; 	xld.w	%r12, 8				;   %r12 = x = 8
dmgvideo_draw_chr_FAST_DO_X:			;   do {
	;
	ext	0x1		; 	xand	%r15, %r11, 1			;     %r15  = 00000000 00000000 00000000 0000000A
	and	%r15,%r11
	add	%r10, %r10			;     lobit = bcdefgh0 00000000 00000000 00000000, %psr(C) = a
	adc	%r15, %r15			;     %r15  = 00000000 00000000 00000000 000000Aa
dmgvideo_draw_chr_PATCH_POINT_1:
	;{{dmgvideo_draw_chr_opaqueから呼ばれるときはnopに置き換えます。
	jreq.d	dmgvideo_draw_chr_FAST_SKIP_X	;     if(!v) goto SKIP_X
	;}}dmgvideo_draw_chr_opaqueから呼ばれるときはnopに置き換えます。
	rl	%r11, 1				;     hibit = CDEFGH00 00000000 00000000 0000000B  *delay*
	;
	add	%r15, %r7			;     *vbuff = clut[v]
	ld.ub	%r15, [%r15]
	ld.b	[%r6], %r15
	;
dmgvideo_draw_chr_FAST_SKIP_X:
	sub	%r12,0x1	; 	xsub	%r12, %r12, 1
	jrne.d	dmgvideo_draw_chr_FAST_DO_X	; 	xjrne.d	dmgvideo_draw_chr_FAST_DO_X	;   } while(--x)
	add	%r6, 1				;   vbuff++ *delay*
	;
	ext	0x2		; 	xadd	%r6, %r6, 0x98			;   vbuff += 160-8
	add	%r6,0x18
	;
	sub	%r13,0x1	; 	xsub	%r13, %r13, 1
	jrne	dmgvideo_draw_chr_FAST_DO_Y	; 	xjrne	dmgvideo_draw_chr_FAST_DO_Y	; } while(--y)
	; (TODO: DelaySlot空いてます。なにか移せるものがあれば移してください)
	;
	jp	dmgvideo_draw_chr_EXIT	; 	xjp	dmgvideo_draw_chr_EXIT
	;--------------------------------------------------------------------
dmgvideo_draw_chr_CLIP:
	pushn	%r1
	;
	ld.w	%r1,0x8		; 	xld.w	%r1, 8				; %r1 = y = 8
dmgvideo_draw_chr_CLIP_DO_Y:			; do {
	;
	cmp	%r13, %r4			;   if(ypos < scan_start) goto SKIP_Y
	jrlt	dmgvideo_draw_chr_CLIP_SKIP_Y	; 	xjrlt	dmgvideo_draw_chr_CLIP_SKIP_Y
	cmp	%r13, %r5			;   if(ypos >= scan_end) goto SKIP_Y
	jrge	dmgvideo_draw_chr_CLIP_SKIP_Y	; 	xjrge	dmgvideo_draw_chr_CLIP_SKIP_Y
	;
	;{{2005/05/10 修正
	;ld.ub	%r10, [%r14]+			;   %r10 = *pattern++ (lobit = 00000000 00000000 00000000 abcdefgh)
	;ld.ub	%r11, [%r14]+			;   %r11 = *pattern++ (hibit = 00000000 00000000 00000000 ABCDEFGH)
	;↓2005/05/10 修正
	ld.ub	%r10,[%r14]	; 	xld.ub	%r10, [%r14+0x0]			;   %r10 = pattern[0] (lobit = 00000000 00000000 00000000 abcdefgh)
	ext	0x1		; 	xld.ub	%r11, [%r14+0x1]			;   %r11 = pattern[1] (hibit = 00000000 00000000 00000000 ABCDEFGH)
	ld.ub	%r11,[%r14]
	;}}2005/05/10 修正
	rr	%r10, 8				;   lobit = abcdefgh 00000000 00000000 00000000
	rr	%r11, 7				;   hibit = BCDEFGH0 00000000 00000000 0000000A
	;
	ld.w	%r0,0x8		; 	xld.w	%r0, 8				;   %r0 = x = 8
dmgvideo_draw_chr_CLIP_DO_X:			;   do {
	;
	ext	0x1		; 	xand	%r15, %r11, 1			;     %r15  = 00000000 00000000 00000000 0000000A
	and	%r15,%r11
	add	%r10, %r10			;     lobit = bcdefgh0 00000000 00000000 00000000, %psr(C) = a
	adc	%r15, %r15			;     %r15  = 00000000 00000000 00000000 000000Aa
dmgvideo_draw_chr_PATCH_POINT_2:
	;{{dmgvideo_draw_chr_opaqueから呼ばれるときはnopに置き換えます。
	jreq.d	dmgvideo_draw_chr_CLIP_SKIP_X	;     if(!v) goto SKIP_X
	;}}dmgvideo_draw_chr_opaqueから呼ばれるときはnopに置き換えます。
	rl	%r11, 1				;     hibit = CDEFGH00 00000000 00000000 0000000B  *delay*
	;
	ext	0x2		; 	xcmp	%r12, 160			;     if(x < 0 || x >= 160) goto SKIP_X
	cmp	%r12,0x20
	jruge	dmgvideo_draw_chr_CLIP_SKIP_X	; 	xjruge	dmgvideo_draw_chr_CLIP_SKIP_X
	;
	add	%r15, %r7			;     *vbuff = clut[v]
	ld.ub	%r15, [%r15]
	ld.b	[%r6], %r15
	;
dmgvideo_draw_chr_CLIP_SKIP_X:
	add	%r12,0x1	; 	xadd	%r12, %r12, 1			;     xpos++
	;
	sub	%r0,0x1		; 	xsub	%r0, %r0, 1
	jrne.d	dmgvideo_draw_chr_CLIP_DO_X	; 	xjrne.d	dmgvideo_draw_chr_CLIP_DO_X	;   } while(--x)
	add	%r6, 1				;   vbuff++ *delay*
	;
	sub	%r12,0x8	; 	xsub	%r12, %r12, 8			;   xpos -= 8
	sub	%r6,0x8		; 	xsub	%r6, %r6, 8			;   vbuff -= 8
dmgvideo_draw_chr_CLIP_SKIP_Y:
	add	%r13,0x1	; 	xadd	%r13, %r13, 1			;   ypos++
	ext	0x2		; 	xadd	%r6, %r6, 160			;   vbuff += 160
	add	%r6,0x20
	;
	sub	%r1,0x1		; 	xsub	%r1, %r1, 1
	;{{2005/05/10 修正
	;xjrne	dmgvideo_draw_chr_CLIP_DO_Y	; } while(--y)
	;↓2005/05/10 修正
	jrne.d	dmgvideo_draw_chr_CLIP_DO_Y	; 	xjrne.d	dmgvideo_draw_chr_CLIP_DO_Y	; } while(--y)
	add	%r14, 2				; pattern += 2 *delay*
	;}}2005/05/10 修正
	;
	popn	%r1
	;--------------------------------------------------------------------
dmgvideo_draw_chr_EXIT:
	ret

;****************************************************************************
;	
;****************************************************************************

	.global	dmgvideo_draw_chr_opaque
dmgvideo_draw_chr_opaque:
	pushn	%r1
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@ah	; 	xld.h	%r0, [dmgvideo_draw_chr_PATCH_POINT_1]
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@al
	ld.h	%r0,[%r8]
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@ah	; 	xld.h	%r1, [dmgvideo_draw_chr_PATCH_POINT_2]
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@al
	ld.h	%r1,[%r8]
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@ah	; 	xld.h	[dmgvideo_draw_chr_PATCH_POINT_1], %r8	; nop (Code=0x0000)
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@al
	ld.h	[%r8],%r8
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@ah	; 	xld.h	[dmgvideo_draw_chr_PATCH_POINT_2], %r8	; nop (Code=0x0000)
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@al
	ld.h	[%r8],%r8
	call	dmgvideo_draw_chr	; 	xcall	dmgvideo_draw_chr
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@ah	; 	xld.h	[dmgvideo_draw_chr_PATCH_POINT_1], %r0
	ext	dmgvideo_draw_chr_PATCH_POINT_1+0x0@al
	ld.h	[%r8],%r0
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@ah	; 	xld.h	[dmgvideo_draw_chr_PATCH_POINT_2], %r1
	ext	dmgvideo_draw_chr_PATCH_POINT_2+0x0@al
	ld.h	[%r8],%r1
	popn	%r1
	ret

;****************************************************************************
;	
;****************************************************************************

;#endif /*DMGVIDEO_ASM*/
