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 63static long cookie_snd, cookie_mch; 64static cookie_stfa_t *cookie_stfa; 65 66static 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 75static void Mint_CloseAudio(_THIS); 76static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); 77static void Mint_LockAudio(_THIS); 78static void Mint_UnlockAudio(_THIS); 79 80/* To check/init hardware audio */ 81static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); 82static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec); 83 84/*--- Audio driver bootstrap functions ---*/ 85 86static 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 120static void Audio_DeleteDevice(SDL_AudioDevice *device) 121{ 122 SDL_free(device->hidden); 123 SDL_free(device); 124} 125 126static 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 156AudioBootStrap MINTAUDIO_STFA_bootstrap = { 157 MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver", 158 Audio_Available, Audio_CreateDevice 159}; 160 161static 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 171static 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 181static 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 201static 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 242static 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 292static 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