mirror of
https://github.com/joel16/SDL2.git
synced 2024-12-15 07:20:03 +00:00
Atari MiNT: added more audio drivers
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40645
This commit is contained in:
parent
ae6427430d
commit
e1695a4b13
43
README.MiNT
43
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 <pmandin@caramail.com>
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1,628 +1,93 @@
|
||||
/*
|
||||
* MiNT audio driver
|
||||
*
|
||||
* Patrice Mandin
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Audio interrupt variables and callback function
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_types.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
#include "SDL_mintaudiodma.h"
|
||||
#include "SDL_mintaudiogsxb.h"
|
||||
#include "SDL_mintaudiointerrupt_s.h"
|
||||
#include "SDL_mintaudio_stfa.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
/* The audio device */
|
||||
|
||||
/*--- Defines ---*/
|
||||
SDL_AudioDevice *SDL_MintAudio_device;
|
||||
Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */
|
||||
long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */
|
||||
long SDL_MintAudio_numbuf; /* Buffer to play */
|
||||
long SDL_MintAudio_mutex;
|
||||
cookie_stfa_t *SDL_MintAudio_stfa;
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint"
|
||||
/* The callback function, called by each driver whenever needed */
|
||||
|
||||
/* Master clocks for replay frequencies */
|
||||
#define MASTERCLOCK_STE 8010666 /* Not sure of this one */
|
||||
#define MASTERCLOCK_TT 16107953 /* Not sure of this one */
|
||||
#define MASTERCLOCK_FALCON1 25175000
|
||||
#define MASTERCLOCK_FALCON2 32000000 /* Only usable for DSP56K */
|
||||
#define MASTERCLOCK_FALCONEXT -1 /* Clock on DSP56K port, unknown */
|
||||
#define MASTERCLOCK_MILAN1 22579200 /* Standard clock for 44.1 Khz */
|
||||
#define MASTERCLOCK_MILAN2 24576000 /* Standard clock for 48 Khz */
|
||||
|
||||
/* Master clock predivisors */
|
||||
#define MASTERPREDIV_STE 160
|
||||
#define MASTERPREDIV_TT 320
|
||||
#define MASTERPREDIV_FALCON 256
|
||||
#define MASTERPREDIV_MILAN 256
|
||||
|
||||
/* Values>>16 in _MCH cookie */
|
||||
enum {
|
||||
MCH_ST=0,
|
||||
MCH_STE,
|
||||
MCH_TT,
|
||||
MCH_F30
|
||||
};
|
||||
|
||||
/* MFP 68901 interrupt sources */
|
||||
enum {
|
||||
MFP_PARALLEL=0,
|
||||
MFP_DCD,
|
||||
MFP_CTS,
|
||||
MFP_BITBLT,
|
||||
MFP_TIMERD,
|
||||
MFP_BAUDRATE=MFP_TIMERD,
|
||||
MFP_TIMERC,
|
||||
MFP_200HZ=MFP_TIMERC,
|
||||
MFP_ACIA,
|
||||
MFP_DISK,
|
||||
MFP_TIMERB,
|
||||
MFP_HBLANK=MFP_TIMERB,
|
||||
MFP_TERR,
|
||||
MFP_TBE,
|
||||
MFP_RERR,
|
||||
MFP_RBF,
|
||||
MFP_TIMERA,
|
||||
MFP_DMASOUND=MFP_TIMERA,
|
||||
MFP_RING,
|
||||
MFP_MONODETECT
|
||||
};
|
||||
|
||||
/* Xbtimer() timers */
|
||||
enum {
|
||||
XB_TIMERA=0,
|
||||
XB_TIMERB,
|
||||
XB_TIMERC,
|
||||
XB_TIMERD
|
||||
};
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd, cookie_mch, cookie_gsxb;
|
||||
static Uint16 hardfreq[16];
|
||||
static Uint16 numfreq;
|
||||
static SDL_AudioDevice *SDL_MintAudio_device;
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Cookie _MCH present ? if not, assume ST machine */
|
||||
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
|
||||
cookie_mch = MCH_ST << 16;
|
||||
}
|
||||
|
||||
/* Cookie GSXB present ? */
|
||||
cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
|
||||
|
||||
/* Check if we have xbios functions (Falcon, clones) */
|
||||
if ((cookie_snd & SND_16BIT)!=0) {
|
||||
/* Check if audio is lockable */
|
||||
if (Locksnd()==1) {
|
||||
Unlocksnd();
|
||||
} else {
|
||||
/* Already in use */
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Check if we have 8 bits DMA audio (STE, TT) */
|
||||
if ((cookie_snd & SND_8BIT)!=0) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
}
|
||||
if ( this == NULL ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Stop replay */
|
||||
if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Buffoper(0);
|
||||
} else if ((cookie_snd & SND_8BIT)!=0) {
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=0;
|
||||
Super(oldpile);
|
||||
}
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Restart replay */
|
||||
if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
} else if ((cookie_snd & SND_8BIT)!=0) {
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=3;
|
||||
Super(oldpile);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called from the interrupt routine */
|
||||
void SDL_MintAudio_Callback(void)
|
||||
{
|
||||
SDL_AudioDevice *audio;
|
||||
Uint8 *buffer;
|
||||
|
||||
audio = SDL_MintAudio_device;
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
memset(buffer, SDL_MintAudio_device->spec.silence, SDL_MintAudio_device->spec.size);
|
||||
|
||||
if ( ! audio->paused ) {
|
||||
if ( audio->convert.needed ) {
|
||||
audio->spec.callback(audio->spec.userdata,
|
||||
(Uint8 *)audio->convert.buf,audio->convert.len);
|
||||
SDL_ConvertAudio(&audio->convert);
|
||||
memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
|
||||
if ( ! SDL_MintAudio_device->paused ) {
|
||||
if ( SDL_MintAudio_device->convert.needed ) {
|
||||
SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata,
|
||||
(Uint8 *)SDL_MintAudio_device->convert.buf,SDL_MintAudio_device->convert.len);
|
||||
SDL_ConvertAudio(&SDL_MintAudio_device->convert);
|
||||
memcpy(buffer, SDL_MintAudio_device->convert.buf, SDL_MintAudio_device->convert.len_cvt);
|
||||
} else {
|
||||
audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size);
|
||||
SDL_MintAudio_device->spec.callback(SDL_MintAudio_device->spec.userdata, buffer, SDL_MintAudio_device->spec.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Mint_StopAudio_Dma8(void)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=0;
|
||||
Super(oldpile);
|
||||
|
||||
Jdisint(MFP_DMASOUND);
|
||||
}
|
||||
|
||||
static void Mint_StopAudio_Xbios(void)
|
||||
{
|
||||
Buffoper(0);
|
||||
Jdisint(MFP_DMASOUND);
|
||||
}
|
||||
|
||||
static void Mint_StopAudio_Gsxb(void)
|
||||
{
|
||||
Buffoper(0);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
|
||||
Mint_StopAudio_Gsxb();
|
||||
} else if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Mint_StopAudio_Xbios();
|
||||
} else if ((cookie_snd & SND_8BIT)!=0) {
|
||||
Mint_StopAudio_Dma8();
|
||||
}
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
|
||||
/* Unlock sound system */
|
||||
if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Unlocksnd();
|
||||
}
|
||||
}
|
||||
|
||||
static void Mint_CheckAudio_Dma8(SDL_AudioSpec *spec)
|
||||
/* Simple function to search for the nearest frequency */
|
||||
int SDL_MintAudio_SearchFrequency(_THIS, int falcon_codec, int desired_freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
spec->format = AUDIO_S8;
|
||||
|
||||
switch(cookie_mch>>16) {
|
||||
case MCH_STE:
|
||||
/* STE replay frequencies */
|
||||
for (i=0;i<4;i++) {
|
||||
hardfreq[i]=MASTERCLOCK_STE/(MASTERPREDIV_STE*(i+1));
|
||||
/* Only 1 freq ? */
|
||||
if (MINTAUDIO_nfreq==1) {
|
||||
return(MINTAUDIO_sfreq);
|
||||
}
|
||||
|
||||
if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
|
||||
numfreq=3; /* 50066 */
|
||||
} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
|
||||
numfreq=2; /* 25033 */
|
||||
} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
|
||||
numfreq=1; /* 12517 */
|
||||
} else {
|
||||
numfreq=0; /* 6258 */
|
||||
}
|
||||
|
||||
spec->freq=hardfreq[numfreq];
|
||||
break;
|
||||
case MCH_TT:
|
||||
/* TT replay frequencies */
|
||||
for (i=0;i<4;i++) {
|
||||
hardfreq[i]=MASTERCLOCK_TT/(MASTERPREDIV_TT*(i+1));
|
||||
}
|
||||
|
||||
if (spec->freq>=(hardfreq[0]+hardfreq[1])>>1) {
|
||||
numfreq=3; /* 50337 */
|
||||
} else if (spec->freq>=(hardfreq[1]+hardfreq[2])>>1) {
|
||||
numfreq=2; /* 25169 */
|
||||
} else if (spec->freq>=(hardfreq[2]+hardfreq[3])>>1) {
|
||||
numfreq=1; /* 12584 */
|
||||
} else {
|
||||
numfreq=0; /* 6292 */
|
||||
}
|
||||
spec->freq=hardfreq[numfreq];
|
||||
break;
|
||||
/* Check the array */
|
||||
for (i=MINTAUDIO_sfreq; i<MINTAUDIO_nfreq-1; i++) {
|
||||
/* Remove unusable falcon codec frequencies */
|
||||
if (falcon_codec) {
|
||||
if ((i==6) || (i==8) || (i==10)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mint_CheckAudio_Xbios(SDL_AudioSpec *spec)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check conversions needed */
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
spec->format = AUDIO_S8;
|
||||
break;
|
||||
case 16:
|
||||
spec->format = AUDIO_S16MSB;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check hardware channels */
|
||||
if ((spec->channels==1) && ((spec->format & 0xff)==16)) {
|
||||
spec->channels=2;
|
||||
}
|
||||
|
||||
/* Falcon replay frequencies */
|
||||
for (i=0;i<16;i++) {
|
||||
hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
|
||||
}
|
||||
|
||||
/* The Falcon CODEC only support some frequencies */
|
||||
if (spec->freq>=(hardfreq[CLK50K]+hardfreq[CLK33K])>>1) {
|
||||
numfreq=CLK50K; /* 49170 */
|
||||
} else if (spec->freq>=(hardfreq[CLK33K]+hardfreq[CLK25K])>>1) {
|
||||
numfreq=CLK33K; /* 32780 */
|
||||
} else if (spec->freq>=(hardfreq[CLK25K]+hardfreq[CLK20K])>>1) {
|
||||
numfreq=CLK25K; /* 24585 */
|
||||
} else if (spec->freq>=(hardfreq[CLK20K]+hardfreq[CLK16K])>>1) {
|
||||
numfreq=CLK20K; /* 19668 */
|
||||
} else if (spec->freq>=(hardfreq[CLK16K]+hardfreq[CLK12K])>>1) {
|
||||
numfreq=CLK16K; /* 16390 */
|
||||
} else if (spec->freq>=(hardfreq[CLK12K]+hardfreq[CLK10K])>>1) {
|
||||
numfreq=CLK12K; /* 12292 */
|
||||
} else if (spec->freq>=(hardfreq[CLK10K]+hardfreq[CLK8K])>>1) {
|
||||
numfreq=CLK10K; /* 9834 */
|
||||
} else {
|
||||
numfreq=CLK8K; /* 8195 */
|
||||
}
|
||||
|
||||
spec->freq=hardfreq[numfreq];
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio_Gsxb(SDL_AudioSpec *spec)
|
||||
{
|
||||
long snd_format;
|
||||
int i, resolution, format_signed, format_bigendian;
|
||||
|
||||
resolution = spec->format & 0x00ff;
|
||||
format_signed = ((spec->format & 0x8000)!=0);
|
||||
format_bigendian = ((spec->format & 0x1000)!=0);
|
||||
|
||||
/* Check formats available */
|
||||
snd_format = Sndstatus(SND_QUERYFORMATS);
|
||||
switch (resolution) {
|
||||
case 8:
|
||||
if ((snd_format & SND_FORMAT8)==0) {
|
||||
SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
|
||||
return -1;
|
||||
}
|
||||
snd_format = Sndstatus(SND_QUERY8BIT);
|
||||
break;
|
||||
case 16:
|
||||
if ((snd_format & SND_FORMAT16)==0) {
|
||||
SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
|
||||
return -1;
|
||||
}
|
||||
snd_format = Sndstatus(SND_QUERY16BIT);
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check signed/unsigned format */
|
||||
if (format_signed) {
|
||||
if (snd_format & SND_FORMATSIGNED) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATUNSIGNED) {
|
||||
/* Give unsigned format */
|
||||
spec->format = spec->format & (~0x8000);
|
||||
}
|
||||
} else {
|
||||
if (snd_format & SND_FORMATUNSIGNED) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATSIGNED) {
|
||||
/* Give signed format */
|
||||
spec->format |= 0x8000;
|
||||
if (desired_freq >= ((MINTAUDIO_hardfreq[i]+MINTAUDIO_hardfreq[i+1])>>1)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (format_bigendian) {
|
||||
if (snd_format & SND_FORMATBIGENDIAN) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
|
||||
/* Give little endian format */
|
||||
spec->format = spec->format & (~0x1000);
|
||||
}
|
||||
} else {
|
||||
if (snd_format & SND_FORMATBIGENDIAN) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
|
||||
/* Give big endian format */
|
||||
spec->format |= 0x1000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only xbios functions available = clone with PC board */
|
||||
for (i=0;i<8;i++) {
|
||||
hardfreq[i]=MASTERCLOCK_MILAN1/(MASTERPREDIV_MILAN*(i+1));
|
||||
}
|
||||
|
||||
if (spec->freq>=(hardfreq[CLK_44K]+hardfreq[CLK_22K])>>1) {
|
||||
numfreq = CLK_44K; /* 44100 */
|
||||
} else if (spec->freq>=(hardfreq[CLK_22K]+hardfreq[CLK_11K])>>1) {
|
||||
numfreq = CLK_22K; /* 22050 */
|
||||
} else {
|
||||
numfreq = CLK_11K; /* 11025 */
|
||||
}
|
||||
|
||||
spec->freq=hardfreq[numfreq];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio_Dma8(SDL_AudioSpec *spec)
|
||||
{
|
||||
void *oldpile;
|
||||
unsigned long buffer;
|
||||
unsigned char mode;
|
||||
|
||||
oldpile=(void *)Super(0);
|
||||
|
||||
/* Stop currently playing sound */
|
||||
DMAAUDIO_IO.control=0;
|
||||
|
||||
/* Set buffer */
|
||||
buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
DMAAUDIO_IO.start_high = (buffer>>16) & 255;
|
||||
DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
|
||||
DMAAUDIO_IO.start_low = buffer & 255;
|
||||
|
||||
buffer += SDL_MintAudio_audiosize;
|
||||
DMAAUDIO_IO.end_high = (buffer>>16) & 255;
|
||||
DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
|
||||
DMAAUDIO_IO.end_low = buffer & 255;
|
||||
|
||||
mode = numfreq;
|
||||
if (spec->channels==1) {
|
||||
mode |= 1<<7;
|
||||
}
|
||||
DMAAUDIO_IO.mode = mode;
|
||||
|
||||
/* Set interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntDma);
|
||||
Jenabint(MFP_DMASOUND);
|
||||
|
||||
/* Go */
|
||||
DMAAUDIO_IO.control = 3; /* playback + repeat */
|
||||
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static void Mint_InitAudio_Xbios(SDL_AudioSpec *spec)
|
||||
{
|
||||
int channels_mode;
|
||||
void *buffer;
|
||||
|
||||
/* Stop currently playing sound */
|
||||
Buffoper(0);
|
||||
|
||||
Settracks(0,0);
|
||||
Setmontracks(0);
|
||||
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO8;
|
||||
} else {
|
||||
channels_mode=MONO8;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
default:
|
||||
channels_mode=STEREO16;
|
||||
break;
|
||||
}
|
||||
Setmode(channels_mode);
|
||||
|
||||
Devconnect(DMAPLAY, DAC, CLK25M, numfreq, 1);
|
||||
|
||||
/* Set buffer */
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
|
||||
|
||||
/* Install interrupt */
|
||||
Setinterrupt(SI_TIMERA, SI_PLAY);
|
||||
|
||||
Jdisint(MFP_DMASOUND);
|
||||
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_IntXbios);
|
||||
Jenabint(MFP_DMASOUND);
|
||||
|
||||
/* Go */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
}
|
||||
|
||||
static void Mint_InitAudio_Gsxb(SDL_AudioSpec *spec)
|
||||
{
|
||||
int channels_mode;
|
||||
void *buffer;
|
||||
|
||||
/* Stop currently playing sound */
|
||||
Buffoper(0);
|
||||
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO8;
|
||||
} else {
|
||||
channels_mode=MONO8;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO16;
|
||||
} else {
|
||||
channels_mode=MONO16;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
channels_mode=STEREO16;
|
||||
break;
|
||||
}
|
||||
Setmode(channels_mode);
|
||||
|
||||
Devconnect(0, 0, CLKEXT, numfreq, 1);
|
||||
|
||||
/* Set buffer */
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
Setbuffer(0, buffer, buffer+SDL_MintAudio_audiosize);
|
||||
|
||||
/* Install interrupt */
|
||||
NSetinterrupt(2, SI_PLAY, SDL_MintAudio_IntGsxb);
|
||||
|
||||
/* Go */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
/* Lock sound system */
|
||||
if ((cookie_snd & SND_16BIT)!=0) {
|
||||
if (Locksnd()!=1) {
|
||||
SDL_SetError("Mint_OpenAudio: Audio system already in use");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
|
||||
if (Mint_CheckAudio_Gsxb(spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
} else if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Mint_CheckAudio_Xbios(spec);
|
||||
} else if ((cookie_snd & SND_8BIT)!=0) {
|
||||
Mint_CheckAudio_Dma8(spec);
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(SDL_MintAudio_audiosize *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], 0, SDL_MintAudio_audiosize * 2);
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Setup audio hardware */
|
||||
if (cookie_gsxb && ((cookie_snd & (SND_GSXB|SND_16BIT))==(SND_GSXB|SND_16BIT)) ) {
|
||||
Mint_InitAudio_Gsxb(spec);
|
||||
} else if ((cookie_snd & SND_16BIT)!=0) {
|
||||
Mint_InitAudio_Xbios(spec);
|
||||
} else if ((cookie_snd & SND_8BIT)!=0) {
|
||||
Mint_InitAudio_Dma8(spec);
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* Not in the array, give the latest */
|
||||
return MINTAUDIO_nfreq-1;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
354
src/audio/mint/SDL_mintaudio_dma8.c
Normal file
354
src/audio/mint/SDL_mintaudio_dma8.c
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MiNT audio driver
|
||||
using DMA 8bits (hardware access)
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
#include "SDL_mintaudio_dma8.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint_dma8"
|
||||
|
||||
/* Debug print info */
|
||||
#define DEBUG_NAME "audio:dma8: "
|
||||
#if 0
|
||||
#define DEBUG_PRINT(what) \
|
||||
{ \
|
||||
printf what; \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_PRINT(what)
|
||||
#endif
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd, cookie_mch;
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/* To check/init hardware audio */
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cookie _MCH present ? if not, assume ST machine */
|
||||
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
|
||||
cookie_mch = MCH_ST;
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Check if we have 8 bits audio */
|
||||
if ((cookie_snd & SND_8BIT)==0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ((cookie_mch>>16)>MCH_F30) {
|
||||
DEBUG_PRINT((DEBUG_NAME "unknown 8 bits audio chip\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if audio is lockable */
|
||||
if ((cookie_mch>>16) == MCH_F30) {
|
||||
if (Locksnd()!=1) {
|
||||
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Unlocksnd();
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Stop replay */
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=0;
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Restart replay */
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=3;
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Stop replay */
|
||||
oldpile=(void *)Super(0);
|
||||
DMAAUDIO_IO.control=0;
|
||||
Super(oldpile);
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
|
||||
|
||||
/* Disable interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
|
||||
|
||||
/* Wait if currently playing sound */
|
||||
while (SDL_MintAudio_mutex != 0) {
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int i, masterprediv;
|
||||
unsigned long masterclock;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
/* Check formats available */
|
||||
spec->format = AUDIO_S8;
|
||||
|
||||
/* Calculate and select the closest frequency */
|
||||
MINTAUDIO_nfreq=4;
|
||||
MINTAUDIO_sfreq=0;
|
||||
masterclock=MASTERCLOCK_STE;
|
||||
masterprediv=MASTERPREDIV_STE;
|
||||
switch(cookie_mch>>16) {
|
||||
/*
|
||||
case MCH_STE:
|
||||
masterclock=MASTERCLOCK_STE;
|
||||
masterprediv=MASTERPREDIV_STE;
|
||||
break;
|
||||
*/
|
||||
case MCH_TT:
|
||||
masterclock=MASTERCLOCK_TT;
|
||||
masterprediv=MASTERPREDIV_TT;
|
||||
break;
|
||||
case MCH_F30:
|
||||
masterclock=MASTERCLOCK_FALCON1;
|
||||
masterprediv=MASTERPREDIV_FALCON<<1;
|
||||
MINTAUDIO_nfreq=3;
|
||||
MINTAUDIO_sfreq=1;
|
||||
break;
|
||||
}
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
|
||||
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
|
||||
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
void *oldpile;
|
||||
unsigned long buffer;
|
||||
unsigned char mode;
|
||||
|
||||
/* Set replay tracks */
|
||||
if (cookie_snd & SND_16BIT) {
|
||||
Settracks(0,0);
|
||||
Setmontracks(0);
|
||||
}
|
||||
|
||||
oldpile=(void *)Super(0);
|
||||
|
||||
/* Stop currently playing sound */
|
||||
DMAAUDIO_IO.control=0;
|
||||
|
||||
/* Set buffer */
|
||||
buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
DMAAUDIO_IO.start_high = (buffer>>16) & 255;
|
||||
DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
|
||||
DMAAUDIO_IO.start_low = buffer & 255;
|
||||
|
||||
buffer += SDL_MintAudio_audiosize;
|
||||
DMAAUDIO_IO.end_high = (buffer>>16) & 255;
|
||||
DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
|
||||
DMAAUDIO_IO.end_low = buffer & 255;
|
||||
|
||||
mode = 3-MINTAUDIO_numfreq;
|
||||
if (spec->channels==1) {
|
||||
mode |= 1<<7;
|
||||
}
|
||||
DMAAUDIO_IO.mode = mode;
|
||||
|
||||
/* Set interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
|
||||
Jenabint(MFP_DMASOUND);
|
||||
|
||||
/* Go */
|
||||
DMAAUDIO_IO.control = 3; /* playback + repeat */
|
||||
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (Mint_CheckAudio(this, spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
|
||||
|
||||
/* Setup audio hardware */
|
||||
Mint_InitAudio(this, spec);
|
||||
|
||||
return(1); /* We don't use threaded audio */
|
||||
}
|
65
src/audio/mint/SDL_mintaudio_dma8.h
Normal file
65
src/audio/mint/SDL_mintaudio_dma8.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
DMA 8bits audio definitions
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#ifndef _SDL_mintaudio_dma8_h
|
||||
#define _SDL_mintaudio_dma8_h
|
||||
|
||||
#define DMAAUDIO_IO_BASE (0xffff8900)
|
||||
struct DMAAUDIO_IO_S {
|
||||
unsigned char int_ctrl;
|
||||
unsigned char control;
|
||||
|
||||
unsigned char dummy1;
|
||||
unsigned char start_high;
|
||||
unsigned char dummy2;
|
||||
unsigned char start_mid;
|
||||
unsigned char dummy3;
|
||||
unsigned char start_low;
|
||||
|
||||
unsigned char dummy4;
|
||||
unsigned char cur_high;
|
||||
unsigned char dummy5;
|
||||
unsigned char cur_mid;
|
||||
unsigned char dummy6;
|
||||
unsigned char cur_low;
|
||||
|
||||
unsigned char dummy7;
|
||||
unsigned char end_high;
|
||||
unsigned char dummy8;
|
||||
unsigned char end_mid;
|
||||
unsigned char dummy9;
|
||||
unsigned char end_low;
|
||||
|
||||
unsigned char dummy10[12];
|
||||
|
||||
unsigned char track_select; /* CODEC only */
|
||||
unsigned char mode;
|
||||
};
|
||||
#define DMAAUDIO_IO ((*(volatile struct DMAAUDIO_IO_S *)DMAAUDIO_IO_BASE))
|
||||
|
||||
#endif /* _SDL_mintaudio_dma8_h */
|
395
src/audio/mint/SDL_mintaudio_gsxb.c
Normal file
395
src/audio/mint/SDL_mintaudio_gsxb.c
Normal file
@ -0,0 +1,395 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MiNT audio driver
|
||||
using XBIOS functions (GSXB compatible driver)
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
#include "SDL_mintaudio_gsxb.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint_gsxb"
|
||||
|
||||
/* Debug print info */
|
||||
#define DEBUG_NAME "audio:gsxb: "
|
||||
#if 0
|
||||
#define DEBUG_PRINT(what) \
|
||||
{ \
|
||||
printf what; \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_PRINT(what)
|
||||
#endif
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd, cookie_gsxb;
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/* To check/init hardware audio */
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Check if we have 16 bits audio */
|
||||
if ((cookie_snd & SND_16BIT)==0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie GSXB present ? */
|
||||
cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
|
||||
|
||||
/* Is it GSXB ? */
|
||||
if (((cookie_snd & SND_GSXB)==0) || (cookie_gsxb==0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no GSXB audio\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check if audio is lockable */
|
||||
if (Locksnd()!=1) {
|
||||
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Unlocksnd();
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n"));
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_GSXB_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
/* Restart replay */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
|
||||
|
||||
/* Uninstall interrupt */
|
||||
if (NSetinterrupt(2, SI_NONE, SDL_MintAudio_EmptyGsxbInterrupt)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
|
||||
|
||||
/* Wait if currently playing sound */
|
||||
while (SDL_MintAudio_mutex != 0) {
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
|
||||
|
||||
/* Unlock sound system */
|
||||
Unlocksnd();
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
long snd_format;
|
||||
int i, resolution, format_signed, format_bigendian;
|
||||
|
||||
resolution = spec->format & 0x00ff;
|
||||
format_signed = ((spec->format & 0x8000)!=0);
|
||||
format_bigendian = ((spec->format & 0x1000)!=0);
|
||||
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",resolution));
|
||||
DEBUG_PRINT(("signed=%d, ", format_signed));
|
||||
DEBUG_PRINT(("big endian=%d, ", format_bigendian));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
/* Check formats available */
|
||||
snd_format = Sndstatus(SND_QUERYFORMATS);
|
||||
switch (resolution) {
|
||||
case 8:
|
||||
if ((snd_format & SND_FORMAT8)==0) {
|
||||
SDL_SetError("Mint_CheckAudio: 8 bits samples not supported");
|
||||
return -1;
|
||||
}
|
||||
snd_format = Sndstatus(SND_QUERY8BIT);
|
||||
break;
|
||||
case 16:
|
||||
if ((snd_format & SND_FORMAT16)==0) {
|
||||
SDL_SetError("Mint_CheckAudio: 16 bits samples not supported");
|
||||
return -1;
|
||||
}
|
||||
snd_format = Sndstatus(SND_QUERY16BIT);
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Mint_CheckAudio: Unsupported sample resolution");
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check signed/unsigned format */
|
||||
if (format_signed) {
|
||||
if (snd_format & SND_FORMATSIGNED) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATUNSIGNED) {
|
||||
/* Give unsigned format */
|
||||
spec->format = spec->format & (~0x8000);
|
||||
}
|
||||
} else {
|
||||
if (snd_format & SND_FORMATUNSIGNED) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATSIGNED) {
|
||||
/* Give signed format */
|
||||
spec->format |= 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
if (format_bigendian) {
|
||||
if (snd_format & SND_FORMATBIGENDIAN) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
|
||||
/* Give little endian format */
|
||||
spec->format = spec->format & (~0x1000);
|
||||
}
|
||||
} else {
|
||||
if (snd_format & SND_FORMATBIGENDIAN) {
|
||||
/* Ok */
|
||||
} else if (snd_format & SND_FORMATLITTLEENDIAN) {
|
||||
/* Give big endian format */
|
||||
spec->format |= 0x1000;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate and select the closest frequency */
|
||||
MINTAUDIO_sfreq=1;
|
||||
MINTAUDIO_nfreq=12;
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(i+1));
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
|
||||
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
|
||||
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int channels_mode;
|
||||
void *buffer;
|
||||
|
||||
/* Stop currently playing sound */
|
||||
Buffoper(0);
|
||||
|
||||
/* Set replay tracks */
|
||||
Settracks(0,0);
|
||||
Setmontracks(0);
|
||||
|
||||
/* Select replay format */
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO8;
|
||||
} else {
|
||||
channels_mode=MONO8;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO16;
|
||||
} else {
|
||||
channels_mode=MONO16;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
channels_mode=STEREO16;
|
||||
break;
|
||||
}
|
||||
if (Setmode(channels_mode)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
|
||||
}
|
||||
|
||||
Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
|
||||
|
||||
/* Set buffer */
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
|
||||
}
|
||||
|
||||
/* Install interrupt */
|
||||
if (NSetinterrupt(2, SI_PLAY, SDL_MintAudio_GsxbInterrupt)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n"));
|
||||
}
|
||||
|
||||
/* Go */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
/* Lock sound system */
|
||||
if (Locksnd()!=1) {
|
||||
SDL_SetError("Mint_OpenAudio: Audio system already in use");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (Mint_CheckAudio(this, spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
|
||||
|
||||
/* Setup audio hardware */
|
||||
Mint_InitAudio(this, spec);
|
||||
|
||||
return(1); /* We don't use threaded audio */
|
||||
}
|
85
src/audio/mint/SDL_mintaudio_gsxb.h
Normal file
85
src/audio/mint/SDL_mintaudio_gsxb.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* GSXB audio definitions
|
||||
*
|
||||
* Patrice Mandin
|
||||
*/
|
||||
|
||||
#ifndef _SDL_mintaudio_gsxb_h
|
||||
#define _SDL_mintaudio_gsxb_h
|
||||
|
||||
#include <mint/falcon.h> /* for trap_14_xxx macros */
|
||||
|
||||
/* GSXB Cookie */
|
||||
|
||||
#define C_GSXB 0x47535842L
|
||||
|
||||
/* Bit 5 in cookie _SND */
|
||||
|
||||
#define SND_GSXB (1<<5)
|
||||
|
||||
/* NSoundcmd modes */
|
||||
|
||||
#define SETRATE 7 /* Set sample rate */
|
||||
#define SET8BITFORMAT 8 /* 8 bits format */
|
||||
#define SET16BITFORMAT 9 /* 16 bits format */
|
||||
#define SET24BITFORMAT 10 /* 24 bits format */
|
||||
#define SET32BITFORMAT 11 /* 32 bits format */
|
||||
#define LTATTEN_MASTER 12 /* Attenuation */
|
||||
#define RTATTEN_MASTER 13
|
||||
#define LTATTEN_MICIN 14
|
||||
#define RTATTEN_MICIN 15
|
||||
#define LTATTEN_FMGEN 16
|
||||
#define RTATTEN_FMGEN 17
|
||||
#define LTATTEN_LINEIN 18
|
||||
#define RTATTEN_LINEIN 19
|
||||
#define LTATTEN_CDIN 20
|
||||
#define RTATTEN_CDIN 21
|
||||
#define LTATTEN_VIDIN 22
|
||||
#define RTATTEN_VIDIN 23
|
||||
#define LTATTEN_AUXIN 24
|
||||
#define RTATTEN_AUXIN 25
|
||||
|
||||
/* Setmode modes */
|
||||
|
||||
#define MONO16 3
|
||||
#define STEREO24 4
|
||||
#define STEREO32 5
|
||||
#define MONO24 6
|
||||
#define MONO32 7
|
||||
|
||||
/* Sndstatus modes */
|
||||
|
||||
#define SND_QUERYFORMATS 2
|
||||
#define SND_QUERYMIXERS 3
|
||||
#define SND_QUERYSOURCES 4
|
||||
#define SND_QUERYDUPLEX 5
|
||||
#define SND_QUERY8BIT 8
|
||||
#define SND_QUERY16BIT 9
|
||||
#define SND_QUERY24BIT 10
|
||||
#define SND_QUERY32BIT 11
|
||||
|
||||
#define SND_FORMAT8 (1<<0)
|
||||
#define SND_FORMAT16 (1<<1)
|
||||
#define SND_FORMAT24 (1<<2)
|
||||
#define SND_FORMAT32 (1<<3)
|
||||
|
||||
#define SND_FORMATSIGNED (1<<0)
|
||||
#define SND_FORMATUNSIGNED (1<<1)
|
||||
#define SND_FORMATBIGENDIAN (1<<2)
|
||||
#define SND_FORMATLITTLEENDIAN (1<<3)
|
||||
|
||||
/* Devconnect prescalers */
|
||||
|
||||
#define CLK_44K 1
|
||||
#define CLK_22K 3
|
||||
#define CLK_11K 7
|
||||
|
||||
/* Extra xbios functions */
|
||||
|
||||
#define NSoundcmd(mode,data,data2) \
|
||||
(long)trap_14_wwl((short)130,(short)(mode),(short)(data),(long)(data2))
|
||||
#define NSetinterrupt(src_inter,cause,inth_addr) \
|
||||
(long)trap_14_wwwl((short)135,(short)(src_inter),(short)(cause), \
|
||||
(long)(inth_addr))
|
||||
|
||||
#endif /* _SDL_mintaudio_gsxb_h */
|
242
src/audio/mint/SDL_mintaudio_it.S
Normal file
242
src/audio/mint/SDL_mintaudio_it.S
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Audio interrupts
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
.globl _SDL_MintAudio_Callback
|
||||
|
||||
.globl _SDL_MintAudio_GsxbInterrupt
|
||||
.globl _SDL_MintAudio_EmptyGsxbInterrupt
|
||||
.globl _SDL_MintAudio_XbiosInterrupt
|
||||
.globl _SDL_MintAudio_Dma8Interrupt
|
||||
.globl _SDL_MintAudio_StfaInterrupt
|
||||
|
||||
.globl _SDL_MintAudio_mutex
|
||||
.globl _SDL_MintAudio_audiobuf
|
||||
.globl _SDL_MintAudio_numbuf
|
||||
.globl _SDL_MintAudio_audiosize
|
||||
|
||||
.globl _SDL_MintAudio_stfa
|
||||
|
||||
/*
|
||||
How it works:
|
||||
- Audio is playing buffer #0 (resp. #1)
|
||||
- We must calculate a sample in buffer #1 (resp. #0)
|
||||
so we first call the callback to do it
|
||||
- Then we swap the buffers
|
||||
*/
|
||||
|
||||
/*--- GSXB interrupt vector ---*/
|
||||
|
||||
.text
|
||||
_SDL_MintAudio_GsxbInterrupt:
|
||||
|
||||
/* Check if we are not already running */
|
||||
tstw _SDL_MintAudio_mutex
|
||||
bnes _SDL_MintAudio_EmptyGsxbInterrupt
|
||||
notw _SDL_MintAudio_mutex
|
||||
|
||||
/* Swap buffers */
|
||||
moveml d0-d2/a0-a2,sp@-
|
||||
|
||||
movel _SDL_MintAudio_numbuf,d0
|
||||
movel _SDL_MintAudio_audiobuf,a0
|
||||
eorl #1,d0
|
||||
beqs SDL_MintAudio_GsxbBuffer0
|
||||
movel _SDL_MintAudio_audiobuf+4,a0
|
||||
SDL_MintAudio_GsxbBuffer0:
|
||||
movel d0,_SDL_MintAudio_numbuf
|
||||
|
||||
/* Callback */
|
||||
movel a0,sp@-
|
||||
jsr _SDL_MintAudio_Callback
|
||||
movel sp@+,a0
|
||||
|
||||
/* Setbuffer xbios function */
|
||||
movel _SDL_MintAudio_audiosize,d1
|
||||
lea a0@(0,d1:l),a1
|
||||
|
||||
movel a1,sp@-
|
||||
movel a0,sp@-
|
||||
clrw sp@-
|
||||
movew #131,sp@-
|
||||
trap #14
|
||||
lea sp@(12),sp
|
||||
|
||||
moveml sp@+,d0-d2/a0-a2
|
||||
|
||||
clrw _SDL_MintAudio_mutex
|
||||
_SDL_MintAudio_EmptyGsxbInterrupt:
|
||||
rts
|
||||
|
||||
/*--- Xbios interrupt vector ---*/
|
||||
|
||||
_SDL_MintAudio_XbiosInterrupt:
|
||||
|
||||
/* Reenable interrupts, so other interrupts can work */
|
||||
movew #0x2300,sr
|
||||
|
||||
/* Clear service bit, so other MFP interrupts can work */
|
||||
bclr #5,0xfffffa0f:w
|
||||
|
||||
/* Check if we are not already running */
|
||||
tstw _SDL_MintAudio_mutex
|
||||
bnes SDL_MintAudio_XbiosEnd
|
||||
notw _SDL_MintAudio_mutex
|
||||
|
||||
/* Swap buffers */
|
||||
moveml d0-d2/a0-a2,sp@-
|
||||
|
||||
movel _SDL_MintAudio_numbuf,d0
|
||||
movel _SDL_MintAudio_audiobuf,a0
|
||||
eorl #1,d0
|
||||
beqs SDL_MintAudio_XbiosBuffer0
|
||||
movel _SDL_MintAudio_audiobuf+4,a0
|
||||
SDL_MintAudio_XbiosBuffer0:
|
||||
movel d0,_SDL_MintAudio_numbuf
|
||||
|
||||
/* Callback */
|
||||
movel a0,sp@-
|
||||
jsr _SDL_MintAudio_Callback
|
||||
movel sp@+,a0
|
||||
|
||||
/* Setbuffer xbios function */
|
||||
movel _SDL_MintAudio_audiosize,d1
|
||||
lea a0@(0,d1:l),a1
|
||||
|
||||
movel a1,sp@-
|
||||
movel a0,sp@-
|
||||
clrw sp@-
|
||||
movew #131,sp@-
|
||||
trap #14
|
||||
lea sp@(12),sp
|
||||
|
||||
moveml sp@+,d0-d2/a0-a2
|
||||
|
||||
clrw _SDL_MintAudio_mutex
|
||||
SDL_MintAudio_XbiosEnd:
|
||||
rte
|
||||
|
||||
/*--- DMA 8 bits interrupt vector ---*/
|
||||
|
||||
_SDL_MintAudio_Dma8Interrupt:
|
||||
|
||||
/* Reenable interrupts, so other interrupts can work */
|
||||
movew #0x2300,sr
|
||||
|
||||
/* Clear service bit, so other MFP interrupts can work */
|
||||
bclr #5,0xfffffa0f:w
|
||||
|
||||
/* Check if we are not already running */
|
||||
tstw _SDL_MintAudio_mutex
|
||||
bnes SDL_MintAudio_Dma8End
|
||||
notw _SDL_MintAudio_mutex
|
||||
|
||||
/* Swap buffers */
|
||||
moveml d0-d1/a0-a1,sp@-
|
||||
|
||||
movel _SDL_MintAudio_numbuf,d0
|
||||
movel _SDL_MintAudio_audiobuf,d1
|
||||
eorl #1,d0
|
||||
beqs SDL_MintAudio_Dma8Buffer0
|
||||
movel _SDL_MintAudio_audiobuf+4,d1
|
||||
SDL_MintAudio_Dma8Buffer0:
|
||||
movel d0,_SDL_MintAudio_numbuf
|
||||
|
||||
/* Callback */
|
||||
movel d1,sp@-
|
||||
jsr _SDL_MintAudio_Callback
|
||||
movel sp@+,d1
|
||||
|
||||
/* Modify DMA addresses */
|
||||
lea 0xffff8900:w,a0
|
||||
|
||||
moveb d1,a0@(0x07) /* Start address */
|
||||
rorl #8,d1
|
||||
moveb d1,a0@(0x05)
|
||||
rorl #8,d1
|
||||
moveb d1,a0@(0x03)
|
||||
swap d1
|
||||
|
||||
addl _SDL_MintAudio_audiosize,d1
|
||||
|
||||
moveb d1,a0@(0x13) /* End address */
|
||||
rorl #8,d1
|
||||
moveb d1,a0@(0x11)
|
||||
rorl #8,d1
|
||||
moveb d1,a0@(0x0f)
|
||||
|
||||
moveml sp@+,d0-d1/a0-a1
|
||||
|
||||
clrw _SDL_MintAudio_mutex
|
||||
SDL_MintAudio_Dma8End:
|
||||
rte
|
||||
|
||||
/*--- STFA interrupt vector ---*/
|
||||
|
||||
STFA_SOUND_START = 6
|
||||
STFA_SOUND_END = STFA_SOUND_START+8
|
||||
|
||||
_SDL_MintAudio_StfaInterrupt:
|
||||
|
||||
/* Reenable interrupts, so other interrupts can work */
|
||||
movew #0x2300,sr
|
||||
|
||||
/* Check if we are not already running */
|
||||
tstw _SDL_MintAudio_mutex
|
||||
bnes SDL_MintAudio_StfaEnd
|
||||
notw _SDL_MintAudio_mutex
|
||||
|
||||
/* Swap buffers */
|
||||
moveml d0-d1/a0-a1,sp@-
|
||||
|
||||
movel _SDL_MintAudio_numbuf,d0
|
||||
movel _SDL_MintAudio_audiobuf,d1
|
||||
eorl #1,d0
|
||||
beqs SDL_MintAudio_StfaBuffer0
|
||||
movel _SDL_MintAudio_audiobuf+4,d1
|
||||
SDL_MintAudio_StfaBuffer0:
|
||||
movel d0,_SDL_MintAudio_numbuf
|
||||
|
||||
/* Callback */
|
||||
movel d1,sp@-
|
||||
jsr _SDL_MintAudio_Callback
|
||||
movel sp@+,d1
|
||||
|
||||
/* Modify STFA replay buffers */
|
||||
movel _SDL_MintAudio_stfa,a0
|
||||
movel d1,a0@(STFA_SOUND_START)
|
||||
addl _SDL_MintAudio_audiosize,d1
|
||||
movel d1,a0@(STFA_SOUND_END)
|
||||
|
||||
moveml sp@+,d0-d1/a0-a1
|
||||
|
||||
clrw _SDL_MintAudio_mutex
|
||||
SDL_MintAudio_StfaEnd:
|
||||
rte
|
||||
|
379
src/audio/mint/SDL_mintaudio_mcsn.c
Normal file
379
src/audio/mint/SDL_mintaudio_mcsn.c
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MiNT audio driver
|
||||
using XBIOS functions (MacSound compatible driver)
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
#include "SDL_mintaudio_mcsn.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint_mcsn"
|
||||
|
||||
/* Debug print info */
|
||||
#define DEBUG_NAME "audio:mcsn: "
|
||||
#if 0
|
||||
#define DEBUG_PRINT(what) \
|
||||
{ \
|
||||
printf what; \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_PRINT(what)
|
||||
#endif
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd, cookie_mch;
|
||||
static cookie_mcsn_t *cookie_mcsn;
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/* To check/init hardware audio */
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie _MCH present ? if not, assume ST machine */
|
||||
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
|
||||
cookie_mch = MCH_ST;
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Check if we have 16 bits audio */
|
||||
if ((cookie_snd & SND_16BIT)==0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie MCSN present ? */
|
||||
if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check if interrupt at end of replay */
|
||||
if (cookie_mcsn->pint == 0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check if audio is lockable */
|
||||
if (Locksnd()!=1) {
|
||||
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Unlocksnd();
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
/* Restart replay */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
|
||||
/* Uninstall interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
|
||||
/* Wait if currently playing sound */
|
||||
while (SDL_MintAudio_mutex != 0) {
|
||||
}
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
|
||||
/* Unlock sound system */
|
||||
Unlocksnd();
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int i;
|
||||
unsigned long masterclock, masterprediv;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
/* Check formats available */
|
||||
MINTAUDIO_nfreq=4;
|
||||
MINTAUDIO_sfreq=0;
|
||||
switch(cookie_mcsn->play) {
|
||||
case MCSN_ST:
|
||||
spec->channels=1;
|
||||
spec->format=8; /* FIXME: is it signed or unsigned ? */
|
||||
MINTAUDIO_nfreq=1;
|
||||
MINTAUDIO_hardfreq[0]=12500;
|
||||
break;
|
||||
case MCSN_TT: /* Also STE, Mega STE */
|
||||
spec->format=AUDIO_S8;
|
||||
masterclock=MASTERCLOCK_STE;
|
||||
masterprediv=MASTERPREDIV_STE;
|
||||
if ((cookie_mch>>16)==MCH_TT) {
|
||||
masterclock=MASTERCLOCK_TT;
|
||||
masterprediv=MASTERPREDIV_TT;
|
||||
}
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
break;
|
||||
case MCSN_FALCON: /* Also Mac */
|
||||
MINTAUDIO_nfreq=12;
|
||||
MINTAUDIO_sfreq=1;
|
||||
masterclock=MASTERCLOCK_FALCON1;
|
||||
if (cookie_mcsn->res1 != 0) {
|
||||
masterclock=cookie_mcsn->res1;
|
||||
}
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=masterclock/(MASTERPREDIV_FALCON*(i+1));
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
spec->format |= 0x8000; /* Audio is always signed */
|
||||
if ((spec->format & 0x00ff)==16) {
|
||||
spec->format |= 0x1000; /* Audio is always big endian */
|
||||
spec->channels=2; /* 16 bits always stereo */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, (cookie_mch>>16)==MCH_F30, spec->freq);
|
||||
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int channels_mode;
|
||||
void *buffer;
|
||||
|
||||
/* Stop currently playing sound */
|
||||
Buffoper(0);
|
||||
|
||||
/* Set replay tracks */
|
||||
Settracks(0,0);
|
||||
Setmontracks(0);
|
||||
|
||||
/* Select replay format */
|
||||
channels_mode=STEREO16;
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO8;
|
||||
} else {
|
||||
channels_mode=MONO8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Setmode(channels_mode)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
|
||||
}
|
||||
|
||||
switch(cookie_mcsn->play) {
|
||||
case MCSN_TT:
|
||||
Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1);
|
||||
Soundcmd(SETPRESCALE, 3-MINTAUDIO_numfreq);
|
||||
DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n"));
|
||||
break;
|
||||
case MCSN_FALCON:
|
||||
if (cookie_mcsn->res1 != 0) {
|
||||
Devconnect(DMAPLAY, DAC, CLKEXT, MINTAUDIO_numfreq, 1);
|
||||
DEBUG_PRINT((DEBUG_NAME "External clock selected, prescaler %d\n", MINTAUDIO_numfreq));
|
||||
} else {
|
||||
Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
|
||||
DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set buffer */
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
|
||||
}
|
||||
|
||||
/* Install interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
|
||||
Jenabint(MFP_DMASOUND);
|
||||
|
||||
if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
|
||||
}
|
||||
|
||||
/* Go */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
/* Lock sound system */
|
||||
if (Locksnd()!=1) {
|
||||
SDL_SetError("Mint_OpenAudio: Audio system already in use");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (Mint_CheckAudio(this, spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
|
||||
|
||||
/* Setup audio hardware */
|
||||
Mint_InitAudio(this, spec);
|
||||
|
||||
return(1); /* We don't use threaded audio */
|
||||
}
|
58
src/audio/mint/SDL_mintaudio_mcsn.h
Normal file
58
src/audio/mint/SDL_mintaudio_mcsn.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MCSN control structure
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#ifndef _SDL_mintaudio_mcsh_h
|
||||
#define _SDL_mintaudio_mcsh_h
|
||||
|
||||
typedef struct {
|
||||
unsigned short version; /* Version */
|
||||
unsigned short size; /* Size of structure */
|
||||
|
||||
unsigned short play; /* Replay capability */
|
||||
unsigned short record; /* Record capability */
|
||||
unsigned short dsp; /* DSP56K present */
|
||||
unsigned short pint; /* Interrupt at end of replay */
|
||||
unsigned short rint; /* Interrupt at end of record */
|
||||
|
||||
unsigned long res1; /* Frequency of external clock */
|
||||
unsigned long res2;
|
||||
unsigned long res3;
|
||||
unsigned long res4;
|
||||
} cookie_mcsn_t __attribute__((packed));
|
||||
|
||||
enum {
|
||||
MCSN_ST=0,
|
||||
MCSN_TT,
|
||||
MCSN_STE=MCSN_TT,
|
||||
MCSN_FALCON,
|
||||
MCSN_MAC=MCSN_FALCON
|
||||
};
|
||||
|
||||
#define SETSMPFREQ 7 /* Set sample frequency */
|
||||
|
||||
#endif /* _SDL_mintaudio_mcsh_h */
|
319
src/audio/mint/SDL_mintaudio_stfa.c
Normal file
319
src/audio/mint/SDL_mintaudio_stfa.c
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MiNT audio driver
|
||||
using XBIOS functions (STFA driver)
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
#include "SDL_mintaudio_stfa.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint_stfa"
|
||||
|
||||
/* Debug print info */
|
||||
#define DEBUG_NAME "audio:stfa: "
|
||||
#if 0
|
||||
#define DEBUG_PRINT(what) \
|
||||
{ \
|
||||
printf what; \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_PRINT(what)
|
||||
#endif
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd, cookie_mch;
|
||||
static cookie_stfa_t *cookie_stfa;
|
||||
|
||||
static const int freqs[16]={
|
||||
4995, 6269, 7493, 8192,
|
||||
9830, 10971, 12538, 14985,
|
||||
16384, 19819, 21943, 24576,
|
||||
30720, 32336, 43885, 49152
|
||||
};
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/* To check/init hardware audio */
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie _MCH present ? if not, assume ST machine */
|
||||
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
|
||||
cookie_mch = MCH_ST;
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Cookie STFA present ? */
|
||||
if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no STFA audio\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
SDL_MintAudio_stfa = cookie_stfa;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n"));
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_STFA_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Stop replay */
|
||||
oldpile=(void *)Super(0);
|
||||
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Restart replay */
|
||||
oldpile=(void *)Super(0);
|
||||
cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
|
||||
Super(oldpile);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
void *oldpile;
|
||||
|
||||
/* Stop replay */
|
||||
oldpile=(void *)Super(0);
|
||||
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
|
||||
Super(oldpile);
|
||||
|
||||
/* Wait if currently playing sound */
|
||||
while (SDL_MintAudio_mutex != 0) {
|
||||
}
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int i;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
/* Check formats available */
|
||||
MINTAUDIO_nfreq=16;
|
||||
MINTAUDIO_sfreq=0;
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=freqs[15-i];
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
|
||||
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
|
||||
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
void *buffer;
|
||||
void *oldpile;
|
||||
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
|
||||
oldpile=(void *)Super(0);
|
||||
|
||||
/* Stop replay */
|
||||
cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
|
||||
|
||||
/* Select replay format */
|
||||
cookie_stfa->sound_control = 15-MINTAUDIO_numfreq;
|
||||
if ((spec->format & 0xff)==8) {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_8BIT;
|
||||
} else {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_16BIT;
|
||||
}
|
||||
if (spec->channels==2) {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_STEREO;
|
||||
} else {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_MONO;
|
||||
}
|
||||
if (spec->format & 0x8000) {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_SIGNED;
|
||||
} else {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED;
|
||||
}
|
||||
if (spec->format & 0x1000) {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN;
|
||||
} else {
|
||||
cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN;
|
||||
}
|
||||
|
||||
/* Set buffer */
|
||||
cookie_stfa->sound_start = (unsigned long) buffer;
|
||||
cookie_stfa->sound_end = (unsigned long) (buffer + spec->size);
|
||||
|
||||
/* Set interrupt */
|
||||
cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt;
|
||||
|
||||
/* Restart replay */
|
||||
cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
|
||||
|
||||
Super(oldpile);
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (Mint_CheckAudio(this, spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
|
||||
|
||||
/* Setup audio hardware */
|
||||
Mint_InitAudio(this, spec);
|
||||
|
||||
return(1); /* We don't use threaded audio */
|
||||
}
|
99
src/audio/mint/SDL_mintaudio_stfa.h
Normal file
99
src/audio/mint/SDL_mintaudio_stfa.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
STFA control structure
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#ifndef _SDL_mintaudio_stfa_h
|
||||
#define _SDL_mintaudio_stfa_h
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define C_STFA 0x53544641L /* Sound treiber für atari (seb/The removers) */
|
||||
|
||||
#define STFA_PLAY_ENABLE (1<<0)
|
||||
#define STFA_PLAY_DISABLE (0<<0)
|
||||
#define STFA_PLAY_REPEAT (1<<1)
|
||||
#define STFA_PLAY_SINGLE (0<<1)
|
||||
|
||||
#define STFA_FORMAT_SIGNED (1<<15)
|
||||
#define STFA_FORMAT_UNSIGNED (0<<15)
|
||||
#define STFA_FORMAT_STEREO (1<<14)
|
||||
#define STFA_FORMAT_MONO (0<<14)
|
||||
#define STFA_FORMAT_16BIT (1<<13)
|
||||
#define STFA_FORMAT_8BIT (0<<13)
|
||||
#define STFA_FORMAT_LITENDIAN (1<<9)
|
||||
#define STFA_FORMAT_BIGENDIAN (0<<9)
|
||||
#define STFA_FORMAT_FREQ_MASK 0x0f
|
||||
enum {
|
||||
STFA_FORMAT_F4995=0,
|
||||
STFA_FORMAT_F6269,
|
||||
STFA_FORMAT_F7493,
|
||||
STFA_FORMAT_F8192,
|
||||
|
||||
STFA_FORMAT_F9830,
|
||||
STFA_FORMAT_F10971,
|
||||
STFA_FORMAT_F12538,
|
||||
STFA_FORMAT_F14985,
|
||||
|
||||
STFA_FORMAT_F16384,
|
||||
STFA_FORMAT_F19819,
|
||||
STFA_FORMAT_F21943,
|
||||
STFA_FORMAT_F24576,
|
||||
|
||||
STFA_FORMAT_F30720,
|
||||
STFA_FORMAT_F32336,
|
||||
STFA_FORMAT_F43885,
|
||||
STFA_FORMAT_F49152
|
||||
};
|
||||
|
||||
/*--- Types ---*/
|
||||
|
||||
typedef struct {
|
||||
unsigned short sound_enable;
|
||||
unsigned short sound_control;
|
||||
unsigned short sound_output;
|
||||
unsigned long sound_start;
|
||||
unsigned long sound_current;
|
||||
unsigned long sound_end;
|
||||
unsigned short version;
|
||||
void *old_vbl;
|
||||
void *old_timera;
|
||||
unsigned long old_mfp_status;
|
||||
void *new_vbl;
|
||||
void *drivers_list;
|
||||
void *play_stop;
|
||||
unsigned short frequency;
|
||||
void *set_frequency;
|
||||
|
||||
unsigned short frequency_threshold;
|
||||
unsigned short *custom_freq_table;
|
||||
unsigned short stfa_on_off;
|
||||
void *new_drivers_list;
|
||||
unsigned long old_bit_2_of_cookie_snd;
|
||||
void (*stfa_it)(void);
|
||||
} cookie_stfa_t __attribute__((packed));
|
||||
|
||||
#endif /* _SDL_mintaudio_stfa_h */
|
319
src/audio/mint/SDL_mintaudio_xbios.c
Normal file
319
src/audio/mint/SDL_mintaudio_xbios.c
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/*
|
||||
MiNT audio driver
|
||||
using XBIOS functions (Falcon)
|
||||
|
||||
Patrice Mandin
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Mint includes */
|
||||
#include <mint/osbind.h>
|
||||
#include <mint/falcon.h>
|
||||
#include <mint/cookie.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
#include "SDL_audiomem.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
#include "SDL_atarimxalloc_c.h"
|
||||
|
||||
#include "SDL_mintaudio.h"
|
||||
|
||||
/*--- Defines ---*/
|
||||
|
||||
#define MINT_AUDIO_DRIVER_NAME "mint_xbios"
|
||||
|
||||
/* Debug print info */
|
||||
#define DEBUG_NAME "audio:xbios: "
|
||||
#if 0
|
||||
#define DEBUG_PRINT(what) \
|
||||
{ \
|
||||
printf what; \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_PRINT(what)
|
||||
#endif
|
||||
|
||||
/*--- Static variables ---*/
|
||||
|
||||
static unsigned long cookie_snd;
|
||||
|
||||
/*--- Audio driver functions ---*/
|
||||
|
||||
static void Mint_CloseAudio(_THIS);
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_LockAudio(_THIS);
|
||||
static void Mint_UnlockAudio(_THIS);
|
||||
|
||||
/* To check/init hardware audio */
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
|
||||
|
||||
/*--- Audio driver bootstrap functions ---*/
|
||||
|
||||
static int Audio_Available(void)
|
||||
{
|
||||
const char *envr = getenv("SDL_AUDIODRIVER");
|
||||
|
||||
/* Check if user asked a different audio driver */
|
||||
if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
|
||||
DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Cookie _SND present ? if not, assume ST machine */
|
||||
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
|
||||
cookie_snd = SND_PSG;
|
||||
}
|
||||
|
||||
/* Check if we have 16 bits audio */
|
||||
if ((cookie_snd & SND_16BIT)==0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check if audio is lockable */
|
||||
if (Locksnd()!=1) {
|
||||
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
Unlocksnd();
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void Audio_DeleteDevice(SDL_AudioDevice *device)
|
||||
{
|
||||
free(device->hidden);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
|
||||
if ( this ) {
|
||||
memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ( (this == NULL) || (this->hidden == NULL) ) {
|
||||
SDL_OutOfMemory();
|
||||
if ( this ) {
|
||||
free(this);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = Mint_OpenAudio;
|
||||
this->CloseAudio = Mint_CloseAudio;
|
||||
this->LockAudio = Mint_LockAudio;
|
||||
this->UnlockAudio = Mint_UnlockAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
|
||||
MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
|
||||
Audio_Available, Audio_CreateDevice
|
||||
};
|
||||
|
||||
static void Mint_LockAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
}
|
||||
|
||||
static void Mint_UnlockAudio(_THIS)
|
||||
{
|
||||
/* Restart replay */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
}
|
||||
|
||||
static void Mint_CloseAudio(_THIS)
|
||||
{
|
||||
/* Stop replay */
|
||||
Buffoper(0);
|
||||
|
||||
/* Uninstall interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
|
||||
/* Wait if currently playing sound */
|
||||
while (SDL_MintAudio_mutex != 0) {
|
||||
}
|
||||
|
||||
/* Clear buffers */
|
||||
if (SDL_MintAudio_audiobuf[0]) {
|
||||
Mfree(SDL_MintAudio_audiobuf[0]);
|
||||
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
|
||||
}
|
||||
|
||||
/* Unlock sound system */
|
||||
Unlocksnd();
|
||||
}
|
||||
|
||||
static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int i;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
spec->format |= 0x8000; /* Audio is always signed */
|
||||
if ((spec->format & 0x00ff)==16) {
|
||||
spec->format |= 0x1000; /* Audio is always big endian */
|
||||
spec->channels=2; /* 16 bits always stereo */
|
||||
}
|
||||
|
||||
/* FIXME: check for an external clock */
|
||||
MINTAUDIO_sfreq=1;
|
||||
MINTAUDIO_nfreq=12;
|
||||
for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
|
||||
MINTAUDIO_hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
|
||||
DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
|
||||
}
|
||||
|
||||
MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
|
||||
spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
|
||||
DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
|
||||
DEBUG_PRINT(("channels=%d, ", spec->channels));
|
||||
DEBUG_PRINT(("freq=%d\n", spec->freq));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
int channels_mode;
|
||||
void *buffer;
|
||||
|
||||
/* Stop currently playing sound */
|
||||
Buffoper(0);
|
||||
|
||||
/* Set replay tracks */
|
||||
Settracks(0,0);
|
||||
Setmontracks(0);
|
||||
|
||||
/* Select replay format */
|
||||
channels_mode=STEREO16;
|
||||
switch (spec->format & 0xff) {
|
||||
case 8:
|
||||
if (spec->channels==2) {
|
||||
channels_mode=STEREO8;
|
||||
} else {
|
||||
channels_mode=MONO8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Setmode(channels_mode)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
|
||||
}
|
||||
|
||||
/* FIXME: select an external clock */
|
||||
|
||||
Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
|
||||
DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
|
||||
|
||||
/* Set buffer */
|
||||
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
|
||||
if (Setbuffer(0, buffer, buffer + spec->size)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
|
||||
}
|
||||
|
||||
/* Install interrupt */
|
||||
Jdisint(MFP_DMASOUND);
|
||||
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
|
||||
Jenabint(MFP_DMASOUND);
|
||||
|
||||
if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
|
||||
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
|
||||
}
|
||||
|
||||
/* Go */
|
||||
Buffoper(SB_PLA_ENA|SB_PLA_RPT);
|
||||
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
|
||||
}
|
||||
|
||||
static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
|
||||
{
|
||||
/* Lock sound system */
|
||||
if (Locksnd()!=1) {
|
||||
SDL_SetError("Mint_OpenAudio: Audio system already in use");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
SDL_MintAudio_device = this;
|
||||
|
||||
/* Check audio capabilities */
|
||||
if (Mint_CheckAudio(this, spec)==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate memory for audio buffers in DMA-able RAM */
|
||||
spec->size = spec->samples;
|
||||
spec->size *= spec->channels;
|
||||
spec->size *= (spec->format & 0xFF)/8;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
|
||||
|
||||
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
|
||||
if (SDL_MintAudio_audiobuf[0]==NULL) {
|
||||
SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
|
||||
return (-1);
|
||||
}
|
||||
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
|
||||
SDL_MintAudio_numbuf=0;
|
||||
memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
|
||||
SDL_MintAudio_audiosize = spec->size;
|
||||
SDL_MintAudio_mutex = 0;
|
||||
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
|
||||
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
|
||||
|
||||
/* Setup audio hardware */
|
||||
Mint_InitAudio(this, spec);
|
||||
|
||||
return(1); /* We don't use threaded audio */
|
||||
}
|
Loading…
Reference in New Issue
Block a user