comparison src/audio/mint/SDL_mintaudio_mcsn.c @ 644:594422ab8f9f

Atari MiNT: added more audio drivers
author Patrice Mandin <patmandin@gmail.com>
date Mon, 07 Jul 2003 19:16:03 +0000
parents
children c4803992e09c
comparison
equal deleted inserted replaced
643:564716cfb502 644:594422ab8f9f
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22
23 /*
24 MiNT audio driver
25 using XBIOS functions (MacSound compatible driver)
26
27 Patrice Mandin
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 /* Mint includes */
35 #include <mint/osbind.h>
36 #include <mint/falcon.h>
37 #include <mint/cookie.h>
38
39 #include "SDL_endian.h"
40 #include "SDL_audio.h"
41 #include "SDL_audio_c.h"
42 #include "SDL_audiomem.h"
43 #include "SDL_sysaudio.h"
44
45 #include "SDL_atarimxalloc_c.h"
46
47 #include "SDL_mintaudio.h"
48 #include "SDL_mintaudio_mcsn.h"
49
50 /*--- Defines ---*/
51
52 #define MINT_AUDIO_DRIVER_NAME "mint_mcsn"
53
54 /* Debug print info */
55 #define DEBUG_NAME "audio:mcsn: "
56 #if 0
57 #define DEBUG_PRINT(what) \
58 { \
59 printf what; \
60 }
61 #else
62 #define DEBUG_PRINT(what)
63 #endif
64
65 /*--- Static variables ---*/
66
67 static unsigned long cookie_snd, cookie_mch;
68 static cookie_mcsn_t *cookie_mcsn;
69
70 /*--- Audio driver functions ---*/
71
72 static void Mint_CloseAudio(_THIS);
73 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
74 static void Mint_LockAudio(_THIS);
75 static void Mint_UnlockAudio(_THIS);
76
77 /* To check/init hardware audio */
78 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
79 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
80
81 /*--- Audio driver bootstrap functions ---*/
82
83 static int Audio_Available(void)
84 {
85 const char *envr = getenv("SDL_AUDIODRIVER");
86
87 /* Check if user asked a different audio driver */
88 if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
89 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
90 return(0);
91 }
92
93 /* Cookie _MCH present ? if not, assume ST machine */
94 if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
95 cookie_mch = MCH_ST;
96 }
97
98 /* Cookie _SND present ? if not, assume ST machine */
99 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
100 cookie_snd = SND_PSG;
101 }
102
103 /* Check if we have 16 bits audio */
104 if ((cookie_snd & SND_16BIT)==0) {
105 DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
106 return(0);
107 }
108
109 /* Cookie MCSN present ? */
110 if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
111 DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
112 return(0);
113 }
114
115 /* Check if interrupt at end of replay */
116 if (cookie_mcsn->pint == 0) {
117 DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
118 return(0);
119 }
120
121 /* Check if audio is lockable */
122 if (Locksnd()!=1) {
123 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
124 return(0);
125 }
126
127 Unlocksnd();
128
129 DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
130 return(1);
131 }
132
133 static void Audio_DeleteDevice(SDL_AudioDevice *device)
134 {
135 free(device->hidden);
136 free(device);
137 }
138
139 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
140 {
141 SDL_AudioDevice *this;
142
143 /* Initialize all variables that we clean on shutdown */
144 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
145 if ( this ) {
146 memset(this, 0, (sizeof *this));
147 this->hidden = (struct SDL_PrivateAudioData *)
148 malloc((sizeof *this->hidden));
149 }
150 if ( (this == NULL) || (this->hidden == NULL) ) {
151 SDL_OutOfMemory();
152 if ( this ) {
153 free(this);
154 }
155 return(0);
156 }
157 memset(this->hidden, 0, (sizeof *this->hidden));
158
159 /* Set the function pointers */
160 this->OpenAudio = Mint_OpenAudio;
161 this->CloseAudio = Mint_CloseAudio;
162 this->LockAudio = Mint_LockAudio;
163 this->UnlockAudio = Mint_UnlockAudio;
164 this->free = Audio_DeleteDevice;
165
166 return this;
167 }
168
169 AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
170 MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
171 Audio_Available, Audio_CreateDevice
172 };
173
174 static void Mint_LockAudio(_THIS)
175 {
176 /* Stop replay */
177 Buffoper(0);
178 }
179
180 static void Mint_UnlockAudio(_THIS)
181 {
182 /* Restart replay */
183 Buffoper(SB_PLA_ENA|SB_PLA_RPT);
184 }
185
186 static void Mint_CloseAudio(_THIS)
187 {
188 /* Stop replay */
189 Buffoper(0);
190
191 /* Uninstall interrupt */
192 Jdisint(MFP_DMASOUND);
193
194 /* Wait if currently playing sound */
195 while (SDL_MintAudio_mutex != 0) {
196 }
197
198 /* Clear buffers */
199 if (SDL_MintAudio_audiobuf[0]) {
200 Mfree(SDL_MintAudio_audiobuf[0]);
201 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
202 }
203
204 /* Unlock sound system */
205 Unlocksnd();
206 }
207
208 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
209 {
210 int i;
211 unsigned long masterclock, masterprediv;
212
213 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
214 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
215 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
216 DEBUG_PRINT(("channels=%d, ", spec->channels));
217 DEBUG_PRINT(("freq=%d\n", spec->freq));
218
219 /* Check formats available */
220 MINTAUDIO_nfreq=4;
221 MINTAUDIO_sfreq=0;
222 switch(cookie_mcsn->play) {
223 case MCSN_ST:
224 spec->channels=1;
225 spec->format=8; /* FIXME: is it signed or unsigned ? */
226 MINTAUDIO_nfreq=1;
227 MINTAUDIO_hardfreq[0]=12500;
228 break;
229 case MCSN_TT: /* Also STE, Mega STE */
230 spec->format=AUDIO_S8;
231 masterclock=MASTERCLOCK_STE;
232 masterprediv=MASTERPREDIV_STE;
233 if ((cookie_mch>>16)==MCH_TT) {
234 masterclock=MASTERCLOCK_TT;
235 masterprediv=MASTERPREDIV_TT;
236 }
237 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
238 MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
239 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
240 }
241 break;
242 case MCSN_FALCON: /* Also Mac */
243 MINTAUDIO_nfreq=12;
244 MINTAUDIO_sfreq=1;
245 masterclock=MASTERCLOCK_FALCON1;
246 if (cookie_mcsn->res1 != 0) {
247 masterclock=cookie_mcsn->res1;
248 }
249 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
250 MINTAUDIO_hardfreq[i]=masterclock/(MASTERPREDIV_FALCON*(i+1));
251 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
252 }
253 spec->format |= 0x8000; /* Audio is always signed */
254 if ((spec->format & 0x00ff)==16) {
255 spec->format |= 0x1000; /* Audio is always big endian */
256 spec->channels=2; /* 16 bits always stereo */
257 }
258 break;
259 }
260
261 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, (cookie_mch>>16)==MCH_F30, spec->freq);
262 spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
263
264 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
265 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
266 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
267 DEBUG_PRINT(("channels=%d, ", spec->channels));
268 DEBUG_PRINT(("freq=%d\n", spec->freq));
269
270 return 0;
271 }
272
273 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
274 {
275 int channels_mode;
276 void *buffer;
277
278 /* Stop currently playing sound */
279 Buffoper(0);
280
281 /* Set replay tracks */
282 Settracks(0,0);
283 Setmontracks(0);
284
285 /* Select replay format */
286 channels_mode=STEREO16;
287 switch (spec->format & 0xff) {
288 case 8:
289 if (spec->channels==2) {
290 channels_mode=STEREO8;
291 } else {
292 channels_mode=MONO8;
293 }
294 break;
295 }
296 if (Setmode(channels_mode)<0) {
297 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
298 }
299
300 switch(cookie_mcsn->play) {
301 case MCSN_TT:
302 Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1);
303 Soundcmd(SETPRESCALE, 3-MINTAUDIO_numfreq);
304 DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n"));
305 break;
306 case MCSN_FALCON:
307 if (cookie_mcsn->res1 != 0) {
308 Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
309 DEBUG_PRINT((DEBUG_NAME "External clock selected, prescaler %d\n", MINTAUDIO_numfreq));
310 } else {
311 Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
312 DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
313 }
314 break;
315 }
316
317 /* Set buffer */
318 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
319 if (Setbuffer(0, buffer, buffer + spec->size)<0) {
320 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
321 }
322
323 /* Install interrupt */
324 Jdisint(MFP_DMASOUND);
325 Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
326 Jenabint(MFP_DMASOUND);
327
328 if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
329 DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
330 }
331
332 /* Go */
333 Buffoper(SB_PLA_ENA|SB_PLA_RPT);
334 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
335 }
336
337 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
338 {
339 /* Lock sound system */
340 if (Locksnd()!=1) {
341 SDL_SetError("Mint_OpenAudio: Audio system already in use");
342 return(-1);
343 }
344
345 SDL_MintAudio_device = this;
346
347 /* Check audio capabilities */
348 if (Mint_CheckAudio(this, spec)==-1) {
349 return -1;
350 }
351
352 SDL_CalculateAudioSpec(spec);
353
354 /* Allocate memory for audio buffers in DMA-able RAM */
355 spec->size = spec->samples;
356 spec->size *= spec->channels;
357 spec->size *= (spec->format & 0xFF)/8;
358
359 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
360
361 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
362 if (SDL_MintAudio_audiobuf[0]==NULL) {
363 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
364 return (-1);
365 }
366 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
367 SDL_MintAudio_numbuf=0;
368 memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
369 SDL_MintAudio_audiosize = spec->size;
370 SDL_MintAudio_mutex = 0;
371
372 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
373 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
374
375 /* Setup audio hardware */
376 Mint_InitAudio(this, spec);
377
378 return(1); /* We don't use threaded audio */
379 }