home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <malloc.h>
- #include <conio.h>
- #include <mem.h>
-
- #include "mtypes.h"
-
- #include "mdriver.h"
- #include "vc.h"
- #include "mdma.h"
- #include "sbio.h"
-
- char *SB_DMABUF;
- UBYTE SB_TIMECONSTANT;
-
- UBYTE PIC1MSK;
- UBYTE PIC2MSK;
-
- extern UNIMOD *pf;
-
- UWORD sb_int; // interrupt vector that belongs to sb_irq
- UWORD sb_ver; // DSP version number
- UWORD sb_port; // sb base port
- UBYTE sb_irq; // sb irq
- UBYTE sb_lodma; // 8 bit dma channel (1.0/2.0/pro)
- UBYTE sb_hidma; // 16 bit dma channel (16/16asp)
- UBYTE sb_dma; // current dma channel
-
-
- BOOL SB_IsThere(void)
- {
- char *envptr,*endptr,c;
-
- sb_port =0xffff;
- sb_irq =0xff;
- sb_lodma=0xff;
- sb_hidma=0xff;
-
- if((envptr=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;
- }
-
-
-
- BOOL SB_Init(void)
- {
- ULONG t;
-
- if(!SB_IsThere()){
- myerr="No such hardware detected, check your 'BLASTER' env. variable";
- return 0;
- }
-
- printf("SB version %x\n",sb_ver);
-
- // if(sb_ver>0x200) sb_ver=0x200;
-
- if(sb_ver>=0x400 && sb_hidma==0xff){
- myerr="High-dma setting in 'BLASTER' variable is required for SB-16";
- return 0;
- }
-
- if(sb_ver<0x400 && md_mode&DMODE_16BITS){
- // DSP versions below 4.00 can't do 16 bit sound.
- md_mode&=~DMODE_16BITS;
- }
-
- if(sb_ver<0x300 && md_mode&DMODE_STEREO){
- // DSP versions below 3.00 can't do stereo sound.
- md_mode&=~DMODE_STEREO;
- }
-
- // Use low dma channel for 8 bit, high dma for 16 bit
-
- sb_dma=(md_mode & DMODE_16BITS) ? sb_hidma : sb_lodma;
-
- if(sb_ver<0x400){
-
- t=md_mixfreq;
- if(md_mode & DMODE_STEREO) t<<=1;
-
- SB_TIMECONSTANT=256-(1000000L/t);
-
- if(sb_ver<0x201){
- if(SB_TIMECONSTANT>210) SB_TIMECONSTANT=210;
- }
- else{
- if(SB_TIMECONSTANT>233) SB_TIMECONSTANT=233;
- }
-
- md_mixfreq=1000000L/(256-SB_TIMECONSTANT);
- if(md_mode & DMODE_STEREO) md_mixfreq>>=1;
- }
-
- if(!VC_Init()) return 0;
-
- SB_DMABUF=Dma_AllocMem(md_dmabufsize);
-
- if(SB_DMABUF==NULL){
- myerr="Couldn't allocate page-contiguous dma-buffer";
- return 0;
- }
-
- return 1;
- }
-
-
-
- void SB_Exit(void)
- {
- Dma_FreeMem(SB_DMABUF);
- VC_Exit();
- }
-
-
- void interrupt newhandler(void)
- {
- if(sb_ver<0x200){
- SB_WriteDSP(0x14);
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xfe);
- }
-
- if(md_mode & DMODE_16BITS)
- inportb(sb_port+0xf);
- else
- inportb(DSP_DATA_AVAIL);
-
- if(sb_irq>7) outportb(0xa0,0x20);
- outportb(0x20,0x20);
- }
-
- void (interrupt far *oldhandler)(void);
-
- UWORD last=0;
- UWORD curr=0;
-
-
- void SB_Update(void)
- {
- UWORD todo;
-
- curr=(md_dmabufsize-Dma_Todo(sb_dma))&0xfffc;
-
- if(curr>last){
- todo=curr-last;
- last+=VC_WriteBytes(&SB_DMABUF[last],todo);
- if(last>=md_dmabufsize) last=0;
- }
- else{
- todo=md_dmabufsize-last;
- VC_WriteBytes(&SB_DMABUF[last],todo);
- last=VC_WriteBytes(SB_DMABUF,curr);
- }
- }
-
-
-
-
- void SB_PlayStart(void)
- {
- VC_PlayStart();
-
- disable();
-
- PIC1MSK=inportb(0x21);
- PIC2MSK=inportb(0xa1);
-
- if(sb_irq>7){
- outportb(0x21,PIC1MSK & 0xfb); // 1111 1011 enable irq 2
- outportb(0xa1,PIC2MSK & ~(1<<(sb_irq-8))); // and enable high irq
- }
- else{
- // En de SB interrupts toestaan
- outportb(0x21,PIC1MSK & ~(1<<sb_irq));
- }
-
- oldhandler=_dos_getvect(sb_int);
- _dos_setvect(sb_int,newhandler);
-
- enable();
-
- if(sb_ver>=0x300 && sb_ver<0x400){
- if(md_mode & DMODE_STEREO){
- SB_MixerStereo();
- }
- else{
- SB_MixerMono();
- }
- }
-
- /* clear the dma buffer to zero (16 bits
- signed ) or 0x80 (8 bits unsigned) */
-
- if(md_mode & DMODE_16BITS)
- memset(SB_DMABUF,0,md_dmabufsize);
- else
- memset(SB_DMABUF,0x80,md_dmabufsize);
-
- if(!Dma_Start(sb_dma,SB_DMABUF,md_dmabufsize,INDEF_WRITE)){
- return;
- }
-
- if(sb_ver<0x400){
- SB_SpeakerOn();
-
- SB_WriteDSP(0x40);
- SB_WriteDSP(SB_TIMECONSTANT);
-
- if(sb_ver<0x200){
- SB_WriteDSP(0x14);
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xfe);
- }
- else if(sb_ver==0x200){
- SB_WriteDSP(0x48);
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xfe);
- SB_WriteDSP(0x1c);
- }
- else{
- SB_WriteDSP(0x48);
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xfe);
- SB_WriteDSP(0x90);
- }
- }
- else{
- SB_WriteDSP(0x41);
-
- SB_WriteDSP(md_mixfreq>>8);
- SB_WriteDSP(md_mixfreq&0xff);
-
- if(md_mode & DMODE_16BITS){
- SB_WriteDSP(0xb6);
- SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x30 : 0x10);
- }
- else{
- SB_WriteDSP(0xc6);
- SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x20 : 0x00);
- }
-
- SB_WriteDSP(0xff);
- SB_WriteDSP(0xef);
- }
- }
-
-
-
-
- void SB_PlayStop(void)
- {
- VC_PlayStop();
-
- SB_SpeakerOff();
- SB_ResetDSP();
- SB_ResetDSP();
- Dma_Stop(sb_dma);
-
- disable();
- _dos_setvect(sb_int,oldhandler);
- outportb(0x21,PIC1MSK);
- outportb(0xa1,PIC2MSK);
- enable();
- }
-
-
- DRIVER sbdriver={
- NULL,
- "Soundblaster & compatibles",
- "MikMod Soundblaster Driver v1.0 for 1.0 / 2.0 / Pro / 16",
- SB_IsThere,
- VC_SampleLoad,
- VC_SampleUnload,
- SB_Init,
- SB_Exit,
- SB_PlayStart,
- SB_PlayStop,
- SB_Update
- };
-