;	
;	framsva.s
;
;	P/ECE SUPERVISION Video/Sound Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Thu Apr 14 05:55:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;

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

	.code
	.align	1

;****************************************************************************
;	Video
;****************************************************************************

; [note]
;	* framdmva.sのdmgvideo_reduce()をほとんどそのまま流用しました。
;	  変更点は、iの初期値(1->3)と再設定値(3->6)だけです。
;
	.global	svvideo_reduce
svvideo_reduce:
	ld.w	%r10,0x8	; 	xld.w	%r10, 8				; z = 8
svvideo_reduce_DO_Z:				; do {
	;
	ld.w	%r11,0xb	; 	xld.w	%r11, 11			; y = 11
	ld.w	%r15,0x3	; 	xld.w	%r15, 3				; i = 3
svvideo_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	svvideo_reduce_DO_X1	; 	xjrne	svvideo_reduce_DO_X1
	;
svvideo_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	svvideo_reduce_DO_X0	; 	xjrne	svvideo_reduce_DO_X0
	jp.d	svvideo_reduce_LOOP_Y	; 	xjp.d	svvideo_reduce_LOOP_Y
	ld.w	%r15, 6				; i = 6 *delay*
	;
svvideo_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	svvideo_reduce_DO_X1	; 	xjrne	svvideo_reduce_DO_X1
	ext	0x2		; 	xadd	%r13, %r13, 160			; src += 160
	add	%r13,0x20
	;
svvideo_reduce_LOOP_Y:
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1			; } while(y)
	jrne	svvideo_reduce_DO_Y	; 	xjrne	svvideo_reduce_DO_Y
	;
	sub	%r10,0x1	; 	xsub	%r10, %r10, 1			; } while(z)
	jrne	svvideo_reduce_DO_Z	; 	xjrne	svvideo_reduce_DO_Z
	ret

;****************************************************************************
;	Sound
;****************************************************************************

				; typedef struct _SVSOUNDTONE {
;#define TONE_VOLUME	 0	; 	int volume;	/* + 0,4: ボリューム (silent:0..15:max) */
;#define TONE_PERIOD	 4	; 	int period;	/* + 4,4: 音程(周期) */
;#define TONE_POLAR	 8	; 	int polar;	/* + 8,4: 出力極性 0:-/1:+ */
;#define TONE_COUNT	12	; 	int count;	/* +12,4: 周期カウンタ */
				; } SVSOUNDTONE;	/* =16 */

				; typedef struct _SVSOUNDNOISE {
;#define NOISE_ON	 0	; 	int on;		/* + 0,4: 0:Off/1:On */
;#define NOISE_VOLUME	 4	; 	int volume;	/* + 4,4: ボリューム (silent:0..15:max) */
;#define NOISE_PERIOD	 8	; 	int period;	/* + 8,4: 音程(周期) */
;#define NOISE_LFSR	12	; 	int lfsr;	/* +12,4: ノイズLFSR */
;#define NOISE_COUNT	16	; 	int count;	/* +16,4: 周期カウンタ */
				; } SVSOUNDNOISE;	/* =20 */

;#define SVSOUND_VOLUME_SHIFT	((16-7)+1)	; -> framsv.c

;
;	void svsound_tone_mix(SVSOUNDTONE* tone, short wbuff[/*SVSOUNDBUFLEN*/])
;
	.global	svsound_tone_mix
svsound_tone_mix:
	ld.w	%r4,[%r12]	; 	xld.w	%r4, [%r12+0x0]		; %r4 = volume = tone->volume
	cmp	%r4,0x0		; 	xcmp	%r4, 0				; if(!volume) goto EXIT
	jreq	svsound_tone_mix_EXIT	; 	xjreq	svsound_tone_mix_EXIT
	;
	ext	0x4		; 	xld.w	%r5, [%r12+0x4]		; %r5 = period = tone->period
	ld.w	%r5,[%r12]
	cmp	%r5,0x0		; 	xcmp	%r5, 0				; if(!period) goto EXIT
	jreq	svsound_tone_mix_EXIT	; 	xjreq	svsound_tone_mix_EXIT
	;
	ext	0x8		; 	xld.w	%r6, [%r12+0x8]		; %r6 = polar = tone->polar /* 取り出し */
	ld.w	%r6,[%r12]
	ext	0xc		; 	xld.w	%r7, [%r12+0xc]		; %r7 = count = tone->count /* 取り出し */
	ld.w	%r7,[%r12]
	;
	not	%r10, %r4			; %r10 = -volume
	add	%r10,0x1	; 	xadd	%r10, %r10, 1
	;
	cmp	%r6,0x0		; 	xcmp	%r6, 0				; %r11 = output = polar ? volume : -volume
	jrne.d	3
	ld.w	%r11, %r4			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
	ext	0x7		; 	xld.w	%r14, 0x1f4		; %r14 = (4000000/SPEAKER_FREQUENCY)*2
	ld.w	%r14,0x34
	ext	0x5		; 	xld.w	%r15, 320			; %r15 = i = SVSOUNDBUFLEN
	ld.w	%r15,0x0
svsound_tone_mix_DO:
	sub	%r7, %r14			; count -= (4000000/SPEAKER_FREQUENCY)*2
	jruge	svsound_tone_mix_NO_ADVANCE	; 	xjruge	svsound_tone_mix_NO_ADVANCE	; if(NonCarry) goto NO_ADVANCE
	;
svsound_tone_mix_ADVANCE:
	add	%r7, %r5			; count += period
	jruge.d	svsound_tone_mix_ADVANCE	; 	xjruge.d svsound_tone_mix_ADVANCE	; if(NonCarry) goto ADVANCE
	xor	%r6, 1				; polar ^= 1 *delay*
	;
	cmp	%r6,0x0		; 	xcmp	%r6, 0				; output = polar ? volume : -volume
	jrne.d	3
	ld.w	%r11, %r4			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
svsound_tone_mix_NO_ADVANCE:
	ld.h	%r9, [%r13]			; *wbuff++ += output
	add	%r9, %r11
	ld.h	[%r13]+, %r9
	;
	sub	%r15,0x1	; 	xsub	%r15, %r15, 1			; if(--i) goto DO
	jrne	svsound_tone_mix_DO	; 	xjrne	svsound_tone_mix_DO
	;
	ext	0x8		; 	xld.w	[%r12+0x8], %r6		; tone->polar = polar /* 書き戻し */
	ld.w	[%r12],%r6
	ext	0xc		; 	xld.w	[%r12+0xc], %r7		; tone->count = count /* 書き戻し */
	ld.w	[%r12],%r7
	;
svsound_tone_mix_EXIT:
	ret

;
;	void svsound_noise_mix(SVSOUNDNOISE* noise, short wbuff[/*SVSOUNDBUFLEN*/])
;
	.global	svsound_noise_mix
svsound_noise_mix:
	btst	[%r12],0x0	; 	xbtst	[%r12+0x0], 0x0		; if(!noise->on) goto EXIT
	jreq	svsound_noise_mix_EXIT	; 	xjreq	svsound_noise_mix_EXIT
	;
	ext	0x4		; 	xld.w	%r4, [%r12+0x4]	; %r4 = volume = noise->volume
	ld.w	%r4,[%r12]
	cmp	%r4,0x0		; 	xcmp	%r4, 0				; if(!volume) goto EXIT
	jreq	svsound_noise_mix_EXIT	; 	xjreq	svsound_noise_mix_EXIT
	;
	ext	0x8		; 	xld.w	%r5, [%r12+0x8]	; %r5 = period = noise->period
	ld.w	%r5,[%r12]
	cmp	%r5,0x0		; 	xcmp	%r5, 0				; if(!period) goto EXIT
	jreq	svsound_noise_mix_EXIT	; 	xjreq	svsound_noise_mix_EXIT
	;
	ext	0xc		; 	xld.w	%r6, [%r12+0xc ]		; %r6 = lfsr  = noise->lfsr  /* 取り出し */
	ld.w	%r6,[%r12]
	ext	0x10		; 	xld.w	%r7, [%r12+0x10]		; %r7 = count = noise->count /* 取り出し */
	ld.w	%r7,[%r12]
	;
	not	%r10, %r4			; %r10 = -volume
	add	%r10,0x1	; 	xadd	%r10, %r10, 1
	;
	ext	0x1		; 	xand	%r9, %r6, 1			; %r11 = output = (lfsr & 1) ? volume : -volume
	and	%r9,%r6
	jrne.d	3
	ld.w	%r11, %r4			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
	ext	0x5		; 	xld.w	%r15, 320			; %r15 = i = SVSOUNDBUFLEN
	ld.w	%r15,0x0
svsound_noise_mix_DO:
	sub	%r7,0x1		; 	xsub	%r7, %r7, 1			; count--
	jruge	svsound_noise_mix_NO_ADVANCE	; 	xjruge	svsound_noise_mix_NO_ADVANCE	; if(NonCarry) goto NO_ADVANCE
	;
svsound_noise_mix_ADVANCE:
	ld.w	%r9, %r6			; %r9 = x = (lfsr ^ (lfsr >> 5)) & 1
	srl	%r9,0x5		; 	xsrl	%r9, 5
	xor	%r9, %r6
	and	%r9,0x1		; 	xand	%r9, %r9, 1
	srl	%r6,0x1		; 	xsrl	%r6, 1				; lfsr = (lfsr >> 1) | (x << 8)
	sll	%r9,0x8		; 	xsll	%r9, 8
	;or	%r6, %r9			; ---------------------------+
	;					;                            |
	add	%r7, %r5			; count += period            |
	jruge.d	svsound_noise_mix_ADVANCE	; 	xjruge.d svsound_noise_mix_ADVANCE	; if(NonCarry) goto ADVANCE  |
	 or	%r6, %r9			; *delay* <------------------+
	;
	ext	0x1		; 	xand	%r9, %r6, 1			; %r11 = output = (lfsr & 1) ? volume : -volume
	and	%r9,%r6
	jrne.d	3
	ld.w	%r11, %r4			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
svsound_noise_mix_NO_ADVANCE:
	ld.h	%r9, [%r13]			; *wbuff++ += output
	add	%r9, %r11
	ld.h	[%r13]+, %r9
	;
	sub	%r15,0x1	; 	xsub	%r15, %r15, 1			; if(--i) goto DO
	jrne	svsound_noise_mix_DO	; 	xjrne	svsound_noise_mix_DO
	;
	ext	0xc		; 	xld.w	[%r12+0xc ], %r6		; noise->lfsr  = lfsr  /* 書き戻し */
	ld.w	[%r12],%r6
	ext	0x10		; 	xld.w	[%r12+0x10], %r7		; noise->count = count /* 書き戻し */
	ld.w	[%r12],%r7
	;
svsound_noise_mix_EXIT:
	ret

;
;	void svsound_volume_shift(short wbuff[/*SVSOUNDBUFLEN*/])
;
	.global svsound_volume_shift
svsound_volume_shift:
	; %r12 = wbuff
	ext	0x5		; 	xld.w %r13, 320			; SVSOUNDBUFLEN = 320
	ld.w	%r13,0x0
	ext	0x1ff		; 	xld.w %r4, 32767
	ld.w	%r4,0x3f
	not %r5, %r4			; -32768
svsound_volume_shift_DO:
	ld.h %r6, [%r12]
	sll	%r6,0x8		; 	xsll %r6, 0xa
	sll	%r6,0x2
	cmp %r6, %r4
	jrle.d 3
	cmp %r6, %r5			; *delay*
	ld.w %r6, %r4			; (skip?)
	jrge.d 3
	sub %r13, 1			; *delay*
	ld.w %r6, %r5			; (skip?)
	ld.h [%r12]+, %r6
	jrne	svsound_volume_shift_DO	; 	xjrne svsound_volume_shift_DO
	ret

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