1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 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 #include "SDL_config.h"
23
24 /*
25 MiNT audio driver
26 using XBIOS functions (STFA driver)
27
28 Patrice Mandin
29 */
30
31 /* Mint includes */
32 #include <mint/osbind.h>
33 #include <mint/falcon.h>
34 #include <mint/cookie.h>
35
36 #include "SDL_audio.h"
37 #include "../SDL_audio_c.h"
38 #include "../SDL_sysaudio.h"
39
40 #include "../../video/ataricommon/SDL_atarimxalloc_c.h"
41 #include "../../video/ataricommon/SDL_atarisuper.h"
42
43 #include "SDL_mintaudio.h"
44 #include "SDL_mintaudio_stfa.h"
45
46 /*--- Defines ---*/
47
48 #define MINT_AUDIO_DRIVER_NAME "mint_stfa"
49
50 /* Debug print info */
51 #define DEBUG_NAME "audio:stfa: "
52 #if 0
53 #define DEBUG_PRINT(what) \
54 { \
55 printf what; \
56 }
57 #else
58 #define DEBUG_PRINT(what)
59 #endif
60
61 /*--- Static variables ---*/
62
63 static long cookie_snd, cookie_mch;
64 static cookie_stfa_t *cookie_stfa;
65
66 static const int freqs[16]={
67 4995, 6269, 7493, 8192,
68 9830, 10971, 12538, 14985,
69 16384, 19819, 21943, 24576,
70 30720, 32336, 43885, 49152
71 };
72
73 /*--- Audio driver functions ---*/
74
75 static void Mint_CloseAudio(_THIS);
76 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
77 static void Mint_LockAudio(_THIS);
78 static void Mint_UnlockAudio(_THIS);
79
80 /* To check/init hardware audio */
81 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
82 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
83
84 /*--- Audio driver bootstrap functions ---*/
85
Audio_Available(void)86 static int Audio_Available(void)
87 {
88 long dummy;
89 const char *envr = SDL_getenv("SDL_AUDIODRIVER");
90
91 /* Check if user asked a different audio driver */
92 if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
93 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
94 return(0);
95 }
96
97 /* Cookie _MCH present ? if not, assume ST machine */
98 if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
99 cookie_mch = MCH_ST;
100 }
101
102 /* Cookie _SND present ? if not, assume ST machine */
103 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
104 cookie_snd = SND_PSG;
105 }
106
107 /* Cookie STFA present ? */
108 if (Getcookie(C_STFA, &dummy) != C_FOUND) {
109 DEBUG_PRINT((DEBUG_NAME "no STFA audio\n"));
110 return(0);
111 }
112 cookie_stfa = (cookie_stfa_t *) dummy;
113
114 SDL_MintAudio_stfa = cookie_stfa;
115
116 DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n"));
117 return(1);
118 }
119
Audio_DeleteDevice(SDL_AudioDevice * device)120 static void Audio_DeleteDevice(SDL_AudioDevice *device)
121 {
122 SDL_free(device->hidden);
123 SDL_free(device);
124 }
125
Audio_CreateDevice(int devindex)126 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
127 {
128 SDL_AudioDevice *this;
129
130 /* Initialize all variables that we clean on shutdown */
131 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
132 if ( this ) {
133 SDL_memset(this, 0, (sizeof *this));
134 this->hidden = (struct SDL_PrivateAudioData *)
135 SDL_malloc((sizeof *this->hidden));
136 }
137 if ( (this == NULL) || (this->hidden == NULL) ) {
138 SDL_OutOfMemory();
139 if ( this ) {
140 SDL_free(this);
141 }
142 return(0);
143 }
144 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
145
146 /* Set the function pointers */
147 this->OpenAudio = Mint_OpenAudio;
148 this->CloseAudio = Mint_CloseAudio;
149 this->LockAudio = Mint_LockAudio;
150 this->UnlockAudio = Mint_UnlockAudio;
151 this->free = Audio_DeleteDevice;
152
153 return this;
154 }
155
156 AudioBootStrap MINTAUDIO_STFA_bootstrap = {
157 MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver",
158 Audio_Available, Audio_CreateDevice
159 };
160
Mint_LockAudio(_THIS)161 static void Mint_LockAudio(_THIS)
162 {
163 void *oldpile;
164
165 /* Stop replay */
166 oldpile=(void *)Super(0);
167 cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
168 SuperToUser(oldpile);
169 }
170
Mint_UnlockAudio(_THIS)171 static void Mint_UnlockAudio(_THIS)
172 {
173 void *oldpile;
174
175 /* Restart replay */
176 oldpile=(void *)Super(0);
177 cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
178 SuperToUser(oldpile);
179 }
180
Mint_CloseAudio(_THIS)181 static void Mint_CloseAudio(_THIS)
182 {
183 void *oldpile;
184
185 /* Stop replay */
186 oldpile=(void *)Super(0);
187 cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
188 SuperToUser(oldpile);
189
190 /* Wait if currently playing sound */
191 while (SDL_MintAudio_mutex != 0) {
192 }
193
194 /* Clear buffers */
195 if (SDL_MintAudio_audiobuf[0]) {
196 Mfree(SDL_MintAudio_audiobuf[0]);
197 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
198 }
199 }
200
Mint_CheckAudio(_THIS,SDL_AudioSpec * spec)201 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
202 {
203 int i;
204
205 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
206 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
207 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
208 DEBUG_PRINT(("channels=%d, ", spec->channels));
209 DEBUG_PRINT(("freq=%d\n", spec->freq));
210
211 if (spec->channels > 2) {
212 spec->channels = 2; /* no more than stereo! */
213 }
214
215 /* Check formats available */
216 MINTAUDIO_freqcount=0;
217 for (i=0;i<16;i++) {
218 SDL_MintAudio_AddFrequency(this, freqs[i], 0, i, -1);
219 }
220
221 #if 1
222 for (i=0; i<MINTAUDIO_freqcount; i++) {
223 DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
224 i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
225 MINTAUDIO_frequencies[i].predivisor
226 ));
227 }
228 #endif
229
230 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
231 spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
232
233 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
234 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
235 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
236 DEBUG_PRINT(("channels=%d, ", spec->channels));
237 DEBUG_PRINT(("freq=%d\n", spec->freq));
238
239 return 0;
240 }
241
Mint_InitAudio(_THIS,SDL_AudioSpec * spec)242 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
243 {
244 void *buffer;
245 void *oldpile;
246
247 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
248
249 oldpile=(void *)Super(0);
250
251 /* Stop replay */
252 cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
253
254 /* Select replay format */
255 cookie_stfa->sound_control = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
256 if ((spec->format & 0xff)==8) {
257 cookie_stfa->sound_control |= STFA_FORMAT_8BIT;
258 } else {
259 cookie_stfa->sound_control |= STFA_FORMAT_16BIT;
260 }
261 if (spec->channels==2) {
262 cookie_stfa->sound_control |= STFA_FORMAT_STEREO;
263 } else {
264 cookie_stfa->sound_control |= STFA_FORMAT_MONO;
265 }
266 if ((spec->format & 0x8000)!=0) {
267 cookie_stfa->sound_control |= STFA_FORMAT_SIGNED;
268 } else {
269 cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED;
270 }
271 if ((spec->format & 0x1000)!=0) {
272 cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN;
273 } else {
274 cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN;
275 }
276
277 /* Set buffer */
278 cookie_stfa->sound_start = (unsigned long) buffer;
279 cookie_stfa->sound_end = (unsigned long) (buffer + spec->size);
280
281 /* Set interrupt */
282 cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt;
283
284 /* Restart replay */
285 cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
286
287 SuperToUser(oldpile);
288
289 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
290 }
291
Mint_OpenAudio(_THIS,SDL_AudioSpec * spec)292 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
293 {
294 SDL_MintAudio_device = this;
295
296 /* Check audio capabilities */
297 if (Mint_CheckAudio(this, spec)==-1) {
298 return -1;
299 }
300
301 SDL_CalculateAudioSpec(spec);
302
303 /* Allocate memory for audio buffers in DMA-able RAM */
304 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
305
306 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
307 if (SDL_MintAudio_audiobuf[0]==NULL) {
308 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
309 return (-1);
310 }
311 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
312 SDL_MintAudio_numbuf=0;
313 SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
314 SDL_MintAudio_audiosize = spec->size;
315 SDL_MintAudio_mutex = 0;
316
317 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
318 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
319
320 SDL_MintAudio_CheckFpu();
321
322 /* Setup audio hardware */
323 Mint_InitAudio(this, spec);
324
325 return(1); /* We don't use threaded audio */
326 }
327