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