1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20//
21// snd_mixa.s
22// x86 assembly-language sound code
23//
24
25#include "asm_i386.h"
26#include "quakeasm.h"
27
28#if	id386
29
30	.text
31
32//----------------------------------------------------------------------
33// 8-bit sound-mixing code
34//----------------------------------------------------------------------
35
36#define ch		4+16
37#define sc		8+16
38#define count	12+16
39
40.globl C(SND_PaintChannelFrom8)
41C(SND_PaintChannelFrom8):
42	pushl	%esi				// preserve register variables
43	pushl	%edi
44	pushl	%ebx
45	pushl	%ebp
46
47//	int 	data;
48//	short	*lscale, *rscale;
49//	unsigned char *sfx;
50//	int		i;
51
52	movl	ch(%esp),%ebx
53	movl	sc(%esp),%esi
54
55//	if (ch->leftvol > 255)
56//		ch->leftvol = 255;
57//	if (ch->rightvol > 255)
58//		ch->rightvol = 255;
59	movl	ch_leftvol(%ebx),%eax
60	movl	ch_rightvol(%ebx),%edx
61	cmpl	$255,%eax
62	jna		LLeftSet
63	movl	$255,%eax
64LLeftSet:
65	cmpl	$255,%edx
66	jna		LRightSet
67	movl	$255,%edx
68LRightSet:
69
70//	lscale = snd_scaletable[ch->leftvol >> 3];
71//	rscale = snd_scaletable[ch->rightvol >> 3];
72//	sfx = (signed char *)sc->data + ch->pos;
73//	ch->pos += count;
74	andl	$0xF8,%eax
75	addl	$(sfxc_data),%esi
76	andl	$0xF8,%edx
77	movl	ch_pos(%ebx),%edi
78	movl	count(%esp),%ecx
79	addl	%edi,%esi
80	shll	$7,%eax
81	addl	%ecx,%edi
82	shll	$7,%edx
83	movl	%edi,ch_pos(%ebx)
84	addl	$(C(snd_scaletable)),%eax
85	addl	$(C(snd_scaletable)),%edx
86	subl	%ebx,%ebx
87	movb	-1(%esi,%ecx,1),%bl
88
89	testl	$1,%ecx
90	jz		LMix8Loop
91
92	movl	(%eax,%ebx,4),%edi
93	movl	(%edx,%ebx,4),%ebp
94	addl	C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
95	addl	C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
96	movl	%edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
97	movl	%ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
98	movb	-2(%esi,%ecx,1),%bl
99
100	decl	%ecx
101	jz		LDone
102
103//	for (i=0 ; i<count ; i++)
104//	{
105LMix8Loop:
106
107//		data = sfx[i];
108//		paintbuffer[i].left += lscale[data];
109//		paintbuffer[i].right += rscale[data];
110	movl	(%eax,%ebx,4),%edi
111	movl	(%edx,%ebx,4),%ebp
112	addl	C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size),%edi
113	addl	C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size),%ebp
114	movb	-2(%esi,%ecx,1),%bl
115	movl	%edi,C(paintbuffer)+psp_left-psp_size(,%ecx,psp_size)
116	movl	%ebp,C(paintbuffer)+psp_right-psp_size(,%ecx,psp_size)
117
118	movl	(%eax,%ebx,4),%edi
119	movl	(%edx,%ebx,4),%ebp
120	movb	-3(%esi,%ecx,1),%bl
121	addl	C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size),%edi
122	addl	C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size),%ebp
123	movl	%edi,C(paintbuffer)+psp_left-psp_size*2(,%ecx,psp_size)
124	movl	%ebp,C(paintbuffer)+psp_right-psp_size*2(,%ecx,psp_size)
125
126//	}
127	subl	$2,%ecx
128	jnz		LMix8Loop
129
130LDone:
131	popl	%ebp
132	popl	%ebx
133	popl	%edi
134	popl	%esi
135
136	ret
137
138
139//----------------------------------------------------------------------
140// Transfer of stereo buffer to 16-bit DMA buffer code
141//----------------------------------------------------------------------
142
143.globl C(Snd_WriteLinearBlastStereo16)
144C(Snd_WriteLinearBlastStereo16):
145	pushl	%esi				// preserve register variables
146	pushl	%edi
147	pushl	%ebx
148
149//	int		i;
150//	int		val;
151	movl	C(snd_linear_count),%ecx
152	movl	C(snd_p),%ebx
153	movl	C(snd_vol),%esi
154	movl	C(snd_out),%edi
155
156//	for (i=0 ; i<snd_linear_count ; i+=2)
157//	{
158LWLBLoopTop:
159
160//		val = (snd_p[i]*snd_vol)>>8;
161//		if (val > 0x7fff)
162//			snd_out[i] = 0x7fff;
163//		else if (val < (short)0x8000)
164//			snd_out[i] = (short)0x8000;
165//		else
166//			snd_out[i] = val;
167	movl	-8(%ebx,%ecx,4),%eax
168	imull	%esi,%eax
169	sarl	$8,%eax
170	cmpl	$0x7FFF,%eax
171	jg		LClampHigh
172	cmpl	$0xFFFF8000,%eax
173	jnl		LClampDone
174	movl	$0xFFFF8000,%eax
175	jmp		LClampDone
176LClampHigh:
177	movl	$0x7FFF,%eax
178LClampDone:
179
180//		val = (snd_p[i+1]*snd_vol)>>8;
181//		if (val > 0x7fff)
182//			snd_out[i+1] = 0x7fff;
183//		else if (val < (short)0x8000)
184//			snd_out[i+1] = (short)0x8000;
185//		else
186//			snd_out[i+1] = val;
187	movl	-4(%ebx,%ecx,4),%edx
188	imull	%esi,%edx
189	sarl	$8,%edx
190	cmpl	$0x7FFF,%edx
191	jg		LClampHigh2
192	cmpl	$0xFFFF8000,%edx
193	jnl		LClampDone2
194	movl	$0xFFFF8000,%edx
195	jmp		LClampDone2
196LClampHigh2:
197	movl	$0x7FFF,%edx
198LClampDone2:
199	shll	$16,%edx
200	andl	$0xFFFF,%eax
201	orl		%eax,%edx
202	movl	%edx,-4(%edi,%ecx,2)
203
204//	}
205	subl	$2,%ecx
206	jnz		LWLBLoopTop
207
208//	snd_p += snd_linear_count;
209
210	popl	%ebx
211	popl	%edi
212	popl	%esi
213
214	ret
215
216
217#endif	// id386
218
219