;	
;	framdms2.c
;
;	P/ECE DMG-Sound Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Mon Feb 28 20:00:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;

	.code
	.align 1

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

;-------------------------------------------------------------------------------------------------------------------------------------------------------------- 
					; /* Ch1,2: 矩形波 */
					; typedef struct _DMGSOUND2SQUARE {
					; 	/*** Length ***/
;#define SQUARE_SOUND_LENGTH	 0	; 	int sound_length;		// + 0,4: 残り発声時間を(1/256[sec])単位で示します。
				  	; 					//          -1ならば、明示的に停止するまで発声を続けます。
				  	; 					//           0ならば、停止中であることを示します。
					; 
					; 	/*** Envelope ***/
;#define SQUARE_ENVELOPE_TIME	 4	; 	unsigned char envelope_time;	// + 4,1: エンベロープ実行間隔を(1/256[sec])単位で示します。
				  	; 					//          0ならば、エンベロープを行いません。
;#define SQUARE_ENVELOPE_TYPE	 5	; 	unsigned char envelope_type;	// + 5,1: エンベロープ方向を示します。
				  	; 					//          0ならば、音量を減少します。(音が小さくなる)
				  	; 					//          1ならば、音量を増加します。(音が大きくなる)
;#define SQUARE_ENVELOPE_VOLUME	 6	; 	unsigned char envelope_volume;	// + 6,1: 現在のエンベロープ音量を示します。(0..15)
				  	; 					//          0で消音、15で最大音量となります。
;#define SQUARE_ENVELOPE_COUNT	 7	; 	unsigned char envelope_count;	// + 7,1: 次回エンベロープ実行までのダウンカウンタです。
					; 
					; 	/*** Sweep (Ch1のみ) ***/
;#define SQUARE_SWEEP_TIME	 8	; 	unsigned char sweep_time;	// + 8,1: スイープ実行間隔を(1/256[sec])単位で示します。
				  	; 					//          0ならば、スイープを行いません。
				  	; 					//          Ch2はスイープ機能が無いので、0固定とします。
;#define SQUARE_SWEEP_TYPE	 9	; 	unsigned char sweep_type;	// + 9,1: スイープ方向を示します。
				  	; 					//          0ならば、周波数を増加します。(音が高くなる)
				  	; 					//          1ならば、周波数を減少します。(音が低くなる)
;#define SQUARE_SWEEP_SHIFT	10	; 	unsigned char sweep_shift;	// +10,1: 周波数変化量のシフト数を示します。
				  	; 					//          スイープを一回実行することによる周波数変化は、次の通りです。
				  	; 					//          frequency(t) = frequency(t-1) ± frequency(t-1)>>sweep_shift
;#define SQUARE_SWEEP_COUNT	11	; 	unsigned char sweep_count;	// +11,1: 次回スイープ実行までのダウンカウンタです。
					; 
					; 	/*** Wave ***/
;#define SQUARE_WAVE_DUTY	12	; 	unsigned char wave_duty;	// +12,1: 矩形波のデューティ比を示します。
				  	; 					//                    01234567
				  	; 					//          1: 12.5% (_-------)
				  	; 					//          2: 25  % (__------)
				  	; 					//          4: 50  % (____----)
				  	; 					//          6: 75  % (______--)
;#define SQUARE_WAVE_INDEX	13	; 	unsigned char wave_index;	// +13,1: 波形サンプル単位の進行カウンタです。(0..7)
				  	; 					//          (wave_index＜wave_duty)ならば、(-envelope_volume)を出力します。
				  	; 					//          (wave_index≧wave_duty)ならば、(+envelope_volume)を出力します。
;#define SQUARE_WAVE_FREQUENCY	14	; 	short wave_frequency;		// +14,2: 周波数を示します。(0x000..0x7ff)
				  	; 					//          矩形波1波形単位の再生周波数は、
				  	; 					//            Frequency = 4194304/(32*(2048-x))[Hz] (仕様)
				  	; 					//          矩形波1波形分のサイクル数を、マスタークロックの倍数で表すと、
				  	; 					//            Period    = (2048-x)*32
				  	; 					//          矩形波1波形が8サンプルと見なすと、1サンプル分のサイクル数は、
				  	; 					//            Period    = (2048-x)*32/8
				  	; 					//                      = (2048-x)*4
;#define SQUARE_WAVE_COUNT	16	; 	int wave_count;			// +16,4: マスタークロック単位の進行カウンタです。
					; 
					; 	/*** Speaker ***/
;#define SQUARE_SPEAKER_VOLUME	20	; 	unsigned char speaker_volume;	// +20,1: 出力先スピーカー(左、右、または両方)の合計ボリューム (0..14)
					; } DMGSOUND2SQUARE;
;-------------------------------------------------------------------------------------------------------------------------------------------------------------- 
					; /* Ch3: 波形メモリ */
					; typedef struct _DMGSOUND2WAVE {
					; 	/*** Length ***/
;#define WAVE_SOUND_LENGTH	 0	; 	int sound_length;		// + 0,4: 残り発声時間を(1/256[sec])単位で示します。
				  	; 					//          -1ならば、明示的に停止するまで発声を続けます。
				  	; 					//           0ならば、停止中であることを示します。
					; 
					; 	/*** Wave ***/
;#define WAVE_WAVE_SHIFT		 4	; 	unsigned char wave_shift;	// + 4,1: 波形データの出力レベルを示します。
				  	; 					//          0: 消音
				  	; 					//          1: そのまま出力
				  	; 					//          2: 1bit右シフトして出力
				  	; 					//          3: 2bit右シフトして出力
;#define WAVE_WAVE_INDEX		 5	; 	unsigned char wave_index;	// + 5,1: 波形サンプル単位の進行カウンタです。(0..31)
				  	; 					//          (wave_pattern[wave_index]>>(wave_shift-1))を出力します。
;#define WAVE_WAVE_FREQUENCY	 6	; 	short wave_frequency;		// + 6,2: 周波数を示します。(0x000..0x7ff)
				  	; 					//          矩形パターン1波形単位の再生周波数は、
				  	; 					//            Frequency = 4194304/(64*(2048-x))[Hz] (仕様)
				  	; 					//          波形パターン1波形分のサイクル数を、マスタークロックの倍数で表すと、
				  	; 					//            Period    = (2048-x)*64
				  	; 					//          波形パターン1波形が32サンプルと見なすと、1サンプル分のサイクル数は、
				  	; 					//            Period    = (2048-x)*64/32
				  	; 					//                      = (2048-x)*2
;#define WAVE_WAVE_COUNT		 8	; 	int wave_count;			// + 8,4: マスタークロック単位の進行カウンタです。
					; 
					; 	/*** Speaker ***/
;#define WAVE_SPEAKER_VOLUME	12	; 	unsigned char speaker_volume;	// +12,1: 出力先スピーカー(左、右、または両方)の合計ボリューム (0..14)
					; } DMGSOUND2WAVE;
;-------------------------------------------------------------------------------------------------------------------------------------------------------------- 
					; /* Ch4: ノイズ */
					; typedef struct _DMGSOUND2NOISE {
					; 	/*** Length ***/
;#define NOISE_SOUND_LENGTH	 0	; 	int sound_length;		// + 0,4: 残り発声時間を(1/256[sec])単位で示します。
				  	; 					//          -1ならば、明示的に停止するまで発声を続けます。
				  	; 					//           0ならば、停止中であることを示します。
					; 
					; 	/*** Envelope ***/
;#define NOISE_ENVELOPE_TIME	 4	; 	unsigned char envelope_time;	// + 4,1: エンベロープ実行間隔を(1/256[sec])単位で示します。
				  	; 					//          0ならば、エンベロープを行いません。
;#define NOISE_ENVELOPE_TYPE	 5	; 	unsigned char envelope_type;	// + 5,1: エンベロープ方向を示します。
				  	; 					//          0ならば、音量を減少します。(音が小さくなる)
				  	; 					//          1ならば、音量を増加します。(音が大きくなる)
;#define NOISE_ENVELOPE_VOLUME	 6	; 	unsigned char envelope_volume;	// + 6,1: 現在のエンベロープ音量を示します。(0..15)
				  	; 					//          0で消音、15で最大音量となります。
;#define NOISE_ENVELOPE_COUNT	 7	; 	unsigned char envelope_count;	// + 7,1: 次回エンベロープ実行までのダウンカウンタです。
					; 
					; 	/*** LFSR ***/
;#define NOISE_LFSR_TYPE		 8	; 	unsigned char lfsr_type;	// + 8,1: 1 = 15 steps (long mode), 6 = 7 steps (short mode)
				  	; 					//          正しい仕様がわからないので、ファミコンAPU互換で実装してみました。
					; 					// + 9,1: (パディング)
;#define NOISE_LFSR		10	; 	unsigned short lfsr;		// +10,2: LFSR (Linear Feedback Shift Register)
;#define NOISE_LFSR_FREQUENCY	12	; 	int lfsr_frequency;		// +12,4: マスタークロックサイクル単位のLFSRシフト周期を示します。
				  	; 					//          {1,2,4,6,8,10,12,14}<<{3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}
;#define NOISE_LFSR_COUNT	16	; 	int lfsr_count;			// +16,4: マスタークロック単位の進行カウンタです。
					; 
					; 	/*** Speaker ***/
;#define NOISE_SPEAKER_VOLUME	20	; 	unsigned char speaker_volume;	// +20,1: 出力先スピーカー(左、右、または両方)の合計ボリューム (0..14)
					; } DMGSOUND2NOISE;
;-------------------------------------------------------------------------------------------------------------------------------------------------------------- 

;#define SPEAKER_FREQUENCY	16000			; -> clipmisc.h
;#define DMGSOUND2_CLOCK		(1<<22)			; -> clipdms2.h
;#define DMGSOUND2_PERIOD_MIN	(DMGSOUND2_CLOCK/16)	; -> clipdms2.c
;#define DMGSOUND2_VOLUME_SHIFT	((16-11)+1)		; -> clipdms2.c

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

	.global	dmgsound2_square_mix
dmgsound2_square_mix:
	ld.w	%r9,[%r12]	; 	xld.w	%r9, [%r12+0x0]		; if(!ch->sound_length) goto EXIT
	cmp	%r9,0x0		; 	xcmp	%r9, 0
	jreq	dmgsound2_square_mix_EXIT	; 	xjreq	dmgsound2_square_mix_EXIT
	;
	ext	0x6		; 	xld.ub	%r4, [%r12+0x6]	; %r4 = volume = ch->envelope_volume * ch->speaker_volume
	ld.ub	%r4,[%r12]
	ext	0x14		; 	xld.ub	%r9, [%r12+0x14]
	ld.ub	%r9,[%r12]
	mlt.h	%r4, %r9
	ld.w	%r4, %alr
	cmp	%r4,0x0		; 	xcmp	%r4, 0					; if(!volume) goto EXIT
	jreq	dmgsound2_square_mix_EXIT	; 	xjreq	dmgsound2_square_mix_EXIT
	;
	ext	0x20		; 	xld.w	%r5, 2048				; %r5 = period = (2048 - ch->wave_frequency) * 4 * SPEAKER_FREQUENCY
	ld.w	%r5,0x0
	ext	0xe		; 	xld.h	%r9, [%r12+0xe]
	ld.h	%r9,[%r12]
	sub	%r5, %r9
	ext	0x3e8		; 	xld.w	%r9, 0xfa00
	ld.w	%r9,0x0
	mltu.h	%r5, %r9				; (4*SPEAKER_FREQUENCY=64000なので、mlt.hではなくmltu.hを使う必要があります)
	ld.w	%r5, %alr
	ext	0x0		; 	xcmp	%r5, 0x40000		; if(period < DMGSOUND2_PERIOD_MIN) period = DMGSOUND2_PERIOD_MIN
	ext	0x1000
	cmp	%r5,0x0
	jrge	dmgsound2_square_mix_L10	; 	xjrge	dmgsound2_square_mix_L10
	ext	0x0		; 	xld.w	%r5, 0x40000
	ext	0x1000
	ld.w	%r5,0x0
dmgsound2_square_mix_L10:
	;
	ext	0xc		; 	xld.ub	%r6, [%r12+0xc]		; %r6 = wave_duty = ch->wave_duty
	ld.ub	%r6,[%r12]
	;
	ext	0xd		; 	xld.ub	%r14, [%r12+0xd]		; %r14 = wave_index = ch->wave_index
	ld.ub	%r14,[%r12]
	ext	0x10		; 	xld.w	%r15, [%r12+0x10]		; %r15 = wave_count = ch->wave_count
	ld.w	%r15,[%r12]
	;
	cmp	%r14, %r6				; output = (wave_index < wave_duty) ? -volume : +volume
	jrge.d	4
	ld.w	%r7, %r4				; *delay*
	not	%r7, %r4				; (skip?)
	add	%r7, 1					; (skip?)
	;
	ext	0x8		; 	xld.w	%r10, 0x400000			; %r10 = DMGSOUND2_CLOCK
	ext	0x0
	ld.w	%r10,0x0
	ext	0x1		; 	xld.w	%r11, 64				; %r11 = i = 64
	ld.w	%r11,0x0
dmgsound2_square_mix_DO:
	sub	%r15, %r10				; wave_count -= DMGSOUND2_CLOCK
	jruge	dmgsound2_square_mix_NO_ADVANCE	; 	xjruge	dmgsound2_square_mix_NO_ADVANCE		; if(NonCarry) goto NO_ADVANCE
	;
dmgsound2_square_mix_ADVANCE:
	add	%r15, %r5				; wave_count += period
	jruge.d	dmgsound2_square_mix_ADVANCE	; 	xjruge.d	dmgsound2_square_mix_ADVANCE	; if(NonCarry) goto ADVANCE
	add	%r14, 1					; wave_index++ *delay*
	;
	and	%r14,0x7	; 	xand	%r14, %r14, 7				; wave_index &= 7
	;
	cmp	%r14, %r6				; output = (wave_index < wave_duty) ? -volume : +volume
	jrge.d	4
	ld.w	%r7, %r4				; *delay*
	not	%r7, %r4				; (skip?)
	add	%r7, 1					; (skip?)
	;
dmgsound2_square_mix_NO_ADVANCE:
	ld.h	%r9, [%r13]				; *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1				; if(--i) goto DO
	jrne	dmgsound2_square_mix_DO	; 	xjrne	dmgsound2_square_mix_DO
	;
	ext	0xd		; 	xld.b	[%r12+0xd], %r14		; ch->wave_index = wave_index
	ld.b	[%r12],%r14
	ext	0x10		; 	xld.w	[%r12+0x10], %r15		; ch->wave_count = wave_count
	ld.w	[%r12],%r15
	;
dmgsound2_square_mix_EXIT:
	ret

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

	.global	dmgsound2_wave_mix
dmgsound2_wave_mix:
	ld.w	%r9,[%r12]	; 	xld.w	%r9, [%r12+0x0]		; if(!ch->sound_length) goto EXIT
	cmp	%r9,0x0		; 	xcmp	%r9, 0
	jreq	dmgsound2_wave_mix_EXIT	; 	xjreq	dmgsound2_wave_mix_EXIT
	;
	ext	0xc		; 	xld.ub	%r4, [%r12+0xc]		; %r4 = volume = ch->speaker_volume
	ld.ub	%r4,[%r12]
	cmp	%r4,0x0		; 	xcmp	%r4, 0					; if(!volume) goto EXIT
	jreq	dmgsound2_wave_mix_EXIT	; 	xjreq	dmgsound2_wave_mix_EXIT
	;
	ext	0x20		; 	xld.w	%r5, 2048				; %r5 = period = (2048 - ch->wave_frequency) * 2 * SPEAKER_FREQUENCY
	ld.w	%r5,0x0
	ext	0x6		; 	xld.h	%r9, [%r12+0x6]
	ld.h	%r9,[%r12]
	sub	%r5, %r9
	ext	0x1f4		; 	xld.w	%r9, 0x7d00
	ld.w	%r9,0x0
	mlt.h	%r5, %r9				; (2*SPEAKER_FREQUENCY=32000なので、mlt.hでもmltu.hでも構いません)
	ld.w	%r5, %alr
	ext	0x0		; 	xcmp	%r5, 0x40000		; if(period < DMGSOUND2_PERIOD_MIN) period = DMGSOUND2_PERIOD_MIN
	ext	0x1000
	cmp	%r5,0x0
	jrge	dmgsound2_wave_mix_L10	; 	xjrge	dmgsound2_wave_mix_L10
	ext	0x0		; 	xld.w	%r5, 0x40000
	ext	0x1000
	ld.w	%r5,0x0
dmgsound2_wave_mix_L10:
	;
	ext	0x4		; 	xld.ub	%r6, [%r12+0x4]		; %r6 = wave_shift = ch->wave_shift
	ld.ub	%r6,[%r12]
	sub	%r6,0x1		; 	xsub	%r6, %r6, 1				; if((--wave_shift) < 0) goto EXIT
	jrlt	dmgsound2_wave_mix_EXIT	; 	xjrlt	dmgsound2_wave_mix_EXIT
	;
	ext	0x5		; 	xld.ub	%r14, [%r12+0x5]		; %r14 = wave_index = ch->wave_index
	ld.ub	%r14,[%r12]
	ext	0x8		; 	xld.w	%r15, [%r12+0x8]		; %r15 = wave_count = ch->wave_count
	ld.w	%r15,[%r12]
	;
	ext	dmgsound2_wave_pattern@ah		; output = (dmgsound2_wave_pattern[wave_index] >> wave_shift) * volume
	ext	dmgsound2_wave_pattern@al
	ld.b	%r7, [%r14]
	sra	%r7, %r6				; (0≦wave_shift≦2なので、xsraを使う必要はありません。sraで充分です)
	mlt.h	%r7, %r4
	ld.w	%r7, %alr
	;
	ext	0x8		; 	xld.w	%r10, 0x400000			; %r10 = DMGSOUND2_CLOCK
	ext	0x0
	ld.w	%r10,0x0
	ext	0x1		; 	xld.w	%r11, 64				; %r11 = i = 64
	ld.w	%r11,0x0
dmgsound2_wave_mix_DO:
	sub	%r15, %r10				; wave_count -= DMGSOUND2_CLOCK
	jruge	dmgsound2_wave_mix_NO_ADVANCE	; 	xjruge	dmgsound2_wave_mix_NO_ADVANCE		; if(NonCarry) goto NO_ADVANCE
	;
dmgsound2_wave_mix_ADVANCE:
	add	%r15, %r5				; wave_count += period
	jruge.d	dmgsound2_wave_mix_ADVANCE	; 	xjruge.d	dmgsound2_wave_mix_ADVANCE	; if(NonCarry) goto ADVANCE
	add	%r14, 1					; wave_index++ *delay*
	;
	and	%r14,0x1f	; 	xand	%r14, %r14, 31				; wave_index &= 31
	;
	ext	dmgsound2_wave_pattern@ah		; output = (dmgsound2_wave_pattern[wave_index] >> wave_shift) * volume
	ext	dmgsound2_wave_pattern@al
	ld.b	%r7, [%r14]
	sra	%r7, %r6				; (0≦wave_shift≦2なので、xsraを使う必要はありません。sraで充分です)
	mlt.h	%r7, %r4
	ld.w	%r7, %alr
	;
dmgsound2_wave_mix_NO_ADVANCE:
	ld.h	%r9, [%r13]				; *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1				; if(--i) goto DO
	jrne	dmgsound2_wave_mix_DO	; 	xjrne	dmgsound2_wave_mix_DO
	;
	ext	0x5		; 	xld.b	[%r12+0x5], %r14		; ch->wave_index = wave_index
	ld.b	[%r12],%r14
	ext	0x8		; 	xld.w	[%r12+0x8], %r15		; ch->wave_count = wave_count
	ld.w	[%r12],%r15
	;
dmgsound2_wave_mix_EXIT:
	ret

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

	.global	dmgsound2_noise_mix
dmgsound2_noise_mix:
	ld.w	%r9,[%r12]	; 	xld.w	%r9, [%r12+0x0]		; if(!ch->sound_length) goto EXIT
	cmp	%r9,0x0		; 	xcmp	%r9, 0
	jreq	dmgsound2_noise_mix_EXIT	; 	xjreq	dmgsound2_noise_mix_EXIT
	;
	ext	0x6		; 	xld.ub	%r4, [%r12+0x6]	; %r4 = volume = ch->envelope_volume * ch->speaker_volume
	ld.ub	%r4,[%r12]
	ext	0x14		; 	xld.ub	%r9, [%r12+0x14]
	ld.ub	%r9,[%r12]
	mlt.h	%r4, %r9
	ld.w	%r4, %alr
	cmp	%r4,0x0		; 	xcmp	%r4, 0					; if(!volume) goto EXIT
	jreq	dmgsound2_noise_mix_EXIT	; 	xjreq	dmgsound2_noise_mix_EXIT
	;
	ext	0xc		; 	xld.w	%r5, [%r12+0xc]	; %r5 = period = ch->lfsr_frequency * (SPEAKER_FREQUENCY>>7)
	ld.w	%r5,[%r12]
	ext	0x1		; 	xld.w	%r9, 0x7d
	ld.w	%r9,0x3d
	mlt.h	%r5, %r9				; ((SPEAKER_FREQUENCY>>7)=125なので、mlt.hでもmltu.hでも構いません)
	ld.w	%r5, %alr
	ext	0x20		; 	xcmp	%r5, 0x800		; if(period < (DMGSOUND2_PERIOD_MIN>>7)) period = (DMGSOUND2_PERIOD_MIN>>7)
	cmp	%r5,0x0
	jrge	dmgsound2_noise_mix_L10	; 	xjrge	dmgsound2_noise_mix_L10
	ext	0x20		; 	xld.w	%r5, 0x800
	ld.w	%r5,0x0
dmgsound2_noise_mix_L10:
	;
	ext	0x8		; 	xld.ub	%r6, [%r12+0x8]		; %r6 = lfsr_type = ch->lfsr_type
	ld.ub	%r6,[%r12]
	;
	ext	0xa		; 	xld.uh	%r14, [%r12+0xa      ]		; %r14 = lfsr       = ch->lfsr
	ld.uh	%r14,[%r12]
	ext	0x10		; 	xld.w	%r15, [%r12+0x10]		; %r15 = wave_count = ch->wave_count
	ld.w	%r15,[%r12]
	;
	ext	0x1		; 	xand	%r9, %r14, 1				; output = !(lfsr & 1) ? -volume : +volume
	and	%r9,%r14
	jrne.d	4
	ld.w	%r7, %r4				; *delay*
	not	%r7, %r4				; (skip?)
	add	%r7, 1					; (skip?)
	;
	ext	0x200		; 	xld.w	%r10, 0x8000		; %r10 = (DMGSOUND2_CLOCK>>7)
	ld.w	%r10,0x0
	ext	0x1		; 	xld.w	%r11, 64				; %r11 = i = 64
	ld.w	%r11,0x0
dmgsound2_noise_mix_DO:
	sub	%r15, %r10				; wave_count -= (DMGSOUND2_CLOCK>>7)
	jruge	dmgsound2_noise_mix_NO_ADVANCE	; 	xjruge	dmgsound2_noise_mix_NO_ADVANCE		; if(NonCarry) goto NO_ADVANCE
	;
dmgsound2_noise_mix_ADVANCE:
	ld.w	%r9, %r14				; %r9 = v = ((lfsr>>0) ^ (lfsr>>mode)) & 1
	srl	%r9, %r6				; ★ "xsrl %r9,%r6"としてはいけません!!
	xor	%r9, %r14				; ★ xsrlが展開され、%r9が破壊されてしまいます。
	and	%r9, 1					; ★ %r6=mode=1or6なので、xsrlは必要ありません。
	;
	srl	%r14,0x1	; 	xsrl	%r14, 1
	sll	%r9,0x8		; 	xsll	%r9, 14					; lfsr = (lfsr >> 1) | (v << 14)
	sll	%r9,0x6
	;or	%r14, %r9				; ◎ -> 4行下へ移動しました。
	;
	add	%r15, %r5				; wavecount += wavelength
	jruge.d	dmgsound2_noise_mix_ADVANCE	; 	xjruge.d	dmgsound2_noise_mix_ADVANCE	; if(NonCarry) goto ADVANCE
	or	%r14, %r9				; ◎ <- 4行上から移しました。 *delay*
	;
	ext	0x1		; 	xand	%r9, %r14, 1				; output = !(lfsr & 1) ? -volume : +volume
	and	%r9,%r14
	jrne.d	4
	ld.w	%r7, %r4				; *delay*
	not	%r7, %r4				; (skip?)
	add	%r7, 1					; (skip?)
	;
dmgsound2_noise_mix_NO_ADVANCE:
	ld.h	%r9, [%r13]				; *wbuff++ += output
	add	%r9, %r7
	ld.h	[%r13]+, %r9
	;
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1				; if(--i) goto DO
	jrne	dmgsound2_noise_mix_DO	; 	xjrne	dmgsound2_noise_mix_DO
	;
	ext	0xa		; 	xld.h	[%r12+0xa      ], %r14		; ch->lfsr       = lfsr
	ld.h	[%r12],%r14
	ext	0x10		; 	xld.w	[%r12+0x10], %r15		; ch->wave_count = wave_count
	ld.w	[%r12],%r15
	;
dmgsound2_noise_mix_EXIT:
	ret

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

	.global dmgsound2_volume_shift
dmgsound2_volume_shift:
	; %r12 = wbuff
	ext	0x5		; 	xld.w %r13, 320			; DMGSOUND2BUFLEN = 320
	ld.w	%r13,0x0
	ext	0x1ff		; 	xld.w %r4, 32767
	ld.w	%r4,0x3f
	not %r5, %r4			; -32768
dmgsound2_volume_shift_DO:
	ld.h %r6, [%r12]
	sll	%r6,0x6		; 	xsll %r6, 0x6
	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	dmgsound2_volume_shift_DO	; 	xjrne dmgsound2_volume_shift_DO
	ret

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

