src/audio/mint/SDL_mintaudio.c
changeset 644 594422ab8f9f
parent 557 0ce5a68278fd
child 704 c4803992e09c
equal deleted inserted replaced
643:564716cfb502 644:594422ab8f9f
     1 /*
     1 /*
     2  * MiNT audio driver
     2     SDL - Simple DirectMedia Layer
     3  * 
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
     4  * Patrice Mandin
       
     5  */
       
     6 
     4 
     7 #include <stdlib.h>
     5     This library is free software; you can redistribute it and/or
     8 #include <stdio.h>
     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 
       
    23 /*
       
    24 	Audio interrupt variables and callback function
       
    25 
       
    26 	Patrice Mandin
       
    27 */
       
    28 
     9 #include <string.h>
    29 #include <string.h>
    10 
    30 
    11 /* Mint includes */
    31 #include "SDL_types.h"
    12 #include <mint/osbind.h>
       
    13 #include <mint/falcon.h>
       
    14 #include <mint/cookie.h>
       
    15 
       
    16 #include "SDL_endian.h"
       
    17 #include "SDL_audio.h"
    32 #include "SDL_audio.h"
    18 #include "SDL_audio_c.h"
       
    19 #include "SDL_audiomem.h"
       
    20 #include "SDL_sysaudio.h"
       
    21 
    33 
    22 #include "SDL_mintaudio.h"
    34 #include "SDL_mintaudio.h"
    23 #include "SDL_mintaudiodma.h"
    35 #include "SDL_mintaudio_stfa.h"
    24 #include "SDL_mintaudiogsxb.h"
       
    25 #include "SDL_mintaudiointerrupt_s.h"
       
    26 
    36 
    27 #include "SDL_atarimxalloc_c.h"
    37 /* The audio device */
    28 
    38 
    29 /*--- Defines ---*/
    39 SDL_AudioDevice *SDL_MintAudio_device;
       
    40 Uint8 *SDL_MintAudio_audiobuf[2];	/* Pointers to buffers */
       
    41 long SDL_MintAudio_audiosize;		/* Length of audio buffer=spec->size */
       
    42 long SDL_MintAudio_numbuf;		/* Buffer to play */
       
    43 long SDL_MintAudio_mutex;
       
    44 cookie_stfa_t	*SDL_MintAudio_stfa;
    30 
    45 
    31 #define MINT_AUDIO_DRIVER_NAME "mint"
    46 /* The callback function, called by each driver whenever needed */
    32 
    47 
    33 /* Master clocks for replay frequencies */
       
    34 #define MASTERCLOCK_STE		8010666		/* Not sure of this one */
       
    35 #define MASTERCLOCK_TT		16107953	/* Not sure of this one */
       
    36 #define MASTERCLOCK_FALCON1	25175000
       
    37 #define MASTERCLOCK_FALCON2	32000000	/* Only usable for DSP56K */
       
    38 #define MASTERCLOCK_FALCONEXT	-1		/* Clock on DSP56K port, unknown */
       
    39 #define MASTERCLOCK_MILAN1	22579200	/* Standard clock for 44.1 Khz */
       
    40 #define MASTERCLOCK_MILAN2	24576000	/* Standard clock for 48 Khz */
       
    41 
       
    42 /* Master clock predivisors */
       
    43 #define MASTERPREDIV_STE	160
       
    44 #define MASTERPREDIV_TT		320
       
    45 #define MASTERPREDIV_FALCON	256
       
    46 #define MASTERPREDIV_MILAN	256
       
    47 
       
    48 /* Values>>16 in _MCH cookie */
       
    49 enum {
       
    50 	MCH_ST=0,
       
    51 	MCH_STE,
       
    52 	MCH_TT,
       
    53 	MCH_F30
       
    54 };
       
    55 
       
    56 /* MFP 68901 interrupt sources */
       
    57 enum {
       
    58 	MFP_PARALLEL=0,
       
    59 	MFP_DCD,
       
    60 	MFP_CTS,
       
    61 	MFP_BITBLT,
       
    62 	MFP_TIMERD,
       
    63 	MFP_BAUDRATE=MFP_TIMERD,
       
    64 	MFP_TIMERC,
       
    65 	MFP_200HZ=MFP_TIMERC,
       
    66 	MFP_ACIA,
       
    67 	MFP_DISK,
       
    68 	MFP_TIMERB,
       
    69 	MFP_HBLANK=MFP_TIMERB,
       
    70 	MFP_TERR,
       
    71 	MFP_TBE,
       
    72 	MFP_RERR,
       
    73 	MFP_RBF,
       
    74 	MFP_TIMERA,
       
    75 	MFP_DMASOUND=MFP_TIMERA,
       
    76 	MFP_RING,
       
    77 	MFP_MONODETECT
       
    78 };
       
    79 
       
    80 /* Xbtimer() timers */
       
    81 enum {
       
    82 	XB_TIMERA=0,
       
    83 	XB_TIMERB,
       
    84 	XB_TIMERC,
       
    85 	XB_TIMERD
       
    86 };
       
    87 
       
    88 /*--- Static variables ---*/
       
    89 
       
    90 static unsigned long cookie_snd, cookie_mch, cookie_gsxb;
       
    91 static Uint16 hardfreq[16];
       
    92 static Uint16 numfreq;
       
    93 static SDL_AudioDevice *SDL_MintAudio_device;
       
    94 
       
    95 /*--- Audio driver functions ---*/
       
    96 
       
    97 static void Mint_CloseAudio(_THIS);
       
    98 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
       
    99 static void Mint_LockAudio(_THIS);
       
   100 static void Mint_UnlockAudio(_THIS);
       
   101 
       
   102 /*--- Audio driver bootstrap functions ---*/
       
   103 
       
   104 static int Audio_Available(void)
       
   105 {
       
   106 	const char *envr = getenv("SDL_AUDIODRIVER");
       
   107 
       
   108 	/* Check if user asked a different audio driver */
       
   109 	if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
       
   110 		return 0;
       
   111 	}
       
   112 
       
   113 	/* Cookie _SND present ? if not, assume ST machine */
       
   114 	if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
       
   115 		cookie_snd = SND_PSG;
       
   116 	}
       
   117 
       
   118 	/* Cookie _MCH present ? if not, assume ST machine */
       
   119 	if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
       
   120 		cookie_mch = MCH_ST << 16;
       
   121 	}
       
   122 
       
   123 	/* Cookie GSXB present ? */
       
   124 	cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
       
   125 
       
   126 	/* Check if we have xbios functions (Falcon, clones) */
       
   127 	if ((cookie_snd & SND_16BIT)!=0) {
       
   128 		/* Check if audio is lockable */
       
   129 		if (Locksnd()==1) {
       
   130 			Unlocksnd();
       
   131 		} else {
       
   132 			/* Already in use */
       
   133 			return(0);
       
   134 		}
       
   135 
       
   136 		return(1);
       
   137 	}
       
   138 
       
   139 	/* Check if we have 8 bits DMA audio (STE, TT) */
       
   140 	if ((cookie_snd & SND_8BIT)!=0) {
       
   141 		return(1);
       
   142 	}
       
   143 
       
   144     return(0);
       
   145 }
       
   146 
       
   147 static void Audio_DeleteDevice(SDL_AudioDevice *device)
       
   148 {
       
   149     free(device->hidden);
       
   150     free(device);
       
   151 }
       
   152 
       
   153 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
       
   154 {
       
   155     SDL_AudioDevice *this;
       
   156 
       
   157     /* Initialize all variables that we clean on shutdown */
       
   158     this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
       
   159     if ( this ) {
       
   160         memset(this, 0, (sizeof *this));
       
   161     }
       
   162     if ( this == NULL ) {
       
   163         SDL_OutOfMemory();
       
   164         if ( this ) {
       
   165             free(this);
       
   166         }
       
   167         return(0);
       
   168     }
       
   169 
       
   170     /* Set the function pointers */
       
   171     this->OpenAudio   = Mint_OpenAudio;
       
   172     this->CloseAudio  = Mint_CloseAudio;
       
   173     this->LockAudio   = Mint_LockAudio;
       
   174     this->UnlockAudio = Mint_UnlockAudio;
       
   175     this->free        = Audio_DeleteDevice;
       
   176 
       
   177     return this;
       
   178 }
       
   179 
       
   180 AudioBootStrap MINTAUDIO_bootstrap = {
       
   181 	MINT_AUDIO_DRIVER_NAME, "MiNT audio driver",
       
   182 	Audio_Available, Audio_CreateDevice
       
   183 };
       
   184 
       
   185 static void Mint_LockAudio(_THIS)
       
   186 {
       
   187 	void *oldpile;
       
   188 
       
   189 	/* Stop replay */
       
   190 	if ((cookie_snd & SND_16BIT)!=0) {
       
   191 		Buffoper(0);
       
   192 	} else if ((cookie_snd & SND_8BIT)!=0) {
       
   193 		oldpile=(void *)Super(0);
       
   194 		DMAAUDIO_IO.control=0;
       
   195 		Super(oldpile);
       
   196 	}
       
   197 }
       
   198 
       
   199 static void Mint_UnlockAudio(_THIS)
       
   200 {
       
   201 	void *oldpile;
       
   202 
       
   203 	/* Restart replay */
       
   204 	if ((cookie_snd & SND_16BIT)!=0) {
       
   205 		Buffoper(SB_PLA_ENA|SB_PLA_RPT);
       
   206 	} else if ((cookie_snd & SND_8BIT)!=0) {
       
   207 		oldpile=(void *)Super(0);
       
   208 		DMAAUDIO_IO.control=3;
       
   209 		Super(oldpile);
       
   210 	}
       
   211 }
       
   212 
       
   213 /* This is called from the interrupt routine */
       
   214 void SDL_MintAudio_Callback(void)
    48 void SDL_MintAudio_Callback(void)
   215 {
    49 {
   216 	SDL_AudioDevice *audio;
       
   217 	Uint8 *buffer;
    50 	Uint8 *buffer;
   218 
    51 
   219 	audio = SDL_MintAudio_device;
       
   220  	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
    52  	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
       
    53 	memset(buffer, SDL_MintAudio_device->spec.silence, SDL_MintAudio_device->spec.size);
   221 
    54 
   222 	if ( ! audio->paused ) {
    55 	if ( ! SDL_MintAudio_device->paused ) {
   223 		if ( audio->convert.needed ) {
    56 		if ( SDL_MintAudio_device->convert.needed ) {
   224 			audio->spec.callback(audio->spec.userdata,
    57 			SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata,
   225 				(Uint8 *)audio->convert.buf,audio->convert.len);
    58 				(Uint8 *)SDL_MintAudio_device->convert.buf,SDL_MintAudio_device->convert.len);
   226 			SDL_ConvertAudio(&audio->convert);
    59 			SDL_ConvertAudio(&SDL_MintAudio_device->convert);
   227 			memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
    60 			memcpy(buffer, SDL_MintAudio_device->convert.buf, SDL_MintAudio_device->convert.len_cvt);
   228 		} else {
    61 		} else {
   229 			audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
    62 			SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata, buffer, SDL_MintAudio_device->spec.size);
   230 		}
    63 		}
   231 	}
    64 	}
   232 }
    65 }
   233 
    66 
   234 static void Mint_StopAudio_Dma8(void)
    67 /* Simple function to search for the nearest frequency */
   235 {
    68 int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq)
   236 	void *oldpile;
       
   237 	
       
   238 	oldpile=(void *)Super(0);
       
   239 	DMAAUDIO_IO.control=0;
       
   240 	Super(oldpile);
       
   241 
       
   242 	Jdisint(MFP_DMASOUND);
       
   243 }
       
   244 
       
   245 static void Mint_StopAudio_Xbios(void)
       
   246 {
       
   247 	Buffoper(0);
       
   248 	Jdisint(MFP_DMASOUND);
       
   249 }
       
   250 
       
   251 static void Mint_StopAudio_Gsxb(void)
       
   252 {
       
   253 	Buffoper(0);
       
   254 }
       
   255 
       
   256 static void Mint_CloseAudio(_THIS)
       
   257 {
       
   258 	if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
       
   259 		Mint_StopAudio_Gsxb();
       
   260 	} else if ((cookie_snd & SND_16BIT)!=0) {
       
   261 		Mint_StopAudio_Xbios();
       
   262 	} else if ((cookie_snd & SND_8BIT)!=0) {
       
   263 		Mint_StopAudio_Dma8();
       
   264 	}
       
   265 
       
   266 	/* Clear buffers */
       
   267 	if (SDL_MintAudio_audiobuf[0]) {
       
   268 		Mfree(SDL_MintAudio_audiobuf[0]);
       
   269 		SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
       
   270 	}
       
   271 
       
   272 	/* Unlock sound system */
       
   273 	if ((cookie_snd & SND_16BIT)!=0) {
       
   274 		Unlocksnd();
       
   275 	}
       
   276 }
       
   277 
       
   278 static void Mint_CheckAudio_Dma8(SDL_AudioSpec *spec)
       
   279 {
    69 {
   280 	int i;
    70 	int i;
   281 
    71 
   282 	spec->format = AUDIO_S8;
    72 	/* Only 1 freq ? */
   283 
    73 	if (MINTAUDIO_nfreq==1) {
   284 	switch(cookie_mch>>16) {
    74 		return(MINTAUDIO_sfreq);
   285 		case MCH_STE:
       
   286 			/* STE replay frequencies */
       
   287 			for (i=0;i<4;i++) {
       
   288 				hardfreq[i]=MASTERCLOCK_STE/(MASTERPREDIV_STE*(i+1));
       
   289 			}
       
   290 
       
   291 			if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
       
   292 				numfreq=3;		/* 50066 */
       
   293 			} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
       
   294 				numfreq=2;		/* 25033 */
       
   295 			} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
       
   296 				numfreq=1;		/* 12517 */
       
   297 			} else {
       
   298 				numfreq=0;		/* 6258 */
       
   299 			}
       
   300 
       
   301 			spec->freq=hardfreq[numfreq];
       
   302 			break;
       
   303 		case MCH_TT:
       
   304 			/* TT replay frequencies */
       
   305 			for (i=0;i<4;i++) {
       
   306 				hardfreq[i]=MASTERCLOCK_TT/(MASTERPREDIV_TT*(i+1));
       
   307 			}
       
   308 
       
   309 			if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
       
   310 				numfreq=3;		/* 50337 */
       
   311 			} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
       
   312 				numfreq=2;		/* 25169 */
       
   313 			} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
       
   314 				numfreq=1;		/* 12584 */
       
   315 			} else {
       
   316 				numfreq=0;		/* 6292 */
       
   317 			}
       
   318 			spec->freq=hardfreq[numfreq];
       
   319 			break;
       
   320 	}
       
   321 }
       
   322 
       
   323 static void Mint_CheckAudio_Xbios(SDL_AudioSpec *spec)
       
   324 {
       
   325 	int i;
       
   326 
       
   327 	/* Check conversions needed */
       
   328 	switch (spec->format & 0xff) {
       
   329 		case 8:
       
   330 			spec->format = AUDIO_S8;
       
   331 			break;
       
   332 		case 16:
       
   333 			spec->format = AUDIO_S16MSB;
       
   334 			break;
       
   335 	}
       
   336 	
       
   337 	/* Check hardware channels */
       
   338 	if ((spec->channels==1) && ((spec->format & 0xff)==16)) {
       
   339 		spec->channels=2;
       
   340 	}
    75 	}
   341 
    76 
   342 	/* Falcon replay frequencies */
    77 	/* Check the array */
   343 	for (i=0;i<16;i++) {
    78 	for (i=MINTAUDIO_sfreq; i<MINTAUDIO_nfreq-1; i++) {
   344 		hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
    79 		/* Remove unusable falcon codec frequencies */
   345 	}
    80 		if (falcon_codec) {
       
    81 			if ((i==6) || (i==8) || (i==10)) {
       
    82 				continue;
       
    83 			}
       
    84 		}
   346 
    85 
   347 	/* The Falcon CODEC only support some frequencies */
    86 		if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) {
   348 	if (spec->freq>=(hardfreq[CLK50K]+hardfreq[CLK33K])>>1) {
    87 			return i;
   349 		numfreq=CLK50K;		/* 49170 */
       
   350 	} else if (spec->freq>=(hardfreq[CLK33K]+hardfreq[CLK25K])>>1) {
       
   351 		numfreq=CLK33K;		/* 32780 */
       
   352 	} else if (spec->freq>=(hardfreq[CLK25K]+hardfreq[CLK20K])>>1) {
       
   353 		numfreq=CLK25K;		/* 24585 */
       
   354 	} else if (spec->freq>=(hardfreq[CLK20K]+hardfreq[CLK16K])>>1) {
       
   355 		numfreq=CLK20K;		/* 19668 */
       
   356 	} else if (spec->freq>=(hardfreq[CLK16K]+hardfreq[CLK12K])>>1) {
       
   357 		numfreq=CLK16K;		/* 16390 */
       
   358 	} else if (spec->freq>=(hardfreq[CLK12K]+hardfreq[CLK10K])>>1) {
       
   359 		numfreq=CLK12K;		/* 12292 */
       
   360 	} else if (spec->freq>=(hardfreq[CLK10K]+hardfreq[CLK8K])>>1) {
       
   361 		numfreq=CLK10K;		/* 9834 */
       
   362 	} else {
       
   363 		numfreq=CLK8K;		/* 8195 */
       
   364 	}				
       
   365 
       
   366 	spec->freq=hardfreq[numfreq];
       
   367 }
       
   368 
       
   369 static int Mint_CheckAudio_Gsxb(SDL_AudioSpec *spec)
       
   370 {
       
   371 	long snd_format;
       
   372 	int i, resolution, format_signed, format_bigendian;
       
   373 
       
   374 	resolution = spec->format & 0x00ff;
       
   375 	format_signed = ((spec->format & 0x8000)!=0);
       
   376 	format_bigendian = ((spec->format & 0x1000)!=0);
       
   377 
       
   378 	/* Check formats available */
       
   379 	snd_format = Sndstatus(SND_QUERYFORMATS);
       
   380 	switch (resolution) {
       
   381 		case 8:
       
   382 			if ((snd_format & SND_FORMAT8)==0) {
       
   383 				SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
       
   384 				return -1;
       
   385 			}
       
   386 			snd_format = Sndstatus(SND_QUERY8BIT);
       
   387 			break;
       
   388 		case 16:
       
   389 			if ((snd_format & SND_FORMAT16)==0) {
       
   390 				SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
       
   391 				return -1;
       
   392 			}
       
   393 			snd_format = Sndstatus(SND_QUERY16BIT);
       
   394 			break;
       
   395 		default:
       
   396 			SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
       
   397 			return -1;
       
   398 			break;
       
   399 	}
       
   400 
       
   401 	/* Check signed/unsigned format */
       
   402 	if (format_signed) {
       
   403 		if (snd_format & SND_FORMATSIGNED) {
       
   404 			/* Ok */
       
   405 		} else if (snd_format & SND_FORMATUNSIGNED) {
       
   406 			/* Give unsigned format */
       
   407 			spec->format = spec->format & (~0x8000);
       
   408 		}
       
   409 	} else {
       
   410 		if (snd_format & SND_FORMATUNSIGNED) {
       
   411 			/* Ok */
       
   412 		} else if (snd_format & SND_FORMATSIGNED) {
       
   413 			/* Give signed format */
       
   414 			spec->format |= 0x8000;
       
   415 		}
    88 		}
   416 	}
    89 	}
   417 
    90 
   418 	if (format_bigendian) {
    91 	/* Not in the array, give the latest */
   419 		if (snd_format & SND_FORMATBIGENDIAN) {
    92 	return MINTAUDIO_nfreq-1;
   420 			/* Ok */
       
   421 		} else if (snd_format & SND_FORMATLITTLEENDIAN) {
       
   422 			/* Give little endian format */
       
   423 			spec->format = spec->format & (~0x1000);
       
   424 		}
       
   425 	} else {
       
   426 		if (snd_format & SND_FORMATBIGENDIAN) {
       
   427 			/* Ok */
       
   428 		} else if (snd_format & SND_FORMATLITTLEENDIAN) {
       
   429 			/* Give big endian format */
       
   430 			spec->format |= 0x1000;
       
   431 		}
       
   432 	}
       
   433 	
       
   434 	/* Only xbios functions available = clone with PC board */
       
   435 	for (i=0;i<8;i++) {
       
   436 		hardfreq[i]=MASTERCLOCK_MILAN1/(MASTERPREDIV_MILAN*(i+1));
       
   437 	}
       
   438 
       
   439 	if (spec->freq>=(hardfreq[CLK_44K]+hardfreq[CLK_22K])>>1) {
       
   440 		numfreq = CLK_44K;	/* 44100 */
       
   441 	} else if (spec->freq>=(hardfreq[CLK_22K]+hardfreq[CLK_11K])>>1) {
       
   442 		numfreq = CLK_22K;	/* 22050 */
       
   443 	} else {
       
   444 		numfreq = CLK_11K;	/* 11025 */
       
   445 	}				
       
   446 
       
   447 	spec->freq=hardfreq[numfreq];
       
   448 
       
   449 	return 0;
       
   450 }
    93 }
   451 
       
   452 static void Mint_InitAudio_Dma8(SDL_AudioSpec *spec)
       
   453 {
       
   454 	void *oldpile;
       
   455 	unsigned long buffer;
       
   456 	unsigned char mode;
       
   457 	
       
   458 	oldpile=(void *)Super(0);
       
   459 
       
   460 	/* Stop currently playing sound */
       
   461 	DMAAUDIO_IO.control=0;
       
   462 
       
   463 	/* Set buffer */
       
   464 	buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
       
   465 	DMAAUDIO_IO.start_high = (buffer>>16) & 255;
       
   466 	DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
       
   467 	DMAAUDIO_IO.start_low = buffer & 255;
       
   468 
       
   469 	buffer += SDL_MintAudio_audiosize;
       
   470 	DMAAUDIO_IO.end_high = (buffer>>16) & 255;
       
   471 	DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
       
   472 	DMAAUDIO_IO.end_low = buffer & 255;
       
   473 
       
   474 	mode = numfreq;
       
   475 	if (spec->channels==1) {
       
   476 		mode |= 1<<7;
       
   477 	}
       
   478 	DMAAUDIO_IO.mode = mode;	
       
   479 
       
   480 	/* Set interrupt */
       
   481 	Jdisint(MFP_DMASOUND);
       
   482 	Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntDma);
       
   483 	Jenabint(MFP_DMASOUND);
       
   484 
       
   485 	/* Go */
       
   486 	DMAAUDIO_IO.control = 3;	/* playback + repeat */
       
   487 
       
   488 	Super(oldpile);
       
   489 }
       
   490 
       
   491 static void Mint_InitAudio_Xbios(SDL_AudioSpec *spec)
       
   492 {
       
   493 	int channels_mode;
       
   494 	void *buffer;
       
   495 
       
   496 	/* Stop currently playing sound */
       
   497 	Buffoper(0);
       
   498 
       
   499 	Settracks(0,0);
       
   500 	Setmontracks(0);
       
   501 
       
   502 	switch (spec->format & 0xff) {
       
   503 		case 8:
       
   504 			if (spec->channels==2) {
       
   505 				channels_mode=STEREO8;
       
   506 			} else {
       
   507 				channels_mode=MONO8;
       
   508 			}
       
   509 			break;
       
   510 		case 16:
       
   511 		default:
       
   512 			channels_mode=STEREO16;
       
   513 			break;
       
   514 	}
       
   515 	Setmode(channels_mode);
       
   516 
       
   517 	Devconnect(DMAPLAY, DAC, CLK25M, numfreq, 1);
       
   518 
       
   519 	/* Set buffer */
       
   520 	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
       
   521 	Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
       
   522 	
       
   523 	/* Install interrupt */
       
   524 	Setinterrupt(SI_TIMERA, SI_PLAY);
       
   525 
       
   526 	Jdisint(MFP_DMASOUND);
       
   527 	Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntXbios);
       
   528 	Jenabint(MFP_DMASOUND);
       
   529 
       
   530 	/* Go */
       
   531 	Buffoper(SB_PLA_ENA|SB_PLA_RPT);
       
   532 }
       
   533 
       
   534 static void Mint_InitAudio_Gsxb(SDL_AudioSpec *spec)
       
   535 {
       
   536 	int channels_mode;
       
   537 	void *buffer;
       
   538 
       
   539 	/* Stop currently playing sound */
       
   540 	Buffoper(0);
       
   541 
       
   542 	switch (spec->format & 0xff) {
       
   543 		case 8:
       
   544 			if (spec->channels==2) {
       
   545 				channels_mode=STEREO8;
       
   546 			} else {
       
   547 				channels_mode=MONO8;
       
   548 			}
       
   549 			break;
       
   550 		case 16:
       
   551 			if (spec->channels==2) {
       
   552 				channels_mode=STEREO16;
       
   553 			} else {
       
   554 				channels_mode=MONO16;
       
   555 			}
       
   556 			break;
       
   557 		default:
       
   558 			channels_mode=STEREO16;
       
   559 			break;
       
   560 	}
       
   561 	Setmode(channels_mode);
       
   562 
       
   563 	Devconnect(0, 0, CLKEXT, numfreq, 1);
       
   564 
       
   565 	/* Set buffer */
       
   566 	buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
       
   567 	Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
       
   568 	
       
   569 	/* Install interrupt */
       
   570 	NSetinterrupt(2, SI_PLAY, SDL_MintAudio_IntGsxb);
       
   571 		
       
   572 	/* Go */
       
   573 	Buffoper(SB_PLA_ENA|SB_PLA_RPT);
       
   574 }
       
   575 
       
   576 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
       
   577 {
       
   578 	/* Lock sound system */
       
   579 	if ((cookie_snd & SND_16BIT)!=0) {
       
   580 		if (Locksnd()!=1) {
       
   581     	    SDL_SetError("Mint_OpenAudio: Audio system already in use");
       
   582 	        return(-1);
       
   583 		}
       
   584 	}
       
   585 
       
   586 	/* Check audio capabilities */
       
   587 	if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
       
   588 		if (Mint_CheckAudio_Gsxb(spec)==-1) {
       
   589 			return -1;
       
   590 		}
       
   591 	} else if ((cookie_snd & SND_16BIT)!=0) {
       
   592 		Mint_CheckAudio_Xbios(spec);
       
   593 	} else if ((cookie_snd & SND_8BIT)!=0) {
       
   594 		Mint_CheckAudio_Dma8(spec);
       
   595 	}
       
   596 
       
   597 	SDL_CalculateAudioSpec(spec);
       
   598 
       
   599 	/* Allocate memory for audio buffers in DMA-able RAM */
       
   600 	spec->size = spec->samples;
       
   601 	spec->size *= spec->channels;
       
   602 	spec->size *= (spec->format & 0xFF)/8;
       
   603 
       
   604 	SDL_MintAudio_audiosize = spec->size;
       
   605 
       
   606 	SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(SDL_MintAudio_audiosize *2, MX_STRAM);
       
   607 	if (SDL_MintAudio_audiobuf[0]==NULL) {
       
   608 		SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
       
   609 		return (-1);
       
   610 	}
       
   611 	SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize;
       
   612 	SDL_MintAudio_numbuf=0;
       
   613 	memset(SDL_MintAudio_audiobuf[0], 0, SDL_MintAudio_audiosize * 2);
       
   614 	SDL_MintAudio_mutex = 0;
       
   615 
       
   616 	SDL_MintAudio_device = this;
       
   617 
       
   618 	/* Setup audio hardware */
       
   619 	if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
       
   620 		Mint_InitAudio_Gsxb(spec);
       
   621 	} else if ((cookie_snd & SND_16BIT)!=0) {
       
   622 		Mint_InitAudio_Xbios(spec);
       
   623 	} else if ((cookie_snd & SND_8BIT)!=0) {
       
   624 		Mint_InitAudio_Dma8(spec);
       
   625 	}
       
   626 
       
   627     return 1;
       
   628 }