Atari MiNT: added more audio drivers

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40645
This commit is contained in:
Patrice Mandin 2003-07-07 19:16:03 +00:00
parent ae6427430d
commit e1695a4b13
16 changed files with 2541 additions and 621 deletions

View File

@ -49,18 +49,18 @@ Mouse (XBIOS, GEM, Ikbd)
Video (XBIOS (Fullscreen), GEM (Windowed and Fullscreen))
Timer (VBL vector, GNU pth library)
Joystick and joypad support (Ikbd, Hardware)
Audio support (Hardware, XBIOS, GSXB, /dev/audio if threads enabled)
Audio support (Hardware, XBIOS, GSXB, MCSN, STFA, /dev/audio if threads enabled)
Threads support (Multitasking OS only via GNU pth library)
- What is missing:
CDROM support (Metados, /dev/cdrom)
- Driver combinations:
Video Kbd Mouse Timer Jstick Joypads
xbios ikbd ikbd vbl(2) ikbd hardware
xbios gemdos xbios vbl(2) xbios hardware
xbios bios xbios vbl(2) xbios hardware
gem gem gem(1) vbl(2) xbios hardware
Video Kbd Mouse Timer Joystick
xbios ikbd ikbd vbl(2) ikbd
xbios gemdos xbios vbl(2) xbios
xbios bios xbios vbl(2) xbios
gem gem gem(1) vbl(2) xbios
(1) GEM does not report relative mouse motion, so xbios mouse driver is used
to report this type event.
@ -76,7 +76,11 @@ SDL_VIDEODRIVER:
Set to 'gem' to force gem video driver
SDL_AUDIODRIVER:
Set to 'mint' to force Atari audio driver
Set to 'mint_gsxb' to force Atari GSXB audio driver
Set to 'mint_mcsn' to force Atari MCSN audio driver
Set to 'mint_stfa' to force Atari STFA audio driver
Set to 'mint_xbios' to force Atari Xbios audio driver
Set to 'mint_dma8' to force Atari 8 bits DMA audio driver
Set to 'audio' to force Sun /dev/audio audio driver
Set to 'disk' to force disk-writing audio driver
@ -163,17 +167,30 @@ PTH timer driver:
VBL timer driver:
Available on all machines (I think).
Audio driver:
Cookie _SND is used to detect supported audio capabilities
Audio drivers:
Cookies _SND, MCSN, STFA and GSXB used to detect supported audio
capabilities.
STE, Mega STE, TT:
8 bits DMA (hardware access)
Falcon, machines with GSXB driver:
STFA, MCSN or GSXB driver if installed
Falcon:
8 bits DMA (hardware access)
Xbios functions
STFA, MCSN or GSXB driver if installed
Other machines:
Not supported
STFA, MCSN or GSXB driver if installed
STFA driver:
http://removers.free.fr/softs/stfa.html
GSXB driver:
http://assemsoft.atari.org/gsxb/
MacSound driver:
http://jf.omnis.ch/software/tos/
MagicSound driver (MCSN,GSXB compatible):
http://perso.wanadoo.fr/didierm/
X-Sound driver (GSXB compatible):
http://www.uni-ulm.de/~s_thuth/atari/xsound_e.html
--
Patrice Mandin <pmandin@caramail.com>

View File

@ -84,7 +84,11 @@ static AudioBootStrap *bootstrap[] = {
&AHI_bootstrap,
#endif
#ifdef MINTAUDIO_SUPPORT
&MINTAUDIO_bootstrap,
&MINTAUDIO_GSXB_bootstrap,
&MINTAUDIO_MCSN_bootstrap,
&MINTAUDIO_STFA_bootstrap,
&MINTAUDIO_XBIOS_bootstrap,
&MINTAUDIO_DMA8_bootstrap,
#endif
#ifdef DISKAUD_SUPPORT
&DISKAUD_bootstrap,

View File

@ -148,7 +148,11 @@ extern AudioBootStrap SNDMGR_bootstrap;
extern AudioBootStrap AHI_bootstrap;
#endif
#ifdef MINTAUDIO_SUPPORT
extern AudioBootStrap MINTAUDIO_bootstrap;
extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
#endif
#ifdef DISKAUD_SUPPORT
extern AudioBootStrap DISKAUD_bootstrap;

View File

@ -1,14 +1,19 @@
## Makefile.am for SDL using Xbios/Dma/whatever available audio functions
noinst_LTLIBRARIES = libaudio_mintaudio.la
libaudio_mintaudio_la_SOURCES = $(SRCS)
# The SDL audio driver sources
SRCS = SDL_mintaudio.c \
SRCS = \
SDL_mintaudio.c \
SDL_mintaudio.h \
SDL_mintaudiointerrupt.S \
SDL_mintaudiointerrupt_s.h \
SDL_mintaudiodma.h \
SDL_mintaudiogsxb.h
SDL_mintaudio_dma8.c \
SDL_mintaudio_dma8.h \
SDL_mintaudio_gsxb.c \
SDL_mintaudio_gsxb.h \
SDL_mintaudio_it.S \
SDL_mintaudio_mcsn.c \
SDL_mintaudio_mcsn.h \
SDL_mintaudio_stfa.c \
SDL_mintaudio_stfa.h \
SDL_mintaudio_xbios.c

View File

@ -1,628 +1,93 @@
/*
* MiNT audio driver
*
* Patrice Mandin
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
Audio interrupt variables and callback function
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_types.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_mintaudio.h"
#include "SDL_mintaudiodma.h"
#include "SDL_mintaudiogsxb.h"
#include "SDL_mintaudiointerrupt_s.h"
#include "SDL_mintaudio_stfa.h"
#include "SDL_atarimxalloc_c.h"
/* The audio device */
/*--- Defines ---*/
SDL_AudioDevice *SDL_MintAudio_device;
Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */
long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */
long SDL_MintAudio_numbuf; /* Buffer to play */
long SDL_MintAudio_mutex;
cookie_stfa_t *SDL_MintAudio_stfa;
#define MINT_AUDIO_DRIVER_NAME "mint"
/* The callback function, called by each driver whenever needed */
/* Master clocks for replay frequencies */
#define MASTERCLOCK_STE 8010666 /* Not sure of this one */
#define MASTERCLOCK_TT 16107953 /* Not sure of this one */
#define MASTERCLOCK_FALCON1 25175000
#define MASTERCLOCK_FALCON2 32000000 /* Only usable for DSP56K */
#define MASTERCLOCK_FALCONEXT -1 /* Clock on DSP56K port, unknown */
#define MASTERCLOCK_MILAN1 22579200 /* Standard clock for 44.1 Khz */
#define MASTERCLOCK_MILAN2 24576000 /* Standard clock for 48 Khz */
/* Master clock predivisors */
#define MASTERPREDIV_STE 160
#define MASTERPREDIV_TT 320
#define MASTERPREDIV_FALCON 256
#define MASTERPREDIV_MILAN 256
/* Values>>16 in _MCH cookie */
enum {
MCH_ST=0,
MCH_STE,
MCH_TT,
MCH_F30
};
/* MFP 68901 interrupt sources */
enum {
MFP_PARALLEL=0,
MFP_DCD,
MFP_CTS,
MFP_BITBLT,
MFP_TIMERD,
MFP_BAUDRATE=MFP_TIMERD,
MFP_TIMERC,
MFP_200HZ=MFP_TIMERC,
MFP_ACIA,
MFP_DISK,
MFP_TIMERB,
MFP_HBLANK=MFP_TIMERB,
MFP_TERR,
MFP_TBE,
MFP_RERR,
MFP_RBF,
MFP_TIMERA,
MFP_DMASOUND=MFP_TIMERA,
MFP_RING,
MFP_MONODETECT
};
/* Xbtimer() timers */
enum {
XB_TIMERA=0,
XB_TIMERB,
XB_TIMERC,
XB_TIMERD
};
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_mch, cookie_gsxb;
static Uint16 hardfreq[16];
static Uint16 numfreq;
static SDL_AudioDevice *SDL_MintAudio_device;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
return 0;
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST << 16;
}
/* Cookie GSXB present ? */
cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
/* Check if we have xbios functions (Falcon, clones) */
if ((cookie_snd & SND_16BIT)!=0) {
/* Check if audio is lockable */
if (Locksnd()==1) {
Unlocksnd();
} else {
/* Already in use */
return(0);
}
return(1);
}
/* Check if we have 8 bits DMA audio (STE, TT) */
if ((cookie_snd & SND_8BIT)!=0) {
return(1);
}
return(0);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
}
if ( this == NULL ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
void *oldpile;
/* Stop replay */
if ((cookie_snd & SND_16BIT)!=0) {
Buffoper(0);
} else if ((cookie_snd & SND_8BIT)!=0) {
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=0;
Super(oldpile);
}
}
static void Mint_UnlockAudio(_THIS)
{
void *oldpile;
/* Restart replay */
if ((cookie_snd & SND_16BIT)!=0) {
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
} else if ((cookie_snd & SND_8BIT)!=0) {
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=3;
Super(oldpile);
}
}
/* This is called from the interrupt routine */
void SDL_MintAudio_Callback(void)
{
SDL_AudioDevice *audio;
Uint8 *buffer;
audio = SDL_MintAudio_device;
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
memset(buffer, SDL_MintAudio_device->spec.silence, SDL_MintAudio_device->spec.size);
if ( ! audio->paused ) {
if ( audio->convert.needed ) {
audio->spec.callback(audio->spec.userdata,
(Uint8 *)audio->convert.buf,audio->convert.len);
SDL_ConvertAudio(&audio->convert);
memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
if ( ! SDL_MintAudio_device->paused ) {
if ( SDL_MintAudio_device->convert.needed ) {
SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata,
(Uint8 *)SDL_MintAudio_device->convert.buf,SDL_MintAudio_device->convert.len);
SDL_ConvertAudio(&SDL_MintAudio_device->convert);
memcpy(buffer, SDL_MintAudio_device->convert.buf, SDL_MintAudio_device->convert.len_cvt);
} else {
audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata, buffer, SDL_MintAudio_device->spec.size);
}
}
}
static void Mint_StopAudio_Dma8(void)
{
void *oldpile;
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=0;
Super(oldpile);
Jdisint(MFP_DMASOUND);
}
static void Mint_StopAudio_Xbios(void)
{
Buffoper(0);
Jdisint(MFP_DMASOUND);
}
static void Mint_StopAudio_Gsxb(void)
{
Buffoper(0);
}
static void Mint_CloseAudio(_THIS)
{
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
Mint_StopAudio_Gsxb();
} else if ((cookie_snd & SND_16BIT)!=0) {
Mint_StopAudio_Xbios();
} else if ((cookie_snd & SND_8BIT)!=0) {
Mint_StopAudio_Dma8();
}
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
/* Unlock sound system */
if ((cookie_snd & SND_16BIT)!=0) {
Unlocksnd();
}
}
static void Mint_CheckAudio_Dma8(SDL_AudioSpec *spec)
/* Simple function to search for the nearest frequency */
int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq)
{
int i;
spec->format = AUDIO_S8;
switch(cookie_mch>>16) {
case MCH_STE:
/* STE replay frequencies */
for (i=0;i<4;i++) {
hardfreq[i]=MASTERCLOCK_STE/(MASTERPREDIV_STE*(i+1));
/* Only 1 freq ? */
if (MINTAUDIO_nfreq==1) {
return(MINTAUDIO_sfreq);
}
if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
numfreq=3; /* 50066 */
} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
numfreq=2; /* 25033 */
} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
numfreq=1; /* 12517 */
} else {
numfreq=0; /* 6258 */
}
spec->freq=hardfreq[numfreq];
break;
case MCH_TT:
/* TT replay frequencies */
for (i=0;i<4;i++) {
hardfreq[i]=MASTERCLOCK_TT/(MASTERPREDIV_TT*(i+1));
}
if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
numfreq=3; /* 50337 */
} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
numfreq=2; /* 25169 */
} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
numfreq=1; /* 12584 */
} else {
numfreq=0; /* 6292 */
}
spec->freq=hardfreq[numfreq];
break;
/* Check the array */
for (i=MINTAUDIO_sfreq; i<MINTAUDIO_nfreq-1; i++) {
/* Remove unusable falcon codec frequencies */
if (falcon_codec) {
if ((i==6) || (i==8) || (i==10)) {
continue;
}
}
static void Mint_CheckAudio_Xbios(SDL_AudioSpec *spec)
{
int i;
/* Check conversions needed */
switch (spec->format & 0xff) {
case 8:
spec->format = AUDIO_S8;
break;
case 16:
spec->format = AUDIO_S16MSB;
break;
}
/* Check hardware channels */
if ((spec->channels==1) && ((spec->format & 0xff)==16)) {
spec->channels=2;
}
/* Falcon replay frequencies */
for (i=0;i<16;i++) {
hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
}
/* The Falcon CODEC only support some frequencies */
if (spec->freq>=(hardfreq[CLK50K]+hardfreq[CLK33K])>>1) {
numfreq=CLK50K; /* 49170 */
} else if (spec->freq>=(hardfreq[CLK33K]+hardfreq[CLK25K])>>1) {
numfreq=CLK33K; /* 32780 */
} else if (spec->freq>=(hardfreq[CLK25K]+hardfreq[CLK20K])>>1) {
numfreq=CLK25K; /* 24585 */
} else if (spec->freq>=(hardfreq[CLK20K]+hardfreq[CLK16K])>>1) {
numfreq=CLK20K; /* 19668 */
} else if (spec->freq>=(hardfreq[CLK16K]+hardfreq[CLK12K])>>1) {
numfreq=CLK16K; /* 16390 */
} else if (spec->freq>=(hardfreq[CLK12K]+hardfreq[CLK10K])>>1) {
numfreq=CLK12K; /* 12292 */
} else if (spec->freq>=(hardfreq[CLK10K]+hardfreq[CLK8K])>>1) {
numfreq=CLK10K; /* 9834 */
} else {
numfreq=CLK8K; /* 8195 */
}
spec->freq=hardfreq[numfreq];
}
static int Mint_CheckAudio_Gsxb(SDL_AudioSpec *spec)
{
long snd_format;
int i, resolution, format_signed, format_bigendian;
resolution = spec->format & 0x00ff;
format_signed = ((spec->format & 0x8000)!=0);
format_bigendian = ((spec->format & 0x1000)!=0);
/* Check formats available */
snd_format = Sndstatus(SND_QUERYFORMATS);
switch (resolution) {
case 8:
if ((snd_format & SND_FORMAT8)==0) {
SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
return -1;
}
snd_format = Sndstatus(SND_QUERY8BIT);
break;
case 16:
if ((snd_format & SND_FORMAT16)==0) {
SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
return -1;
}
snd_format = Sndstatus(SND_QUERY16BIT);
break;
default:
SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
return -1;
break;
}
/* Check signed/unsigned format */
if (format_signed) {
if (snd_format & SND_FORMATSIGNED) {
/* Ok */
} else if (snd_format & SND_FORMATUNSIGNED) {
/* Give unsigned format */
spec->format = spec->format & (~0x8000);
}
} else {
if (snd_format & SND_FORMATUNSIGNED) {
/* Ok */
} else if (snd_format & SND_FORMATSIGNED) {
/* Give signed format */
spec->format |= 0x8000;
if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) {
return i;
}
}
if (format_bigendian) {
if (snd_format & SND_FORMATBIGENDIAN) {
/* Ok */
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
/* Give little endian format */
spec->format = spec->format & (~0x1000);
}
} else {
if (snd_format & SND_FORMATBIGENDIAN) {
/* Ok */
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
/* Give big endian format */
spec->format |= 0x1000;
}
}
/* Only xbios functions available = clone with PC board */
for (i=0;i<8;i++) {
hardfreq[i]=MASTERCLOCK_MILAN1/(MASTERPREDIV_MILAN*(i+1));
}
if (spec->freq>=(hardfreq[CLK_44K]+hardfreq[CLK_22K])>>1) {
numfreq = CLK_44K; /* 44100 */
} else if (spec->freq>=(hardfreq[CLK_22K]+hardfreq[CLK_11K])>>1) {
numfreq = CLK_22K; /* 22050 */
} else {
numfreq = CLK_11K; /* 11025 */
}
spec->freq=hardfreq[numfreq];
return 0;
}
static void Mint_InitAudio_Dma8(SDL_AudioSpec *spec)
{
void *oldpile;
unsigned long buffer;
unsigned char mode;
oldpile=(void *)Super(0);
/* Stop currently playing sound */
DMAAUDIO_IO.control=0;
/* Set buffer */
buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
DMAAUDIO_IO.start_high = (buffer>>16) & 255;
DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
DMAAUDIO_IO.start_low = buffer & 255;
buffer += SDL_MintAudio_audiosize;
DMAAUDIO_IO.end_high = (buffer>>16) & 255;
DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
DMAAUDIO_IO.end_low = buffer & 255;
mode = numfreq;
if (spec->channels==1) {
mode |= 1<<7;
}
DMAAUDIO_IO.mode = mode;
/* Set interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntDma);
Jenabint(MFP_DMASOUND);
/* Go */
DMAAUDIO_IO.control = 3; /* playback + repeat */
Super(oldpile);
}
static void Mint_InitAudio_Xbios(SDL_AudioSpec *spec)
{
int channels_mode;
void *buffer;
/* Stop currently playing sound */
Buffoper(0);
Settracks(0,0);
Setmontracks(0);
switch (spec->format & 0xff) {
case 8:
if (spec->channels==2) {
channels_mode=STEREO8;
} else {
channels_mode=MONO8;
}
break;
case 16:
default:
channels_mode=STEREO16;
break;
}
Setmode(channels_mode);
Devconnect(DMAPLAY, DAC, CLK25M, numfreq, 1);
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
/* Install interrupt */
Setinterrupt(SI_TIMERA, SI_PLAY);
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntXbios);
Jenabint(MFP_DMASOUND);
/* Go */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
}
static void Mint_InitAudio_Gsxb(SDL_AudioSpec *spec)
{
int channels_mode;
void *buffer;
/* Stop currently playing sound */
Buffoper(0);
switch (spec->format & 0xff) {
case 8:
if (spec->channels==2) {
channels_mode=STEREO8;
} else {
channels_mode=MONO8;
}
break;
case 16:
if (spec->channels==2) {
channels_mode=STEREO16;
} else {
channels_mode=MONO16;
}
break;
default:
channels_mode=STEREO16;
break;
}
Setmode(channels_mode);
Devconnect(0, 0, CLKEXT, numfreq, 1);
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
/* Install interrupt */
NSetinterrupt(2, SI_PLAY, SDL_MintAudio_IntGsxb);
/* Go */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
/* Lock sound system */
if ((cookie_snd & SND_16BIT)!=0) {
if (Locksnd()!=1) {
SDL_SetError("Mint_OpenAudio: Audio system already in use");
return(-1);
}
}
/* Check audio capabilities */
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
if (Mint_CheckAudio_Gsxb(spec)==-1) {
return -1;
}
} else if ((cookie_snd & SND_16BIT)!=0) {
Mint_CheckAudio_Xbios(spec);
} else if ((cookie_snd & SND_8BIT)!=0) {
Mint_CheckAudio_Dma8(spec);
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(SDL_MintAudio_audiosize *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], 0, SDL_MintAudio_audiosize * 2);
SDL_MintAudio_mutex = 0;
SDL_MintAudio_device = this;
/* Setup audio hardware */
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
Mint_InitAudio_Gsxb(spec);
} else if ((cookie_snd & SND_16BIT)!=0) {
Mint_InitAudio_Xbios(spec);
} else if ((cookie_snd & SND_8BIT)!=0) {
Mint_InitAudio_Dma8(spec);
}
return 1;
/* Not in the array, give the latest */
return MINTAUDIO_nfreq-1;
}

View File

@ -1,15 +1,125 @@
/*
* MiNT audio driver
*
* Patrice Mandin
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
Patrice Mandin
*/
#ifndef _SDL_mintaudio_h
#define _SDL_mintaudio_h
#include "SDL_sysaudio.h"
#include "SDL_mintaudio_stfa.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData {
Uint32 hardfreq[16]; /* Array of replay freqs of the hardware */
int sfreq; /* First number of freq to use in the array */
int nfreq; /* Number of freqs to use in the array */
int numfreq; /* Number of selected frequency */
};
/* Old variable names */
#define MINTAUDIO_hardfreq (this->hidden->hardfreq)
#define MINTAUDIO_sfreq (this->hidden->sfreq)
#define MINTAUDIO_nfreq (this->hidden->nfreq)
#define MINTAUDIO_numfreq (this->hidden->numfreq)
/* _MCH cookie (values>>16) */
enum {
MCH_ST=0,
MCH_STE,
MCH_TT,
MCH_F30
};
/* Master clocks for replay frequencies */
#define MASTERCLOCK_STE 8010666 /* Not sure of this one */
#define MASTERCLOCK_TT 16107953 /* Not sure of this one */
#define MASTERCLOCK_FALCON1 25175000
#define MASTERCLOCK_FALCON2 32000000 /* Only usable for DSP56K */
#define MASTERCLOCK_FALCONEXT -1 /* Clock on DSP56K port, unknown */
#define MASTERCLOCK_44K 22579200 /* Standard clock for 44.1 Khz */
#define MASTERCLOCK_48K 24576000 /* Standard clock for 48 Khz */
/* Master clock predivisors */
#define MASTERPREDIV_STE 160
#define MASTERPREDIV_TT 320
#define MASTERPREDIV_FALCON 256
#define MASTERPREDIV_MILAN 256
/* MFP 68901 interrupt sources */
enum {
MFP_PARALLEL=0,
MFP_DCD,
MFP_CTS,
MFP_BITBLT,
MFP_TIMERD,
MFP_BAUDRATE=MFP_TIMERD,
MFP_TIMERC,
MFP_200HZ=MFP_TIMERC,
MFP_ACIA,
MFP_DISK,
MFP_TIMERB,
MFP_HBLANK=MFP_TIMERB,
MFP_TERR,
MFP_TBE,
MFP_RERR,
MFP_RBF,
MFP_TIMERA,
MFP_DMASOUND=MFP_TIMERA,
MFP_RING,
MFP_MONODETECT
};
/* Xbtimer() timers */
enum {
XB_TIMERA=0,
XB_TIMERB,
XB_TIMERC,
XB_TIMERD
};
/* Variables */
extern SDL_AudioDevice *SDL_MintAudio_device;
extern Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */
extern long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */
extern long SDL_MintAudio_numbuf; /* Buffer to play */
extern long SDL_MintAudio_mutex;
extern cookie_stfa_t *SDL_MintAudio_stfa;
/* Functions */
void SDL_MintAudio_Callback(void);
int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq);
/* ASM interrupt functions */
void SDL_MintAudio_GsxbInterrupt(void);
void SDL_MintAudio_EmptyGsxbInterrupt(void);
void SDL_MintAudio_XbiosInterrupt(void);
void SDL_MintAudio_Dma8Interrupt(void);
void SDL_MintAudio_StfaInterrupt(void);
#endif /* _SDL_mintaudio_h */

View File

@ -0,0 +1,354 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
using DMA 8bits (hardware access)
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_atarimxalloc_c.h"
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_dma8.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_dma8"
/* Debug print info */
#define DEBUG_NAME "audio:dma8: "
#if 0
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_mch;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return 0;
}
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST;
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Check if we have 8 bits audio */
if ((cookie_snd & SND_8BIT)==0) {
DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n"));
return(0);
}
if ((cookie_mch>>16)>MCH_F30) {
DEBUG_PRINT((DEBUG_NAME "unknown 8 bits audio chip\n"));
return 0;
}
/* Check if audio is lockable */
if ((cookie_mch>>16) == MCH_F30) {
if (Locksnd()!=1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return(0);
}
Unlocksnd();
}
DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
return(1);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
void *oldpile;
/* Stop replay */
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=0;
Super(oldpile);
}
static void Mint_UnlockAudio(_THIS)
{
void *oldpile;
/* Restart replay */
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=3;
Super(oldpile);
}
static void Mint_CloseAudio(_THIS)
{
void *oldpile;
/* Stop replay */
oldpile=(void *)Super(0);
DMAAUDIO_IO.control=0;
Super(oldpile);
DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
/* Disable interrupt */
Jdisint(MFP_DMASOUND);
DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
int i, masterprediv;
unsigned long masterclock;
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
/* Check formats available */
spec->format = AUDIO_S8;
/* Calculate and select the closest frequency */
MINTAUDIO_nfreq=4;
MINTAUDIO_sfreq=0;
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
switch(cookie_mch>>16) {
/*
case MCH_STE:
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
break;
*/
case MCH_TT:
masterclock=MASTERCLOCK_TT;
masterprediv=MASTERPREDIV_TT;
break;
case MCH_F30:
masterclock=MASTERCLOCK_FALCON1;
masterprediv=MASTERPREDIV_FALCON<<1;
MINTAUDIO_nfreq=3;
MINTAUDIO_sfreq=1;
break;
}
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
return 0;
}
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
void *oldpile;
unsigned long buffer;
unsigned char mode;
/* Set replay tracks */
if (cookie_snd & SND_16BIT) {
Settracks(0,0);
Setmontracks(0);
}
oldpile=(void *)Super(0);
/* Stop currently playing sound */
DMAAUDIO_IO.control=0;
/* Set buffer */
buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
DMAAUDIO_IO.start_high = (buffer>>16) & 255;
DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
DMAAUDIO_IO.start_low = buffer & 255;
buffer += SDL_MintAudio_audiosize;
DMAAUDIO_IO.end_high = (buffer>>16) & 255;
DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
DMAAUDIO_IO.end_low = buffer & 255;
mode = 3-MINTAUDIO_numfreq;
if (spec->channels==1) {
mode |= 1<<7;
}
DMAAUDIO_IO.mode = mode;
/* Set interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
Jenabint(MFP_DMASOUND);
/* Go */
DMAAUDIO_IO.control = 3; /* playback + repeat */
Super(oldpile);
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
SDL_MintAudio_device = this;
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec)==-1) {
return -1;
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
/* Setup audio hardware */
Mint_InitAudio(this, spec);
return(1); /* We don't use threaded audio */
}

View File

@ -0,0 +1,65 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
DMA 8bits audio definitions
Patrice Mandin
*/
#ifndef _SDL_mintaudio_dma8_h
#define _SDL_mintaudio_dma8_h
#define DMAAUDIO_IO_BASE (0xffff8900)
struct DMAAUDIO_IO_S {
unsigned char int_ctrl;
unsigned char control;
unsigned char dummy1;
unsigned char start_high;
unsigned char dummy2;
unsigned char start_mid;
unsigned char dummy3;
unsigned char start_low;
unsigned char dummy4;
unsigned char cur_high;
unsigned char dummy5;
unsigned char cur_mid;
unsigned char dummy6;
unsigned char cur_low;
unsigned char dummy7;
unsigned char end_high;
unsigned char dummy8;
unsigned char end_mid;
unsigned char dummy9;
unsigned char end_low;
unsigned char dummy10[12];
unsigned char track_select; /* CODEC only */
unsigned char mode;
};
#define DMAAUDIO_IO ((*(volatile struct DMAAUDIO_IO_S *)DMAAUDIO_IO_BASE))
#endif /* _SDL_mintaudio_dma8_h */

View File

@ -0,0 +1,395 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
using XBIOS functions (GSXB compatible driver)
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_atarimxalloc_c.h"
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_gsxb.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_gsxb"
/* Debug print info */
#define DEBUG_NAME "audio:gsxb: "
#if 0
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_gsxb;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return(0);
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Check if we have 16 bits audio */
if ((cookie_snd & SND_16BIT)==0) {
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
return(0);
}
/* Cookie GSXB present ? */
cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
/* Is it GSXB ? */
if (((cookie_snd & SND_GSXB)==0) || (cookie_gsxb==0)) {
DEBUG_PRINT((DEBUG_NAME "no GSXB audio\n"));
return(0);
}
/* Check if audio is lockable */
if (Locksnd()!=1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return(0);
}
Unlocksnd();
DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n"));
return(1);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_GSXB_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
}
static void Mint_UnlockAudio(_THIS)
{
/* Restart replay */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
}
static void Mint_CloseAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
/* Uninstall interrupt */
if (NSetinterrupt(2, SI_NONE, SDL_MintAudio_EmptyGsxbInterrupt)<0) {
DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
}
DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
/* Unlock sound system */
Unlocksnd();
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
long snd_format;
int i, resolution, format_signed, format_bigendian;
resolution = spec->format & 0x00ff;
format_signed = ((spec->format & 0x8000)!=0);
format_bigendian = ((spec->format & 0x1000)!=0);
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",resolution));
DEBUG_PRINT(("signed=%d, ", format_signed));
DEBUG_PRINT(("big endian=%d, ", format_bigendian));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
/* Check formats available */
snd_format = Sndstatus(SND_QUERYFORMATS);
switch (resolution) {
case 8:
if ((snd_format & SND_FORMAT8)==0) {
SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
return -1;
}
snd_format = Sndstatus(SND_QUERY8BIT);
break;
case 16:
if ((snd_format & SND_FORMAT16)==0) {
SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
return -1;
}
snd_format = Sndstatus(SND_QUERY16BIT);
break;
default:
SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
return -1;
break;
}
/* Check signed/unsigned format */
if (format_signed) {
if (snd_format & SND_FORMATSIGNED) {
/* Ok */
} else if (snd_format & SND_FORMATUNSIGNED) {
/* Give unsigned format */
spec->format = spec->format & (~0x8000);
}
} else {
if (snd_format & SND_FORMATUNSIGNED) {
/* Ok */
} else if (snd_format & SND_FORMATSIGNED) {
/* Give signed format */
spec->format |= 0x8000;
}
}
if (format_bigendian) {
if (snd_format & SND_FORMATBIGENDIAN) {
/* Ok */
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
/* Give little endian format */
spec->format = spec->format & (~0x1000);
}
} else {
if (snd_format & SND_FORMATBIGENDIAN) {
/* Ok */
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
/* Give big endian format */
spec->format |= 0x1000;
}
}
/* Calculate and select the closest frequency */
MINTAUDIO_sfreq=1;
MINTAUDIO_nfreq=12;
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(i+1));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
return 0;
}
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
int channels_mode;
void *buffer;
/* Stop currently playing sound */
Buffoper(0);
/* Set replay tracks */
Settracks(0,0);
Setmontracks(0);
/* Select replay format */
switch (spec->format & 0xff) {
case 8:
if (spec->channels==2) {
channels_mode=STEREO8;
} else {
channels_mode=MONO8;
}
break;
case 16:
if (spec->channels==2) {
channels_mode=STEREO16;
} else {
channels_mode=MONO16;
}
break;
default:
channels_mode=STEREO16;
break;
}
if (Setmode(channels_mode)<0) {
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}
Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
}
/* Install interrupt */
if (NSetinterrupt(2, SI_PLAY, SDL_MintAudio_GsxbInterrupt)<0) {
DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n"));
}
/* Go */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
/* Lock sound system */
if (Locksnd()!=1) {
SDL_SetError("Mint_OpenAudio: Audio system already in use");
return(-1);
}
SDL_MintAudio_device = this;
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec)==-1) {
return -1;
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
/* Setup audio hardware */
Mint_InitAudio(this, spec);
return(1); /* We don't use threaded audio */
}

View File

@ -0,0 +1,85 @@
/*
* GSXB audio definitions
*
* Patrice Mandin
*/
#ifndef _SDL_mintaudio_gsxb_h
#define _SDL_mintaudio_gsxb_h
#include <mint/falcon.h> /* for trap_14_xxx macros */
/* GSXB Cookie */
#define C_GSXB 0x47535842L
/* Bit 5 in cookie _SND */
#define SND_GSXB (1<<5)
/* NSoundcmd modes */
#define SETRATE 7 /* Set sample rate */
#define SET8BITFORMAT 8 /* 8 bits format */
#define SET16BITFORMAT 9 /* 16 bits format */
#define SET24BITFORMAT 10 /* 24 bits format */
#define SET32BITFORMAT 11 /* 32 bits format */
#define LTATTEN_MASTER 12 /* Attenuation */
#define RTATTEN_MASTER 13
#define LTATTEN_MICIN 14
#define RTATTEN_MICIN 15
#define LTATTEN_FMGEN 16
#define RTATTEN_FMGEN 17
#define LTATTEN_LINEIN 18
#define RTATTEN_LINEIN 19
#define LTATTEN_CDIN 20
#define RTATTEN_CDIN 21
#define LTATTEN_VIDIN 22
#define RTATTEN_VIDIN 23
#define LTATTEN_AUXIN 24
#define RTATTEN_AUXIN 25
/* Setmode modes */
#define MONO16 3
#define STEREO24 4
#define STEREO32 5
#define MONO24 6
#define MONO32 7
/* Sndstatus modes */
#define SND_QUERYFORMATS 2
#define SND_QUERYMIXERS 3
#define SND_QUERYSOURCES 4
#define SND_QUERYDUPLEX 5
#define SND_QUERY8BIT 8
#define SND_QUERY16BIT 9
#define SND_QUERY24BIT 10
#define SND_QUERY32BIT 11
#define SND_FORMAT8 (1<<0)
#define SND_FORMAT16 (1<<1)
#define SND_FORMAT24 (1<<2)
#define SND_FORMAT32 (1<<3)
#define SND_FORMATSIGNED (1<<0)
#define SND_FORMATUNSIGNED (1<<1)
#define SND_FORMATBIGENDIAN (1<<2)
#define SND_FORMATLITTLEENDIAN (1<<3)
/* Devconnect prescalers */
#define CLK_44K 1
#define CLK_22K 3
#define CLK_11K 7
/* Extra xbios functions */
#define NSoundcmd(mode,data,data2) \
(long)trap_14_wwl((short)130,(short)(mode),(short)(data),(long)(data2))
#define NSetinterrupt(src_inter,cause,inth_addr) \
(long)trap_14_wwwl((short)135,(short)(src_inter),(short)(cause), \
(long)(inth_addr))
#endif /* _SDL_mintaudio_gsxb_h */

View File

@ -0,0 +1,242 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
Audio interrupts
Patrice Mandin
*/
.text
.globl _SDL_MintAudio_Callback
.globl _SDL_MintAudio_GsxbInterrupt
.globl _SDL_MintAudio_EmptyGsxbInterrupt
.globl _SDL_MintAudio_XbiosInterrupt
.globl _SDL_MintAudio_Dma8Interrupt
.globl _SDL_MintAudio_StfaInterrupt
.globl _SDL_MintAudio_mutex
.globl _SDL_MintAudio_audiobuf
.globl _SDL_MintAudio_numbuf
.globl _SDL_MintAudio_audiosize
.globl _SDL_MintAudio_stfa
/*
How it works:
- Audio is playing buffer #0 (resp. #1)
- We must calculate a sample in buffer #1 (resp. #0)
so we first call the callback to do it
- Then we swap the buffers
*/
/*--- GSXB interrupt vector ---*/
.text
_SDL_MintAudio_GsxbInterrupt:
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes _SDL_MintAudio_EmptyGsxbInterrupt
notw _SDL_MintAudio_mutex
/* Swap buffers */
moveml d0-d2/a0-a2,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,a0
eorl #1,d0
beqs SDL_MintAudio_GsxbBuffer0
movel _SDL_MintAudio_audiobuf+4,a0
SDL_MintAudio_GsxbBuffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
movel a0,sp@-
jsr _SDL_MintAudio_Callback
movel sp@+,a0
/* Setbuffer xbios function */
movel _SDL_MintAudio_audiosize,d1
lea a0@(0,d1:l),a1
movel a1,sp@-
movel a0,sp@-
clrw sp@-
movew #131,sp@-
trap #14
lea sp@(12),sp
moveml sp@+,d0-d2/a0-a2
clrw _SDL_MintAudio_mutex
_SDL_MintAudio_EmptyGsxbInterrupt:
rts
/*--- Xbios interrupt vector ---*/
_SDL_MintAudio_XbiosInterrupt:
/* Reenable interrupts, so other interrupts can work */
movew #0x2300,sr
/* Clear service bit, so other MFP interrupts can work */
bclr #5,0xfffffa0f:w
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes SDL_MintAudio_XbiosEnd
notw _SDL_MintAudio_mutex
/* Swap buffers */
moveml d0-d2/a0-a2,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,a0
eorl #1,d0
beqs SDL_MintAudio_XbiosBuffer0
movel _SDL_MintAudio_audiobuf+4,a0
SDL_MintAudio_XbiosBuffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
movel a0,sp@-
jsr _SDL_MintAudio_Callback
movel sp@+,a0
/* Setbuffer xbios function */
movel _SDL_MintAudio_audiosize,d1
lea a0@(0,d1:l),a1
movel a1,sp@-
movel a0,sp@-
clrw sp@-
movew #131,sp@-
trap #14
lea sp@(12),sp
moveml sp@+,d0-d2/a0-a2
clrw _SDL_MintAudio_mutex
SDL_MintAudio_XbiosEnd:
rte
/*--- DMA 8 bits interrupt vector ---*/
_SDL_MintAudio_Dma8Interrupt:
/* Reenable interrupts, so other interrupts can work */
movew #0x2300,sr
/* Clear service bit, so other MFP interrupts can work */
bclr #5,0xfffffa0f:w
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes SDL_MintAudio_Dma8End
notw _SDL_MintAudio_mutex
/* Swap buffers */
moveml d0-d1/a0-a1,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,d1
eorl #1,d0
beqs SDL_MintAudio_Dma8Buffer0
movel _SDL_MintAudio_audiobuf+4,d1
SDL_MintAudio_Dma8Buffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
movel d1,sp@-
jsr _SDL_MintAudio_Callback
movel sp@+,d1
/* Modify DMA addresses */
lea 0xffff8900:w,a0
moveb d1,a0@(0x07) /* Start address */
rorl #8,d1
moveb d1,a0@(0x05)
rorl #8,d1
moveb d1,a0@(0x03)
swap d1
addl _SDL_MintAudio_audiosize,d1
moveb d1,a0@(0x13) /* End address */
rorl #8,d1
moveb d1,a0@(0x11)
rorl #8,d1
moveb d1,a0@(0x0f)
moveml sp@+,d0-d1/a0-a1
clrw _SDL_MintAudio_mutex
SDL_MintAudio_Dma8End:
rte
/*--- STFA interrupt vector ---*/
STFA_SOUND_START = 6
STFA_SOUND_END = STFA_SOUND_START+8
_SDL_MintAudio_StfaInterrupt:
/* Reenable interrupts, so other interrupts can work */
movew #0x2300,sr
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes SDL_MintAudio_StfaEnd
notw _SDL_MintAudio_mutex
/* Swap buffers */
moveml d0-d1/a0-a1,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,d1
eorl #1,d0
beqs SDL_MintAudio_StfaBuffer0
movel _SDL_MintAudio_audiobuf+4,d1
SDL_MintAudio_StfaBuffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
movel d1,sp@-
jsr _SDL_MintAudio_Callback
movel sp@+,d1
/* Modify STFA replay buffers */
movel _SDL_MintAudio_stfa,a0
movel d1,a0@(STFA_SOUND_START)
addl _SDL_MintAudio_audiosize,d1
movel d1,a0@(STFA_SOUND_END)
moveml sp@+,d0-d1/a0-a1
clrw _SDL_MintAudio_mutex
SDL_MintAudio_StfaEnd:
rte

View File

@ -0,0 +1,379 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
using XBIOS functions (MacSound compatible driver)
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_atarimxalloc_c.h"
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_mcsn.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_mcsn"
/* Debug print info */
#define DEBUG_NAME "audio:mcsn: "
#if 0
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_mch;
static cookie_mcsn_t *cookie_mcsn;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return(0);
}
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST;
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Check if we have 16 bits audio */
if ((cookie_snd & SND_16BIT)==0) {
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
return(0);
}
/* Cookie MCSN present ? */
if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
return(0);
}
/* Check if interrupt at end of replay */
if (cookie_mcsn->pint == 0) {
DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
return(0);
}
/* Check if audio is lockable */
if (Locksnd()!=1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return(0);
}
Unlocksnd();
DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
return(1);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
}
static void Mint_UnlockAudio(_THIS)
{
/* Restart replay */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
}
static void Mint_CloseAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
/* Uninstall interrupt */
Jdisint(MFP_DMASOUND);
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
/* Unlock sound system */
Unlocksnd();
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
int i;
unsigned long masterclock, masterprediv;
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
/* Check formats available */
MINTAUDIO_nfreq=4;
MINTAUDIO_sfreq=0;
switch(cookie_mcsn->play) {
case MCSN_ST:
spec->channels=1;
spec->format=8; /* FIXME: is it signed or unsigned ? */
MINTAUDIO_nfreq=1;
MINTAUDIO_hardfreq[0]=12500;
break;
case MCSN_TT: /* Also STE, Mega STE */
spec->format=AUDIO_S8;
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
if ((cookie_mch>>16)==MCH_TT) {
masterclock=MASTERCLOCK_TT;
masterprediv=MASTERPREDIV_TT;
}
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
break;
case MCSN_FALCON: /* Also Mac */
MINTAUDIO_nfreq=12;
MINTAUDIO_sfreq=1;
masterclock=MASTERCLOCK_FALCON1;
if (cookie_mcsn->res1 != 0) {
masterclock=cookie_mcsn->res1;
}
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=masterclock/(MASTERPREDIV_FALCON*(i+1));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
spec->format |= 0x8000; /* Audio is always signed */
if ((spec->format & 0x00ff)==16) {
spec->format |= 0x1000; /* Audio is always big endian */
spec->channels=2; /* 16 bits always stereo */
}
break;
}
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, (cookie_mch>>16)==MCH_F30, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
return 0;
}
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
int channels_mode;
void *buffer;
/* Stop currently playing sound */
Buffoper(0);
/* Set replay tracks */
Settracks(0,0);
Setmontracks(0);
/* Select replay format */
channels_mode=STEREO16;
switch (spec->format & 0xff) {
case 8:
if (spec->channels==2) {
channels_mode=STEREO8;
} else {
channels_mode=MONO8;
}
break;
}
if (Setmode(channels_mode)<0) {
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}
switch(cookie_mcsn->play) {
case MCSN_TT:
Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1);
Soundcmd(SETPRESCALE, 3-MINTAUDIO_numfreq);
DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n"));
break;
case MCSN_FALCON:
if (cookie_mcsn->res1 != 0) {
Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
DEBUG_PRINT((DEBUG_NAME "External clock selected, prescaler %d\n", MINTAUDIO_numfreq));
} else {
Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
}
break;
}
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
}
/* Install interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
Jenabint(MFP_DMASOUND);
if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
/* Go */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
/* Lock sound system */
if (Locksnd()!=1) {
SDL_SetError("Mint_OpenAudio: Audio system already in use");
return(-1);
}
SDL_MintAudio_device = this;
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec)==-1) {
return -1;
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
/* Setup audio hardware */
Mint_InitAudio(this, spec);
return(1); /* We don't use threaded audio */
}

View File

@ -0,0 +1,58 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MCSN control structure
Patrice Mandin
*/
#ifndef _SDL_mintaudio_mcsh_h
#define _SDL_mintaudio_mcsh_h
typedef struct {
unsigned short version; /* Version */
unsigned short size; /* Size of structure */
unsigned short play; /* Replay capability */
unsigned short record; /* Record capability */
unsigned short dsp; /* DSP56K present */
unsigned short pint; /* Interrupt at end of replay */
unsigned short rint; /* Interrupt at end of record */
unsigned long res1; /* Frequency of external clock */
unsigned long res2;
unsigned long res3;
unsigned long res4;
} cookie_mcsn_t __attribute__((packed));
enum {
MCSN_ST=0,
MCSN_TT,
MCSN_STE=MCSN_TT,
MCSN_FALCON,
MCSN_MAC=MCSN_FALCON
};
#define SETSMPFREQ 7 /* Set sample frequency */
#endif /* _SDL_mintaudio_mcsh_h */

View File

@ -0,0 +1,319 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
using XBIOS functions (STFA driver)
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_atarimxalloc_c.h"
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_stfa.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_stfa"
/* Debug print info */
#define DEBUG_NAME "audio:stfa: "
#if 0
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_mch;
static cookie_stfa_t *cookie_stfa;
static const int freqs[16]={
4995, 6269, 7493, 8192,
9830, 10971, 12538, 14985,
16384, 19819, 21943, 24576,
30720, 32336, 43885, 49152
};
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return(0);
}
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST;
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Cookie STFA present ? */
if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) {
DEBUG_PRINT((DEBUG_NAME "no STFA audio\n"));
return(0);
}
SDL_MintAudio_stfa = cookie_stfa;
DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n"));
return(1);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_STFA_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
void *oldpile;
/* Stop replay */
oldpile=(void *)Super(0);
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
Super(oldpile);
}
static void Mint_UnlockAudio(_THIS)
{
void *oldpile;
/* Restart replay */
oldpile=(void *)Super(0);
cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
Super(oldpile);
}
static void Mint_CloseAudio(_THIS)
{
void *oldpile;
/* Stop replay */
oldpile=(void *)Super(0);
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
Super(oldpile);
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
int i;
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
/* Check formats available */
MINTAUDIO_nfreq=16;
MINTAUDIO_sfreq=0;
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=freqs[15-i];
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
return 0;
}
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
void *buffer;
void *oldpile;
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
oldpile=(void *)Super(0);
/* Stop replay */
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
/* Select replay format */
cookie_stfa->sound_control = 15-MINTAUDIO_numfreq;
if ((spec->format & 0xff)==8) {
cookie_stfa->sound_control |= STFA_FORMAT_8BIT;
} else {
cookie_stfa->sound_control |= STFA_FORMAT_16BIT;
}
if (spec->channels==2) {
cookie_stfa->sound_control |= STFA_FORMAT_STEREO;
} else {
cookie_stfa->sound_control |= STFA_FORMAT_MONO;
}
if (spec->format & 0x8000) {
cookie_stfa->sound_control |= STFA_FORMAT_SIGNED;
} else {
cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED;
}
if (spec->format & 0x1000) {
cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN;
} else {
cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN;
}
/* Set buffer */
cookie_stfa->sound_start = (unsigned long) buffer;
cookie_stfa->sound_end = (unsigned long) (buffer + spec->size);
/* Set interrupt */
cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt;
/* Restart replay */
cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
Super(oldpile);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
SDL_MintAudio_device = this;
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec)==-1) {
return -1;
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
/* Setup audio hardware */
Mint_InitAudio(this, spec);
return(1); /* We don't use threaded audio */
}

View File

@ -0,0 +1,99 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
STFA control structure
Patrice Mandin
*/
#ifndef _SDL_mintaudio_stfa_h
#define _SDL_mintaudio_stfa_h
/*--- Defines ---*/
#define C_STFA 0x53544641L /* Sound treiber für atari (seb/The removers) */
#define STFA_PLAY_ENABLE (1<<0)
#define STFA_PLAY_DISABLE (0<<0)
#define STFA_PLAY_REPEAT (1<<1)
#define STFA_PLAY_SINGLE (0<<1)
#define STFA_FORMAT_SIGNED (1<<15)
#define STFA_FORMAT_UNSIGNED (0<<15)
#define STFA_FORMAT_STEREO (1<<14)
#define STFA_FORMAT_MONO (0<<14)
#define STFA_FORMAT_16BIT (1<<13)
#define STFA_FORMAT_8BIT (0<<13)
#define STFA_FORMAT_LITENDIAN (1<<9)
#define STFA_FORMAT_BIGENDIAN (0<<9)
#define STFA_FORMAT_FREQ_MASK 0x0f
enum {
STFA_FORMAT_F4995=0,
STFA_FORMAT_F6269,
STFA_FORMAT_F7493,
STFA_FORMAT_F8192,
STFA_FORMAT_F9830,
STFA_FORMAT_F10971,
STFA_FORMAT_F12538,
STFA_FORMAT_F14985,
STFA_FORMAT_F16384,
STFA_FORMAT_F19819,
STFA_FORMAT_F21943,
STFA_FORMAT_F24576,
STFA_FORMAT_F30720,
STFA_FORMAT_F32336,
STFA_FORMAT_F43885,
STFA_FORMAT_F49152
};
/*--- Types ---*/
typedef struct {
unsigned short sound_enable;
unsigned short sound_control;
unsigned short sound_output;
unsigned long sound_start;
unsigned long sound_current;
unsigned long sound_end;
unsigned short version;
void *old_vbl;
void *old_timera;
unsigned long old_mfp_status;
void *new_vbl;
void *drivers_list;
void *play_stop;
unsigned short frequency;
void *set_frequency;
unsigned short frequency_threshold;
unsigned short *custom_freq_table;
unsigned short stfa_on_off;
void *new_drivers_list;
unsigned long old_bit_2_of_cookie_snd;
void (*stfa_it)(void);
} cookie_stfa_t __attribute__((packed));
#endif /* _SDL_mintaudio_stfa_h */

View File

@ -0,0 +1,319 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
/*
MiNT audio driver
using XBIOS functions (Falcon)
Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_endian.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
#include "SDL_atarimxalloc_c.h"
#include "SDL_mintaudio.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_xbios"
/* Debug print info */
#define DEBUG_NAME "audio:xbios: "
#if 0
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd;
/*--- Audio driver functions ---*/
static void Mint_CloseAudio(_THIS);
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_LockAudio(_THIS);
static void Mint_UnlockAudio(_THIS);
/* To check/init hardware audio */
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
/*--- Audio driver bootstrap functions ---*/
static int Audio_Available(void)
{
const char *envr = getenv("SDL_AUDIODRIVER");
/* Check if user asked a different audio driver */
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
return(0);
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Check if we have 16 bits audio */
if ((cookie_snd & SND_16BIT)==0) {
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
return(0);
}
/* Check if audio is lockable */
if (Locksnd()!=1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return(0);
}
Unlocksnd();
DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
return(1);
}
static void Audio_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = Mint_OpenAudio;
this->CloseAudio = Mint_CloseAudio;
this->LockAudio = Mint_LockAudio;
this->UnlockAudio = Mint_UnlockAudio;
this->free = Audio_DeleteDevice;
return this;
}
AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
Audio_Available, Audio_CreateDevice
};
static void Mint_LockAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
}
static void Mint_UnlockAudio(_THIS)
{
/* Restart replay */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
}
static void Mint_CloseAudio(_THIS)
{
/* Stop replay */
Buffoper(0);
/* Uninstall interrupt */
Jdisint(MFP_DMASOUND);
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {
}
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
/* Unlock sound system */
Unlocksnd();
}
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
{
int i;
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
spec->format |= 0x8000; /* Audio is always signed */
if ((spec->format & 0x00ff)==16) {
spec->format |= 0x1000; /* Audio is always big endian */
spec->channels=2; /* 16 bits always stereo */
}
/* FIXME: check for an external clock */
MINTAUDIO_sfreq=1;
MINTAUDIO_nfreq=12;
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
MINTAUDIO_hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
}
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
DEBUG_PRINT(("channels=%d, ", spec->channels));
DEBUG_PRINT(("freq=%d\n", spec->freq));
return 0;
}
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
{
int channels_mode;
void *buffer;
/* Stop currently playing sound */
Buffoper(0);
/* Set replay tracks */
Settracks(0,0);
Setmontracks(0);
/* Select replay format */
channels_mode=STEREO16;
switch (spec->format & 0xff) {
case 8:
if (spec->channels==2) {
channels_mode=STEREO8;
} else {
channels_mode=MONO8;
}
break;
}
if (Setmode(channels_mode)<0) {
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}
/* FIXME: select an external clock */
Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
}
/* Install interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
Jenabint(MFP_DMASOUND);
if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
/* Go */
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
}
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
/* Lock sound system */
if (Locksnd()!=1) {
SDL_SetError("Mint_OpenAudio: Audio system already in use");
return(-1);
}
SDL_MintAudio_device = this;
/* Check audio capabilities */
if (Mint_CheckAudio(this, spec)==-1) {
return -1;
}
SDL_CalculateAudioSpec(spec);
/* Allocate memory for audio buffers in DMA-able RAM */
spec->size = spec->samples;
spec->size *= spec->channels;
spec->size *= (spec->format & 0xFF)/8;
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
if (SDL_MintAudio_audiobuf[0]==NULL) {
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
return (-1);
}
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
SDL_MintAudio_numbuf=0;
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
SDL_MintAudio_audiosize = spec->size;
SDL_MintAudio_mutex = 0;
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
/* Setup audio hardware */
Mint_InitAudio(this, spec);
return(1); /* We don't use threaded audio */
}