home *** CD-ROM | disk | FTP | other *** search
- #include <dos.h>
- #include "audio.h"
- #include "mpg123.h"
- #include "mdma.h"
- #include "mirq.h"
-
- #define DMA_SIZE 32768
-
- void interrupt far newhandler();
- void SB_PlayStop(void);
- void SB_PlayStart(void);
- void SB_MixerStereo(void);
- void SB_MixerMono(void);
- BOOL SB_WaitDSPWrite(void);
- BOOL SB_WaitDSPRead(void);
- BOOL SB_WriteDSP(UBYTE);
- UWORD SB_ReadDSP(void);
- void SB_SpeakerOn(void);
- void SB_SpeakerOff(void);
- void SB_ResetDSP(void);
- BOOL SB_Ping(void);
- UWORD SB_GetDSPVersion(void);
- BOOL SB_IsThere(void);
-
- static UWORD sb_port; /* sb base port */
-
- static DMAMEM *SB_DMAMEM;
- static char *SB_DMABUF;
-
- static UBYTE SB_TIMECONSTANT;
-
- static UBYTE PIC1MSK;
- static UBYTE PIC2MSK;
-
- static UWORD sb_int; /* interrupt vector that belongs to sb_irq */
- static UWORD sb_ver; /* DSP version number */
- static UBYTE sb_irq; /* sb irq */
- static UBYTE sb_lodma; /* 8 bit dma channel (1.0/2.0/pro) */
- static UBYTE sb_hidma; /* 16 bit dma channel (16/16asp) */
- static UBYTE sb_dma; /* current dma channel */
-
- UWORD last=0;
- UWORD curr=0;
-
- BOOL playing=0;
- int mixfreq;
-
- PVI oldhandler;
-
- int audio_open(struct audio_info_struct *ai)
- {
- ULONG t;
-
- if(!SB_IsThere()){
- fprintf(stderr,"SB not detected.");
- return -1;
- }
-
- if(sb_ver<0x400){
- fprintf(stderr,"SB16 not detected.");
- return -1;
- }
-
- sb_dma=sb_hidma;
-
- SB_DMAMEM=MDma_AllocMem(DMA_SIZE);
-
- if(SB_DMAMEM==NULL){
- fprintf(stderr,"Couldn't allocate page-contiguous dma-buffer");
- return -1;
- }
-
- SB_DMABUF=(char *)MDma_GetPtr(SB_DMAMEM);
-
- memset(SB_DMABUF,0,DMA_SIZE);
-
- oldhandler=MIrq_SetHandler(sb_irq,newhandler);
- return 0;
- }
-
- int audio_set_rate(struct audio_info_struct *ai)
- {
- mixfreq=ai->rate;
- return 0;
- }
-
- int audio_set_channels(struct audio_info_struct *ai)
- {
- return 0; // not neccessary :)
- }
-
- int audio_play_samples(struct audio_info_struct *ai,short *src,int size)
- {
- UWORD todo,left;
-
- left=size*2;
-
- if (playing==0) SB_PlayStart();
-
- wait:
- curr=(DMA_SIZE-MDma_Todo(sb_dma))&0xfffc;
-
- if(curr>last){
- todo=curr-last;
-
- if(todo>left)
- {
- memcpy(&SB_DMABUF[last],(char *)src,left);
- last += left;
- if(last>=DMA_SIZE) last=0;
- return 0;
- }
- else
- {
- // memcpy(&SB_DMABUF[last],(char *)src,todo);
- // last += todo;
- // src += todo;
- // left-=todo;
-
- // WHAT THE FUCK IS WRONG WITH THIS???
-
- goto wait;
- }
-
- }
- else{
- todo=DMA_SIZE-last;
-
- if(todo>left)
- {
- memcpy(&SB_DMABUF[last],(char *)src,left);
- last += left;
- return 0;
- }
- else
- {
- memcpy(&SB_DMABUF[last],(char *)src,todo);
- left-=todo;
- last=0;
- src+=todo;
- goto wait;
- }
- }
- }
-
- int audio_close(struct audio_info_struct *ai)
- {
- SB_PlayStop();
- MIrq_SetHandler(sb_irq,oldhandler);
- MDma_FreeMem(SB_DMAMEM);
- return 0;
- }
-
- void interrupt far newhandler(MIRQARGS)
- {
- inportb(sb_port+0xf);
- MIrq_EOI(sb_irq);
- }
-
- BOOL SB_WaitDSPWrite(void)
- /*
- Waits until the DSP is ready to be written to.
-
- returns FALSE on timeout
- */
- {
- UWORD timeout=32767;
-
- while(timeout--){
- if(!(inportb(DSP_WRITE_STATUS)&0x80)) return 1;
- }
- return 0;
- }
-
-
-
- BOOL SB_WaitDSPRead(void)
- /*
- Waits until the DSP is ready to read from.
-
- returns FALSE on timeout
- */
- {
- UWORD timeout=32767;
-
- while(timeout--){
- if(inportb(DSP_DATA_AVAIL)&0x80) return 1;
- }
- return 0;
- }
-
-
-
- BOOL SB_WriteDSP(UBYTE data)
- /*
- Writes byte 'data' to the DSP.
-
- returns FALSE on timeout.
- */
- {
- if(!SB_WaitDSPWrite()) return 0;
- outportb(DSP_WRITE_DATA,data);
- return 1;
- }
-
-
-
- UWORD SB_ReadDSP(void)
- /*
- Reads a byte from the DSP.
-
- returns 0xffff on timeout.
- */
- {
- if(!SB_WaitDSPRead()) return 0xffff;
- return(inportb(DSP_READ_DATA));
- }
-
-
-
- void SB_SpeakerOn(void)
- /*
- Enables DAC speaker output.
- */
- {
- SB_WriteDSP(0xd1);
- }
-
-
-
- void SB_SpeakerOff(void)
- /*
- Disables DAC speaker output
- */
- {
- SB_WriteDSP(0xd3);
- }
-
-
-
- void SB_ResetDSP(void)
- /*
- Resets the DSP.
- */
- {
- int t;
- /* reset the DSP by sending 1, (delay), then 0 */
- outportb(DSP_RESET,1);
- for(t=0;t<8;t++) inportb(DSP_RESET);
- outportb(DSP_RESET,0);
- }
-
-
-
- BOOL SB_Ping(void)
- /*
- Checks if a SB is present at the current baseport by
- resetting the DSP and checking if it returned the value 0xaa.
-
- returns: TRUE => SB is present
- FALSE => No SB detected
- */
- {
- SB_ResetDSP();
- return(SB_ReadDSP()==0xaa);
- }
-
-
-
- UWORD SB_GetDSPVersion(void)
- /*
- Gets SB-dsp version. returns 0xffff if dsp didn't respond.
- */
- {
- UWORD hi,lo;
-
- if(!SB_WriteDSP(0xe1)) return 0xffff;
-
- hi=SB_ReadDSP();
- lo=SB_ReadDSP();
-
- return((hi<<8)|lo);
- }
-
- static BOOL SB_IsThere(void)
- {
- char *envptr,c;
- static char *endptr;
-
- sb_port =0xffff;
- sb_irq =0xff;
- sb_lodma=0xff;
- sb_hidma=0xff;
-
- if((envptr=(char *)getenv("BLASTER"))==NULL) return 0;
-
- while(1){
-
- /* skip whitespace */
-
- do c=*(envptr++); while(c==' ' || c=='\t');
-
- /* reached end of string? -> exit */
-
- if(c==0) break;
-
- switch(c){
-
- case 'a':
- case 'A':
- sb_port=strtol(envptr,&endptr,16);
- break;
-
- case 'i':
- case 'I':
- sb_irq=strtol(envptr,&endptr,10);
- break;
-
- case 'd':
- case 'D':
- sb_lodma=strtol(envptr,&endptr,10);
- break;
-
- case 'h':
- case 'H':
- sb_hidma=strtol(envptr,&endptr,10);
- break;
-
- default:
- strtol(envptr,&endptr,16);
- break;
- }
- envptr=endptr;
- }
-
- if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0;
-
- /* determine interrupt vector */
-
- sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8;
-
- if(!SB_Ping()) return 0;
-
- /* get dsp version. */
-
- if((sb_ver=SB_GetDSPVersion())==0xffff) return 0;
-
- return 1;
- }
-
- static void SB_PlayStart(void)
- {
- MIrq_OnOff(sb_irq,1);
-
- if(!MDma_Start(sb_dma,SB_DMAMEM,DMA_SIZE,INDEF_WRITE)){
- return;
- }
-
- SB_WriteDSP(0x41);
-
- SB_WriteDSP(mixfreq>>8);
- SB_WriteDSP(mixfreq&0xff);
-
- SB_WriteDSP(0xb6);
- SB_WriteDSP(0x30);
-
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xef);
-
- playing=1;
- }
-
- static void SB_PlayStop(void)
- {
- if ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc > last)
- while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc>last);
-
- while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc <last);
-
- MDma_Stop(sb_dma);
- MIrq_OnOff(sb_irq,0);
- SB_SpeakerOff();
- SB_ResetDSP();
- SB_ResetDSP();
- }
-
-