146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2004 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Library General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Library General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Library General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MiNT audio driver
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	using XBIOS functions (MacSound compatible driver)
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Patrice Mandin
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <support.h>
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Mint includes */
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <mint/osbind.h>
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <mint/falcon.h>
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <mint/cookie.h>
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_audio.h"
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_audio_c.h"
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_sysaudio.h"
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../../video/ataricommon/SDL_atarimxalloc_c.h"
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_mintaudio.h"
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_mintaudio_mcsn.h"
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*--- Defines ---*/
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MINT_AUDIO_DRIVER_NAME "mint_mcsn"
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Debug print info */
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEBUG_NAME "audio:mcsn: "
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if 0
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEBUG_PRINT(what) \
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{ \
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		printf what; \
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define DEBUG_PRINT(what)
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*--- Static variables ---*/
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic unsigned long cookie_snd, cookie_mch;
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic cookie_mcsn_t *cookie_mcsn;
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*--- Audio driver functions ---*/
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_CloseAudio(_THIS);
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_LockAudio(_THIS);
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_UnlockAudio(_THIS);
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* To check/init hardware audio */
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*--- Audio driver bootstrap functions ---*/
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Audio_Available(void)
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned long dummy;
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	const char *envr = SDL_getenv("SDL_AUDIODRIVER");
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* We can't use XBIOS in interrupt with Magic, don't know about thread */
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Getcookie(C_MagX, &dummy) == C_FOUND) {
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check if user asked a different audio driver */
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Cookie _MCH present ? if not, assume ST machine */
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cookie_mch = MCH_ST;
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Cookie _SND present ? if not, assume ST machine */
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cookie_snd = SND_PSG;
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check if we have 16 bits audio */
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ((cookie_snd & SND_16BIT)==0) {
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	    return(0);
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Cookie MCSN present ? */
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check if interrupt at end of replay */
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (cookie_mcsn->pint == 0) {
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check if audio is lockable */
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Locksnd()!=1) {
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Unlocksnd();
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(1);
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Audio_DeleteDevice(SDL_AudioDevice *device)
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free(device->hidden);
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_free(device);
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic SDL_AudioDevice *Audio_CreateDevice(int devindex)
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_AudioDevice *this;
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Initialize all variables that we clean on shutdown */
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( this ) {
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_memset(this, 0, (sizeof *this));
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        this->hidden = (struct SDL_PrivateAudioData *)
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner                SDL_malloc((sizeof *this->hidden));
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if ( (this == NULL) || (this->hidden == NULL) ) {
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        SDL_OutOfMemory();
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        if ( this ) {
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner            SDL_free(this);
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        }
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return(0);
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* Set the function pointers */
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    this->OpenAudio   = Mint_OpenAudio;
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    this->CloseAudio  = Mint_CloseAudio;
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    this->LockAudio   = Mint_LockAudio;
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    this->UnlockAudio = Mint_UnlockAudio;
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    this->free        = Audio_DeleteDevice;
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return this;
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17446be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerAudioBootStrap MINTAUDIO_MCSN_bootstrap = {
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Audio_Available, Audio_CreateDevice
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_LockAudio(_THIS)
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Stop replay */
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Buffoper(0);
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_UnlockAudio(_THIS)
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Restart replay */
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Buffoper(SB_PLA_ENA|SB_PLA_RPT);
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_CloseAudio(_THIS)
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Stop replay */
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_WaitThread();
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Buffoper(0);
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (!SDL_MintAudio_mint_present) {
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Uninstall interrupt */
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Jdisint(MFP_DMASOUND);
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Wait if currently playing sound */
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	while (SDL_MintAudio_mutex != 0) {
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Clear buffers */
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (SDL_MintAudio_audiobuf[0]) {
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Mfree(SDL_MintAudio_audiobuf[0]);
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Unlock sound system */
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Unlocksnd();
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned long masterclock, masterprediv;
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("channels=%d, ", spec->channels));
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("freq=%d\n", spec->freq));
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    if (spec->channels > 2) {
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        spec->channels = 2;  /* no more than stereo! */
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    }
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check formats available */
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MINTAUDIO_freqcount=0;
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch(cookie_mcsn->play) {
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MCSN_ST:
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			spec->channels=1;
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			spec->format=8; /* FIXME: is it signed or unsigned ? */
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1);
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MCSN_TT:	/* Also STE, Mega STE */
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			spec->format=AUDIO_S8;
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			masterclock=MASTERCLOCK_STE;
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			masterprediv=MASTERPREDIV_STE;
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ((cookie_mch>>16)==MCH_TT) {
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				masterclock=MASTERCLOCK_TT;
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				masterprediv=MASTERPREDIV_TT;
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for (i=0; i<4; i++) {
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				SDL_MintAudio_AddFrequency(this, masterclock/(masterprediv*(1<<i)),
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					masterclock, 3-i, -1);
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MCSN_FALCON:	/* Also Mac */
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for (i=1; i<12; i++) {
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* Remove unusable Falcon codec predivisors */
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ((i==6) || (i==8) || (i==10)) {
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					continue;
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)),
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					CLK25M, i+1, -1);
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if (cookie_mcsn->res1 != 0) {
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				for (i=1; i<4; i++) {
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					SDL_MintAudio_AddFrequency(this, (cookie_mcsn->res1)/(MASTERPREDIV_FALCON*(1<<i)),
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						CLKEXT, (1<<i)-1, -1);
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			spec->format |= 0x8000;	/* Audio is always signed */
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ((spec->format & 0x00ff)==16) {
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				spec->format |= 0x1000;	/* Audio is always big endian */
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				spec->channels=2;	/* 16 bits always stereo */
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if 1
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for (i=0; i<MINTAUDIO_freqcount; i++) {
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock,
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			MINTAUDIO_frequencies[i].predivisor
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		));
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq);
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0)));
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("channels=%d, ", spec->channels));
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT(("freq=%d\n", spec->freq));
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return 0;
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int channels_mode, prediv, dmaclock;
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	void *buffer;
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Stop currently playing sound */
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_quit_thread = SDL_FALSE;
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_thread_finished = SDL_TRUE;
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_WaitThread();
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Buffoper(0);
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set replay tracks */
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Settracks(0,0);
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Setmontracks(0);
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Select replay format */
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	channels_mode=STEREO16;
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch (spec->format & 0xff) {
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case 8:
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if (spec->channels==2) {
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				channels_mode=STEREO8;
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else {
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				channels_mode=MONO8;
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Setmode(channels_mode)<0) {
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock;
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	switch(cookie_mcsn->play) {
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MCSN_TT:
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1);
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Soundcmd(SETPRESCALE, prediv);
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n"));
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		case MCSN_FALCON:
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			Devconnect(DMAPLAY, DAC, dmaclock, prediv, 1);
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			DEBUG_PRINT((DEBUG_NAME "Falcon prescaler selected\n"));
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			break;
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set buffer */
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Setbuffer(0, buffer, buffer + spec->size)<0) {
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (SDL_MintAudio_mint_present) {
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Install interrupt */
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Jdisint(MFP_DMASOUND);
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		Jenabint(MFP_DMASOUND);
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Go */
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Buffoper(SB_PLA_ENA|SB_PLA_RPT);
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Lock sound system */
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Locksnd()!=1) {
36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner   	    SDL_SetError("Mint_OpenAudio: Audio system already in use");
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner        return(-1);
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_device = this;
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Check audio capabilities */
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (Mint_CheckAudio(this, spec)==-1) {
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return -1;
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CalculateAudioSpec(spec);
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Allocate memory for audio buffers in DMA-able RAM */
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (SDL_MintAudio_audiobuf[0]==NULL) {
38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return (-1);
38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_numbuf=0;
39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_audiosize = spec->size;
39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_mutex = 0;
39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_MintAudio_CheckFpu();
39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Setup audio hardware */
40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	Mint_InitAudio(this, spec);
40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    return(1);	/* We don't use SDL threaded audio */
40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
405