Commit 35d6bbe9 authored by Sam Lantinga's avatar Sam Lantinga

Added Atari audio support (thanks Patrice!)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40399
parent dee1deeb
...@@ -10,9 +10,8 @@ I. Building the Simple DirectMedia Layer libraries: ...@@ -10,9 +10,8 @@ I. Building the Simple DirectMedia Layer libraries:
Do the classic configure, with --disable-shared --enable-static and: Do the classic configure, with --disable-shared --enable-static and:
Tos version (should run everywhere): Tos version (should run everywhere):
--disable-audio --disable-threads --disable-threads
Tos does not support threads, so can not support audio, maybe in a future Tos does not support threads.
version audio support will be added via interrupts.
MiNT version (maybe Magic, only for multitasking OS): MiNT version (maybe Magic, only for multitasking OS):
--disable-pthreads --enable-pth --disable-pthreads --enable-pth
...@@ -50,11 +49,11 @@ Mouse (XBIOS, GEM, Ikbd) ...@@ -50,11 +49,11 @@ Mouse (XBIOS, GEM, Ikbd)
Video (XBIOS (Fullscreen), GEM (Windowed and Fullscreen)) Video (XBIOS (Fullscreen), GEM (Windowed and Fullscreen))
Timer (VBL vector) Timer (VBL vector)
Joystick and joypad support (Ikbd, Hardware) Joystick and joypad support (Ikbd, Hardware)
Audio support (Hardware, XBIOS, GSXB, /dev/audio if threads enabled)
Threads support (Multitasking OS only via GNU pth library)
- What is missing: - What is missing:
Audio support (TOS)
CDROM support (Metados, /dev/cdrom) CDROM support (Metados, /dev/cdrom)
Threads support (TOS)
- Driver combinations: - Driver combinations:
Video Kbd Mouse Timer Jstick Joypads Video Kbd Mouse Timer Jstick Joypads
...@@ -69,15 +68,20 @@ to report this type event. ...@@ -69,15 +68,20 @@ to report this type event.
============================================================================== ==============================================================================
V. Environment variables: V. Environment variables:
SDL_VIDEODRIVER:
Set to 'xbios' to force xbios video driver
Set to 'gem' to force gem video driver
SDL_AUDIODRIVER:
Set to 'mint' to force Atari audio driver
Set to 'audio' to force Sun /dev/audio audio driver
Set to 'disk' to force disk-writing audio driver
SDL_ATARI_EVENTSDRIVER SDL_ATARI_EVENTSDRIVER
Set to 'ikbd' to force IKBD 6301 keyboard driver Set to 'ikbd' to force IKBD 6301 keyboard driver
Set to 'gemdos' to force gemdos keyboard driver Set to 'gemdos' to force gemdos keyboard driver
Set to 'bios' to force bios keyboard driver Set to 'bios' to force bios keyboard driver
SDL_VIDEODRIVER:
Set to 'xbios' to force xbios video driver
Set to 'gem' to force gem video driver
SDL_JOYSTICK_ATARI: SDL_JOYSTICK_ATARI:
Use any of these strings in the environment variable to enable or Use any of these strings in the environment variable to enable or
disable a joystick: disable a joystick:
...@@ -151,7 +155,19 @@ Joypad driver: ...@@ -151,7 +155,19 @@ Joypad driver:
Available if _MCH cookie is STE or Falcon. Available if _MCH cookie is STE or Falcon.
VBL timer driver: VBL timer driver:
Available all machines (I think). Available on all machines (I think).
Audio driver:
Cookie _SND is used to detect supported audio capabilities
STE, Mega STE, TT:
8 bits DMA (hardware access)
Falcon, machines with GSXB driver:
Xbios functions
Other machines:
Not supported
-- --
Patrice Mandin <pmandin@caramail.com> Patrice Mandin <pmandin@caramail.com>
......
...@@ -435,6 +435,24 @@ CheckDiskAudio() ...@@ -435,6 +435,24 @@ CheckDiskAudio()
fi fi
} }
dnl Set up the Atari Audio driver
CheckAtariAudio()
{
AC_ARG_ENABLE(mintaudio,
[ --enable-mintaudio support Atari audio driver [default=yes]],
, enable_mintaudio=yes)
if test x$enable_audio = xyes -a x$enable_mintaudio = xyes; then
mintaudio=no
AC_CHECK_HEADER(mint/falcon.h, have_mint_falcon_hdr=yes)
if test x$have_mint_falcon_hdr = xyes; then
mintaudio=yes
CFLAGS="$CFLAGS -DMINTAUDIO_SUPPORT"
AUDIO_SUBDIRS="$AUDIO_SUBDIRS mint"
AUDIO_DRIVERS="$AUDIO_DRIVERS mint/libaudio_mintaudio.la"
fi
fi
}
dnl See if we can use x86 assembly blitters dnl See if we can use x86 assembly blitters
# NASM is available from: http://nasm.octium.net/ # NASM is available from: http://nasm.octium.net/
CheckNASM() CheckNASM()
...@@ -2380,13 +2398,17 @@ case "$target" in ...@@ -2380,13 +2398,17 @@ case "$target" in
CheckAtariBiosEvent CheckAtariBiosEvent
CheckAtariXbiosVideo CheckAtariXbiosVideo
CheckAtariGemVideo CheckAtariGemVideo
CheckAtariAudio
CheckPTH CheckPTH
# Set up files for the main() stub # Set up files for the main() stub
COPY_ARCH_SRC(src/main, linux, SDL_main.c) COPY_ARCH_SRC(src/main, linux, SDL_main.c)
# Set up files for the audio library # Set up files for the audio library
if test x$enable_audio = xyes; then if test x$enable_threads = xyes -a x$enable_pth = xyes; then
AUDIO_SUBDIRS="$AUDIO_SUBDIRS sun" if test x$enable_audio = xyes; then
AUDIO_DRIVERS="$AUDIO_DRIVERS sun/libaudio_sun.la" CFLAGS="$CFLAGS -DSUNAUDIO_SUPPORT"
AUDIO_SUBDIRS="$AUDIO_SUBDIRS sun"
AUDIO_DRIVERS="$AUDIO_DRIVERS sun/libaudio_sun.la"
fi
fi fi
# Set up files for the joystick library # Set up files for the joystick library
if test x$enable_joystick = xyes; then if test x$enable_joystick = xyes; then
...@@ -2575,6 +2597,7 @@ src/audio/ums/Makefile ...@@ -2575,6 +2597,7 @@ src/audio/ums/Makefile
src/audio/windib/Makefile src/audio/windib/Makefile
src/audio/windx5/Makefile src/audio/windx5/Makefile
src/audio/disk/Makefile src/audio/disk/Makefile
src/audio/mint/Makefile
src/video/Makefile src/video/Makefile
src/video/XFree86/Makefile src/video/XFree86/Makefile
src/video/XFree86/extensions/Makefile src/video/XFree86/extensions/Makefile
......
...@@ -5,7 +5,8 @@ noinst_LTLIBRARIES = libaudio.la ...@@ -5,7 +5,8 @@ noinst_LTLIBRARIES = libaudio.la
# Define which subdirectories need to be built # Define which subdirectories need to be built
SUBDIRS = @AUDIO_SUBDIRS@ SUBDIRS = @AUDIO_SUBDIRS@
DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd paudio sun ums windib windx5 disk DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd \
paudio sun ums windib windx5 disk mint
DRIVERS = @AUDIO_DRIVERS@ DRIVERS = @AUDIO_DRIVERS@
......
...@@ -83,6 +83,9 @@ static AudioBootStrap *bootstrap[] = { ...@@ -83,6 +83,9 @@ static AudioBootStrap *bootstrap[] = {
#ifdef ENABLE_AHI #ifdef ENABLE_AHI
&AHI_bootstrap, &AHI_bootstrap,
#endif #endif
#ifdef MINTAUDIO_SUPPORT
&MINTAUDIO_bootstrap,
#endif
#ifdef DISKAUD_SUPPORT #ifdef DISKAUD_SUPPORT
&DISKAUD_bootstrap, &DISKAUD_bootstrap,
#endif #endif
...@@ -377,6 +380,9 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) ...@@ -377,6 +380,9 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
#ifdef macintosh #ifdef macintosh
/* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */ /* FIXME: Need to implement PPC interrupt asm for SDL_LockAudio() */
#else
#if defined(__MINT__) && !defined(ENABLE_THREADS)
/* Uses interrupt driven audio, without thread */
#else #else
/* Create a semaphore for locking the sound buffers */ /* Create a semaphore for locking the sound buffers */
audio->mixer_lock = SDL_CreateMutex(); audio->mixer_lock = SDL_CreateMutex();
...@@ -385,7 +391,8 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) ...@@ -385,7 +391,8 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
SDL_CloseAudio(); SDL_CloseAudio();
return(-1); return(-1);
} }
#endif #endif /* __MINT__ */
#endif /* macintosh */
/* Calculate the silence and size of the audio specification */ /* Calculate the silence and size of the audio specification */
SDL_CalculateAudioSpec(desired); SDL_CalculateAudioSpec(desired);
......
...@@ -147,6 +147,9 @@ extern AudioBootStrap SNDMGR_bootstrap; ...@@ -147,6 +147,9 @@ extern AudioBootStrap SNDMGR_bootstrap;
#ifdef ENABLE_AHI #ifdef ENABLE_AHI
extern AudioBootStrap AHI_bootstrap; extern AudioBootStrap AHI_bootstrap;
#endif #endif
#ifdef MINTAUDIO_SUPPORT
extern AudioBootStrap MINTAUDIO_bootstrap;
#endif
#ifdef DISKAUD_SUPPORT #ifdef DISKAUD_SUPPORT
extern AudioBootStrap DISKAUD_bootstrap; extern AudioBootStrap DISKAUD_bootstrap;
#endif #endif
......
Makefile.in
Makefile
.libs
*.o
*.lo
*.la
## 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 \
SDL_mintaudio.h \
SDL_mintaudiointerrupt.S \
SDL_mintaudiointerrupt_s.h \
SDL_mintaudiodma.h \
SDL_mintaudiogsxb.h
/*
* MiNT audio driver
*
* Patrice Mandin
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <sys/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_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 ---*/
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];
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);
} else {
audio->spec.callback(audio->spec.userdata, buffer, audio->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)
{
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));
}
/* 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 (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;
}
/*
* MiNT audio driver
*
* Patrice Mandin
*/
#ifndef _SDL_mintaudio_h
#define _SDL_mintaudio_h
#include "SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
#endif /* _SDL_mintaudio_h */
/*
* STE/TT 8 bits audio dma registers
*
* Patrice Mandin
*/
#ifndef _SDL_mintdma_h
#define _SDL_mintdma_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_mintdma_h */
/*
* GSXB audio definitions
*
* Patrice Mandin
*/
#ifndef _SDL_mintgsxb_h
#define _SDL_mintgsxb_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_mintgsxb_h */
/*
* Audio interrupt routines
*
* Patrice Mandin
*/
.text
.globl _SDL_MintAudio_Callback
.globl _SDL_MintAudio_IntDma
.globl _SDL_MintAudio_IntXbios
.globl _SDL_MintAudio_IntGsxb
.globl _SDL_MintAudio_mutex
.globl _SDL_MintAudio_audiobuf
.globl _SDL_MintAudio_numbuf
.globl _SDL_MintAudio_audiosize
/*
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
*/
/*--- DMA 8 bits interrupt vector ---*/
.text
_SDL_MintAudio_IntDma:
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes intdma_end
notw _SDL_MintAudio_mutex
/* Reenable interrupts */
movew #0x2300,sr
/* Swap buffers */
moveml d0-d1/a0-a1,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,d1
eorl #1,d0
beqs intdma_buffer0
movel _SDL_MintAudio_audiobuf+4,d1
intdma_buffer0:
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
intdma_end:
bclr #5,0xfffffa0f:w
rte
/*--- Xbios interrupt vector ---*/
.text
_SDL_MintAudio_IntXbios:
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes intxbios_end
notw _SDL_MintAudio_mutex
/* Reenable interrupts */
movew #0x2300,sr
/* Swap buffers */
moveml d0-d2/a0-a2,sp@-
movel _SDL_MintAudio_numbuf,d0
movel _SDL_MintAudio_audiobuf,a0
eorl #1,d0
beqs intxbios_buffer0
movel _SDL_MintAudio_audiobuf+4,a0
intxbios_buffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
moveml a0,sp@-
jsr _SDL_MintAudio_Callback
moveml 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
intxbios_end:
bclr #5,0xfffffa0f:w
rte
/*--- GSXB interrupt vector ---*/
.text
_SDL_MintAudio_IntGsxb:
/* Check if we are not already running */
tstw _SDL_MintAudio_mutex
bnes intgsxb_end
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 intgsxb_buffer0
movel _SDL_MintAudio_audiobuf+4,a0
intgsxb_buffer0:
movel d0,_SDL_MintAudio_numbuf
/* Callback */
moveml a0,sp@-
jsr _SDL_MintAudio_Callback
moveml 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
intgsxb_end:
rts
/*--- Common variables ---*/
.data
.even
.comm _SDL_MintAudio_mutex,4
.even
.comm _SDL_MintAudio_audiobuf,8
.even
.comm _SDL_MintAudio_numbuf,4
.even
.comm _SDL_MintAudio_audiosize,4
/*
* Audio interrupt
*
* Patrice Mandin
*/
#ifndef _SDL_MINTAUDIOINTERRUPT_S_H_
#define _SDL_MINTAUDIOINTERRUPT_S_H_
#include "SDL_types.h"
/* Variables */
extern void *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */
extern long SDL_MintAudio_audiosize; /* Length of audio buffer */
extern long SDL_MintAudio_numbuf; /* Buffer to play */
extern long SDL_MintAudio_mutex;
/* Functions */
void SDL_MintAudio_IntDma(void);
void SDL_MintAudio_IntXbios(void);
void SDL_MintAudio_IntGsxb(void);
#endif /* _SDL_MINTAUDIOINTERRUPT_S_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment