;	
;	clipuvia.s
;
;	P/ECE Signetics 2637 UVI(Universal Video Interface) Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Sat Apr 30 13:14:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;
;#define UVI_DEFINE_OFFSET
;#include "clipuvia.h"
;/	
;/	clipuvia.h
;/
;/	P/ECE Signetics 2637 UVI(Universal Video Interface) Emulator
;/
;/	CLiP - Common Library for P/ECE
;/	Copyright (C) 2001-2005 Naoyuki Sawa
;/
;/	* Sat Apr 30 13:14:00 JST 2005 Naoyuki Sawa
;/	- 作成開始。
;/

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

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

;* clipuvia.s、framuvia.sからのinclude時のみ、以下の定義を有効にします。 */
;#ifdef UVI_DEFINE_OFFSET
;****************************************************************************
;	
;****************************************************************************

				; typedef struct _UVIOBJ {
;#define OBJ_SIZE	 0	; 	unsigned char size;				/* + 0,1: サイズ (0=標準,1=縦2倍拡大) */
;#define OBJ_COLOR	 1	; 	unsigned char color;				/* + 1,1: カラー */
;#define OBJ_RESV	 2	; 	short resv;					/* + 2,2: (予約) */
;#define OBJ_X		 4	; 	short x;					/* + 4,2: X座標 */
;#define OBJ_Y		 6	; 	short y;					/* + 6,2: Y座標 */
;#define OBJ_FONT	 8	; 	unsigned char* font/*[8]*/;			/* + 8,4: フォント */
;#define SIZEOF_UVIOBJ	12	; } UVIOBJ;						/* =12 */

				; typedef struct _UVI {
				; 	/*---------- Video ----------*/
;#define RAM		  0	; 	unsigned char* ram/*[0x400]*/;			/* +  0,  4: 外部RAM、内部レジスタ */
;#define VBUFF		  4	; 	unsigned char* vbuff/*[128*208]*/;		/* +  4,  4: 現在の仮想画面 (NULL=実描画無し) */
;#define SCAN_START	  8	; 	short scan_start;				/* +  8,  2: 前回のスキャンライン位置 (描画区間上端  ) */
;#define SCAN_END	 10	; 	short scan_end;					/* + 10,  2: 現在のスキャンライン位置 (描画区間下端+1) */
;#define SCROLL_Y	 12	; 	short scroll_y;					/* + 12,  2: 垂直スクロール (フレーム単位) */
;#define SCROLL_X	 14	; 	char  scroll_x[26/*Row*/];			/* + 14, 26: 水平スクロール (-1:行未取得、0..7:取得済) */
;#define BG		 40	; 	unsigned short bg[26/*Row*/][16/*Col*/];	/* + 40,832: BG (000000cc0gffffff c=Color,g=GM,f=Code) */
;#define COLOR		872	; 	unsigned char color[4/*B7:6*/][2/*Font*/];	/* +872,  8: BGカラー */
;#define POT		880	; 	unsigned char pot[4];				/* +880,  4: A/D Potentiometer */
;#define OBJ		884	; 	UVIOBJ obj[4];					/* +884, 48: OBJ1,OBJ2,OBJ3,OBJ4 */
				; 	/*---------- Sound ----------*/
;#define TONE_COUNT	932	; 	int tone_count;					/* +932,  4: Tone  進行カウンタ */
;#define NOISE_COUNT	936	; 	int noise_count;				/* +936,  4: Noise 進行カウンタ */
;#define TONE_POLAR	940	; 	unsigned short tone_polar;			/* +940,  2: Tone  出力極性 */
;#define NOISE_LFSR	942	; 	unsigned short noise_lfsr;			/* +942,  2: Noise Linear Feedback Shift Register */
;#define SIZEOF_UVI	944	; } UVI;						/* =944 */

;****************************************************************************
;	
;****************************************************************************
;#endif /*UVI_DEFINE_OFFSET*/
;#ifdef UVI_ASM

	.code
	.align	1

;****************************************************************************
;	内部関数 (Video)
;****************************************************************************


;****************************************************************************
;	内部関数 (Sound)
;****************************************************************************

;#define	NTSC_COLOR_SUBCARRIER 3579545	; -> clipemu.h
;#define UVIBUFLEN 320			; -> clipuvi.h
;#define UVI_VOLUME_SHIFT ((16-5)+1)	; -> clipuvi.c

;----------------------------------------------------------------------------

;
;	void uvi_tone_mix(short wbuff[/*UVIBUFLEN*/], int volume, int period)
;
	.global	uvi_tone_mix
uvi_tone_mix:
	ext	uvi+0x3ac@ah	; 	xld.uh	%r4, [uvi+0x3ac]		; %r4 = polar = uvi.tone_polar /* 取り出し */
	ext	uvi+0x3ac@al
	ld.uh	%r4,[%r8]
	ext	uvi+0x3a4@ah	; 	xld.w	%r5, [uvi+0x3a4]		; %r5 = count = uvi.tone_count /* 取り出し */
	ext	uvi+0x3a4@al
	ld.w	%r5,[%r8]
	;
	not	%r10, %r13			; %r10 = -volume
	add	%r10,0x1	; 	xadd	%r10, %r10, 1
	;
	cmp	%r4,0x0		; 	xcmp	%r4, 0				; %r11 = output = polar ? volume : -volume
	jrne.d	3
	ld.w	%r11, %r13			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
	ext	0x6		; 	xld.w	%r6, 3579545	; %r6 = NTSC_COLOR_SUBCARRIER
	ext	0x1a7a
	ld.w	%r6,0x19
	ext	0x5		; 	xld.w	%r7, 320			; %r7 = i = UVIBUFLEN
	ld.w	%r7,0x0
uvi_tone_mix_DO:
	sub	%r5, %r6			; count -= NTSC_COLOR_SUBCARRIER
	jruge	uvi_tone_mix_NO_ADVANCE	; 	xjruge	uvi_tone_mix_NO_ADVANCE		; if(NonCarry) goto NO_ADVANCE
	;
uvi_tone_mix_ADVANCE:
	add	%r5, %r14			; count += period
	jruge.d	uvi_tone_mix_ADVANCE	; 	xjruge.d uvi_tone_mix_ADVANCE		; if(NonCarry) goto ADVANCE
	xor	%r4, 1				; polar ^= 1 *delay*
	;
	cmp	%r4,0x0		; 	xcmp	%r4, 0				; output = polar ? volume : -volume
	jrne.d	3
	ld.w	%r11, %r13			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
uvi_tone_mix_NO_ADVANCE:
	ld.h	%r9, [%r12]			; *wbuff++ += output
	add	%r9, %r11
	ld.h	[%r12]+, %r9
	;
	sub	%r7,0x1		; 	xsub	%r7, %r7, 1			; if(--i) goto DO
	jrne	uvi_tone_mix_DO	; 	xjrne	uvi_tone_mix_DO
	;
	ext	uvi+0x3ac@ah	; 	xld.h	[uvi+0x3ac], %r4		; uvi.tone_polar = polar /* 書き戻し */
	ext	uvi+0x3ac@al
	ld.h	[%r8],%r4
	ext	uvi+0x3a4@ah	; 	xld.w	[uvi+0x3a4], %r5		; uvi.tone_count = count /* 書き戻し */
	ext	uvi+0x3a4@al
	ld.w	[%r8],%r5
	;
uvi_tone_mix_EXIT:
	ret

;----------------------------------------------------------------------------

;
;	void uvi_noise_mix(short wbuff[/*UVIBUFLEN*/], int volume, int period)
;
	.global	uvi_noise_mix
uvi_noise_mix:
	ext	uvi+0x3ae@ah	; 	xld.uh	%r4, [uvi+0x3ae ]		; lfsr  = uvi.noise_lfsr  /* 取り出し */
	ext	uvi+0x3ae@al
	ld.uh	%r4,[%r8]
	ext	uvi+0x3a8@ah	; 	xld.w	%r5, [uvi+0x3a8]		; count = uvi.noise_count /* 取り出し */
	ext	uvi+0x3a8@al
	ld.w	%r5,[%r8]
	;
	not	%r10, %r13			; %r10 = -volume
	add	%r10,0x1	; 	xadd	%r10, %r10, 1
	;
	ext	0x1		; 	xand	%r9, %r4, 1			; %r11 = output = (lfsr & 1) ? volume : -volume
	and	%r9,%r4
	jrne.d	3
	ld.w	%r11, %r13			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
	ext	0x6		; 	xld.w	%r6, 3579545	; %r6 = NTSC_COLOR_SUBCARRIER
	ext	0x1a7a
	ld.w	%r6,0x19
	ext	0x5		; 	xld.w	%r7, 320			; %r7 = i = UVIBUFLEN
	ld.w	%r7,0x0
uvi_noise_mix_DO:
	sub	%r5, %r6			; count -= NTSC_COLOR_SUBCARRIER
	jruge	uvi_noise_mix_NO_ADVANCE	; 	xjruge	uvi_noise_mix_NO_ADVANCE	; if(NonCarry) goto NO_ADVANCE
	;
uvi_noise_mix_ADVANCE:
	ld.w	%r9, %r4			; %r9 = x = (lfsr ^ (lfsr >> 5)) & 1
	srl	%r9,0x5		; 	xsrl	%r9, 5
	xor	%r9, %r4
	and	%r9,0x1		; 	xand	%r9, %r9, 1
	srl	%r4,0x1		; 	xsrl	%r4, 1				; lfsr = (lfsr >> 1) | (x << 8)
	sll	%r9,0x8		; 	xsll	%r9, 8
	;or	%r4, %r9			; ---------------------------+
	;					;                            |
	add	%r5, %r14			; count += period            |
	jruge.d	uvi_noise_mix_ADVANCE	; 	xjruge.d uvi_noise_mix_ADVANCE		; if(NonCarry) goto ADVANCE  |
	 or	%r4, %r9			; *delay* <------------------+
	;
	ext	0x1		; 	xand	%r9, %r4, 1			; %r11 = output = (lfsr & 1) ? volume : -volume
	and	%r9,%r4
	jrne.d	3
	ld.w	%r11, %r13			; *delay*
	ld.w	%r11, %r10			; (skip?)
	;
uvi_noise_mix_NO_ADVANCE:
	ld.h	%r9, [%r12]			; *wbuff++ += output
	add	%r9, %r11
	ld.h	[%r12]+, %r9
	;
	sub	%r7,0x1		; 	xsub	%r7, %r7, 1			; if(--i) goto DO
	jrne	uvi_noise_mix_DO	; 	xjrne	uvi_noise_mix_DO
	;
	ext	uvi+0x3ae@ah	; 	xld.h	[uvi+0x3ae ], %r4		; uvi.noise_lfsr  = lfsr  /* 書き戻し */
	ext	uvi+0x3ae@al
	ld.h	[%r8],%r4
	ext	uvi+0x3a8@ah	; 	xld.w	[uvi+0x3a8], %r5		; uvi.noise_count = count /* 書き戻し */
	ext	uvi+0x3a8@al
	ld.w	[%r8],%r5
	;
uvi_noise_mix_EXIT:
	ret

;----------------------------------------------------------------------------

;
;	void uvi_volume_shift(short wbuff[/*UVIBUFLEN*/])
;
	.global uvi_volume_shift
uvi_volume_shift:
	; %r12 = wbuff
	ext	0x5		; 	xld.w %r13, 320
	ld.w	%r13,0x0
	ext	0x1ff		; 	xld.w %r4, 32767
	ld.w	%r4,0x3f
	not %r5, %r4			; -32768
uvi_volume_shift_DO:
	ld.h %r6, [%r12]
	sll	%r6,0x8		; 	xsll %r6, 0xc
	sll	%r6,0x4
	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	uvi_volume_shift_DO	; 	xjrne uvi_volume_shift_DO
	ret

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

;#endif /*UVI_ASM*/
