Mercurial > sdl-ios-xcode
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 } |