Home | History | Annotate | Download | only in mint
      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