From 2c51509ace6b7988939c95e5030876556cf77ca1 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Mon, 7 Jul 2003 19:16:03 +0000 Subject: [PATCH] Atari MiNT: added more audio drivers --- README.MiNT | 43 +- src/audio/SDL_audio.c | 6 +- src/audio/SDL_sysaudio.h | 6 +- src/audio/mint/Makefile.am | 19 +- src/audio/mint/SDL_mintaudio.c | 649 +++------------------------ src/audio/mint/SDL_mintaudio.h | 118 ++++- src/audio/mint/SDL_mintaudio_dma8.c | 354 +++++++++++++++ src/audio/mint/SDL_mintaudio_dma8.h | 65 +++ src/audio/mint/SDL_mintaudio_gsxb.c | 395 ++++++++++++++++ src/audio/mint/SDL_mintaudio_gsxb.h | 85 ++++ src/audio/mint/SDL_mintaudio_it.S | 242 ++++++++++ src/audio/mint/SDL_mintaudio_mcsn.c | 379 ++++++++++++++++ src/audio/mint/SDL_mintaudio_mcsn.h | 58 +++ src/audio/mint/SDL_mintaudio_stfa.c | 319 +++++++++++++ src/audio/mint/SDL_mintaudio_stfa.h | 99 ++++ src/audio/mint/SDL_mintaudio_xbios.c | 319 +++++++++++++ 16 files changed, 2538 insertions(+), 618 deletions(-) create mode 100644 src/audio/mint/SDL_mintaudio_dma8.c create mode 100644 src/audio/mint/SDL_mintaudio_dma8.h create mode 100644 src/audio/mint/SDL_mintaudio_gsxb.c create mode 100644 src/audio/mint/SDL_mintaudio_gsxb.h create mode 100644 src/audio/mint/SDL_mintaudio_it.S create mode 100644 src/audio/mint/SDL_mintaudio_mcsn.c create mode 100644 src/audio/mint/SDL_mintaudio_mcsn.h create mode 100644 src/audio/mint/SDL_mintaudio_stfa.c create mode 100644 src/audio/mint/SDL_mintaudio_stfa.h create mode 100644 src/audio/mint/SDL_mintaudio_xbios.c diff --git a/README.MiNT b/README.MiNT index 47ba057aa..ea389ed86 100644 --- a/README.MiNT +++ b/README.MiNT @@ -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 diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index ce066d6ec..23ebbdaa5 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -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, diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 35e096d30..4a745dcc6 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -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; diff --git a/src/audio/mint/Makefile.am b/src/audio/mint/Makefile.am index 57ca3e7f6..21d910d94 100644 --- a/src/audio/mint/Makefile.am +++ b/src/audio/mint/Makefile.am @@ -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 diff --git a/src/audio/mint/SDL_mintaudio.c b/src/audio/mint/SDL_mintaudio.c index abec45412..99a99c614 100644 --- a/src/audio/mint/SDL_mintaudio.c +++ b/src/audio/mint/SDL_mintaudio.c @@ -1,628 +1,93 @@ /* - * MiNT audio driver - * - * Patrice Mandin - */ + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga -#include -#include -#include - -/* Mint includes */ -#include -#include -#include - -#include "SDL_endian.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_atarimxalloc_c.h" - -/*--- Defines ---*/ - -#define MINT_AUDIO_DRIVER_NAME "mint" - -/* 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 ---*/ + 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. -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; - } + 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. - /* 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); -} + 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 -static SDL_AudioDevice *Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; + Sam Lantinga + slouken@libsdl.org +*/ - /* 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); - } +/* + Audio interrupt variables and callback function - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; + Patrice Mandin +*/ - return this; -} +#include -AudioBootStrap MINTAUDIO_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT audio driver", - Audio_Available, Audio_CreateDevice -}; +#include "SDL_types.h" +#include "SDL_audio.h" -static void Mint_LockAudio(_THIS) -{ - void *oldpile; +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_stfa.h" - /* 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); - } -} +/* The audio device */ -static void Mint_UnlockAudio(_THIS) -{ - void *oldpile; +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; - /* 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); - } -} +/* The callback function, called by each driver whenever needed */ -/* 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]; - - 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); + memset(buffer, SDL_MintAudio_device->spec.silence, SDL_MintAudio_device->spec.size); + + 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)); - } - - 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; - } -} - -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)); + /* Only 1 freq ? */ + if (MINTAUDIO_nfreq==1) { + return(MINTAUDIO_sfreq); } - /* 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; + /* Check the array */ + for (i=MINTAUDIO_sfreq; iformat = 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; + if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) { + return i; } } - - /* 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; } diff --git a/src/audio/mint/SDL_mintaudio.h b/src/audio/mint/SDL_mintaudio.h index 18cf7a447..5e6a0a7e6 100644 --- a/src/audio/mint/SDL_mintaudio.h +++ b/src/audio/mint/SDL_mintaudio.h @@ -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 */ diff --git a/src/audio/mint/SDL_mintaudio_dma8.c b/src/audio/mint/SDL_mintaudio_dma8.c new file mode 100644 index 000000000..e285128e4 --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_dma8.c @@ -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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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;ifreq); + 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 */ +} diff --git a/src/audio/mint/SDL_mintaudio_dma8.h b/src/audio/mint/SDL_mintaudio_dma8.h new file mode 100644 index 000000000..7d05d88c1 --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_dma8.h @@ -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 */ diff --git a/src/audio/mint/SDL_mintaudio_gsxb.c b/src/audio/mint/SDL_mintaudio_gsxb.c new file mode 100644 index 000000000..0caf28e2e --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_gsxb.c @@ -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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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;ifreq); + 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 */ +} diff --git a/src/audio/mint/SDL_mintaudio_gsxb.h b/src/audio/mint/SDL_mintaudio_gsxb.h new file mode 100644 index 000000000..21bb96f36 --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_gsxb.h @@ -0,0 +1,85 @@ +/* + * GSXB audio definitions + * + * Patrice Mandin + */ + +#ifndef _SDL_mintaudio_gsxb_h +#define _SDL_mintaudio_gsxb_h + +#include /* 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 */ diff --git a/src/audio/mint/SDL_mintaudio_it.S b/src/audio/mint/SDL_mintaudio_it.S new file mode 100644 index 000000000..a6a999f83 --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_it.S @@ -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 + diff --git a/src/audio/mint/SDL_mintaudio_mcsn.c b/src/audio/mint/SDL_mintaudio_mcsn.c new file mode 100644 index 000000000..e27f727bb --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_mcsn.c @@ -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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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;ires1 != 0) { + masterclock=cookie_mcsn->res1; + } + for (i=MINTAUDIO_sfreq;iformat |= 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 */ +} diff --git a/src/audio/mint/SDL_mintaudio_mcsn.h b/src/audio/mint/SDL_mintaudio_mcsn.h new file mode 100644 index 000000000..ea82301ac --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_mcsn.h @@ -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 */ diff --git a/src/audio/mint/SDL_mintaudio_stfa.c b/src/audio/mint/SDL_mintaudio_stfa.c new file mode 100644 index 000000000..33a0ec90d --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_stfa.c @@ -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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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;ifreq); + 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 */ +} diff --git a/src/audio/mint/SDL_mintaudio_stfa.h b/src/audio/mint/SDL_mintaudio_stfa.h new file mode 100644 index 000000000..d37c4efde --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_stfa.h @@ -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 */ diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c new file mode 100644 index 000000000..708666edd --- /dev/null +++ b/src/audio/mint/SDL_mintaudio_xbios.c @@ -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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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;ifreq); + 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 */ +}