home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / sharewar / mikm202 / source / drvsb / sbdev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-18  |  5.8 KB  |  335 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dos.h>
  4. #include <malloc.h>
  5. #include <conio.h>
  6. #include <mem.h>
  7.  
  8. #include "mtypes.h"
  9.  
  10. #include "mdriver.h"
  11. #include "vc.h"
  12. #include "mdma.h"
  13. #include "sbio.h"
  14.  
  15. char *SB_DMABUF;
  16. UBYTE SB_TIMECONSTANT;
  17.  
  18. UBYTE PIC1MSK;
  19. UBYTE PIC2MSK;
  20.  
  21. extern UNIMOD *pf;
  22.  
  23. UWORD sb_int;           // interrupt vector that belongs to sb_irq
  24. UWORD sb_ver;           // DSP version number
  25. UWORD sb_port;          // sb base port
  26. UBYTE sb_irq;           // sb irq
  27. UBYTE sb_lodma;         // 8 bit dma channel (1.0/2.0/pro)
  28. UBYTE sb_hidma;         // 16 bit dma channel (16/16asp)
  29. UBYTE sb_dma;           // current dma channel
  30.  
  31.  
  32. BOOL SB_IsThere(void)
  33. {
  34.     char *envptr,*endptr,c;
  35.  
  36.     sb_port =0xffff;
  37.     sb_irq  =0xff;
  38.     sb_lodma=0xff;
  39.     sb_hidma=0xff;
  40.  
  41.     if((envptr=getenv("BLASTER"))==NULL) return 0;
  42.  
  43.     while(1){
  44.  
  45.         // skip whitespace
  46.  
  47.         do c=*(envptr++); while(c==' ' || c=='\t');
  48.  
  49.         // reached end of string? -> exit
  50.  
  51.         if(c==0) break;
  52.  
  53.         switch(c){
  54.  
  55.             case 'a':
  56.             case 'A':
  57.                 sb_port=strtol(envptr,&endptr,16);
  58.                 break;
  59.  
  60.             case 'i':
  61.             case 'I':
  62.                 sb_irq=strtol(envptr,&endptr,10);
  63.                 break;
  64.  
  65.             case 'd':
  66.             case 'D':
  67.                 sb_lodma=strtol(envptr,&endptr,10);
  68.                 break;
  69.  
  70.             case 'h':
  71.             case 'H':
  72.                 sb_hidma=strtol(envptr,&endptr,10);
  73.                 break;
  74.  
  75.             default:
  76.                 strtol(envptr,&endptr,16);
  77.                 break;
  78.         }
  79.         envptr=endptr;
  80.     }
  81.  
  82.     if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0;
  83.  
  84.     // determine interrupt vector
  85.  
  86.     sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8;
  87.  
  88.     if(!SB_Ping()) return 0;
  89.  
  90.     // get dsp version.
  91.  
  92.     if((sb_ver=SB_GetDSPVersion())==0xffff) return 0;
  93.  
  94.     return 1;
  95. }
  96.  
  97.  
  98.  
  99. BOOL SB_Init(void)
  100. {
  101.     ULONG t;
  102.  
  103.     if(!SB_IsThere()){
  104.         myerr="No such hardware detected, check your 'BLASTER' env. variable";
  105.         return 0;
  106.     }
  107.  
  108.     printf("SB version %x\n",sb_ver);
  109.  
  110. //      if(sb_ver>0x200) sb_ver=0x200;
  111.  
  112.     if(sb_ver>=0x400 && sb_hidma==0xff){
  113.         myerr="High-dma setting in 'BLASTER' variable is required for SB-16";
  114.         return 0;
  115.     }
  116.  
  117.     if(sb_ver<0x400 && md_mode&DMODE_16BITS){
  118.         // DSP versions below 4.00 can't do 16 bit sound.
  119.         md_mode&=~DMODE_16BITS;
  120.     }
  121.  
  122.     if(sb_ver<0x300 && md_mode&DMODE_STEREO){
  123.         // DSP versions below 3.00 can't do stereo sound.
  124.         md_mode&=~DMODE_STEREO;
  125.     }
  126.  
  127.     // Use low dma channel for 8 bit, high dma for 16 bit
  128.  
  129.     sb_dma=(md_mode & DMODE_16BITS) ? sb_hidma : sb_lodma;
  130.  
  131.     if(sb_ver<0x400){
  132.  
  133.         t=md_mixfreq;
  134.         if(md_mode & DMODE_STEREO) t<<=1;
  135.  
  136.         SB_TIMECONSTANT=256-(1000000L/t);
  137.  
  138.         if(sb_ver<0x201){
  139.             if(SB_TIMECONSTANT>210) SB_TIMECONSTANT=210;
  140.         }
  141.         else{
  142.             if(SB_TIMECONSTANT>233) SB_TIMECONSTANT=233;
  143.         }
  144.  
  145.         md_mixfreq=1000000L/(256-SB_TIMECONSTANT);
  146.         if(md_mode & DMODE_STEREO) md_mixfreq>>=1;
  147.     }
  148.  
  149.     if(!VC_Init()) return 0;
  150.  
  151.     SB_DMABUF=Dma_AllocMem(md_dmabufsize);
  152.  
  153.     if(SB_DMABUF==NULL){
  154.         myerr="Couldn't allocate page-contiguous dma-buffer";
  155.         return 0;
  156.     }
  157.  
  158.     return 1;
  159. }
  160.  
  161.  
  162.  
  163. void SB_Exit(void)
  164. {
  165.     Dma_FreeMem(SB_DMABUF);
  166.     VC_Exit();
  167. }
  168.  
  169.  
  170. void interrupt newhandler(void)
  171. {
  172.     if(sb_ver<0x200){
  173.         SB_WriteDSP(0x14);
  174.         SB_WriteDSP(0xff);
  175.         SB_WriteDSP(0xfe);
  176.     }
  177.  
  178.     if(md_mode & DMODE_16BITS)
  179.         inportb(sb_port+0xf);
  180.     else
  181.         inportb(DSP_DATA_AVAIL);
  182.  
  183.     if(sb_irq>7) outportb(0xa0,0x20);
  184.     outportb(0x20,0x20);
  185. }
  186.  
  187. void (interrupt far *oldhandler)(void);
  188.  
  189. UWORD last=0;
  190. UWORD curr=0;
  191.  
  192.  
  193. void SB_Update(void)
  194. {
  195.     UWORD todo;
  196.  
  197.     curr=(md_dmabufsize-Dma_Todo(sb_dma))&0xfffc;
  198.     
  199.     if(curr>last){
  200.         todo=curr-last;
  201.         last+=VC_WriteBytes(&SB_DMABUF[last],todo);
  202.         if(last>=md_dmabufsize) last=0;
  203.     }
  204.     else{
  205.         todo=md_dmabufsize-last;
  206.         VC_WriteBytes(&SB_DMABUF[last],todo);
  207.         last=VC_WriteBytes(SB_DMABUF,curr);
  208.     }
  209. }
  210.  
  211.  
  212.  
  213.  
  214. void SB_PlayStart(void)
  215. {
  216.     VC_PlayStart();
  217.  
  218.     disable();
  219.  
  220.     PIC1MSK=inportb(0x21);
  221.     PIC2MSK=inportb(0xa1);
  222.  
  223.     if(sb_irq>7){
  224.         outportb(0x21,PIC1MSK & 0xfb);                          // 1111 1011 enable irq 2
  225.         outportb(0xa1,PIC2MSK & ~(1<<(sb_irq-8)));      // and enable high irq
  226.     }
  227.     else{
  228.         // En de SB interrupts toestaan
  229.         outportb(0x21,PIC1MSK & ~(1<<sb_irq));
  230.     }
  231.  
  232.     oldhandler=_dos_getvect(sb_int);
  233.     _dos_setvect(sb_int,newhandler);
  234.  
  235.     enable();
  236.  
  237.     if(sb_ver>=0x300 && sb_ver<0x400){
  238.         if(md_mode & DMODE_STEREO){
  239.             SB_MixerStereo();
  240.         }
  241.         else{
  242.             SB_MixerMono();
  243.         }
  244.     }
  245.  
  246.     /* clear the dma buffer to zero (16 bits
  247.        signed ) or 0x80 (8 bits unsigned) */
  248.  
  249.     if(md_mode & DMODE_16BITS)
  250.         memset(SB_DMABUF,0,md_dmabufsize);
  251.     else
  252.         memset(SB_DMABUF,0x80,md_dmabufsize);
  253.  
  254.     if(!Dma_Start(sb_dma,SB_DMABUF,md_dmabufsize,INDEF_WRITE)){
  255.         return;
  256.     }
  257.  
  258.     if(sb_ver<0x400){
  259.         SB_SpeakerOn();
  260.  
  261.         SB_WriteDSP(0x40);
  262.         SB_WriteDSP(SB_TIMECONSTANT);
  263.  
  264.         if(sb_ver<0x200){
  265.             SB_WriteDSP(0x14);
  266.             SB_WriteDSP(0xff);
  267.             SB_WriteDSP(0xfe);
  268.         }
  269.         else if(sb_ver==0x200){
  270.             SB_WriteDSP(0x48);
  271.             SB_WriteDSP(0xff);
  272.             SB_WriteDSP(0xfe);
  273.             SB_WriteDSP(0x1c);
  274.         }
  275.         else{
  276.             SB_WriteDSP(0x48);
  277.             SB_WriteDSP(0xff);
  278.             SB_WriteDSP(0xfe);
  279.             SB_WriteDSP(0x90);
  280.         }
  281.     }
  282.     else{
  283.         SB_WriteDSP(0x41);
  284.  
  285.         SB_WriteDSP(md_mixfreq>>8);
  286.         SB_WriteDSP(md_mixfreq&0xff);
  287.  
  288.         if(md_mode & DMODE_16BITS){
  289.             SB_WriteDSP(0xb6);
  290.             SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x30 : 0x10);
  291.         }
  292.         else{
  293.             SB_WriteDSP(0xc6);
  294.             SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x20 : 0x00);
  295.         }
  296.  
  297.         SB_WriteDSP(0xff);
  298.         SB_WriteDSP(0xef);
  299.     }
  300. }
  301.  
  302.  
  303.  
  304.  
  305. void SB_PlayStop(void)
  306. {
  307.     VC_PlayStop();
  308.  
  309.     SB_SpeakerOff();
  310.     SB_ResetDSP();
  311.     SB_ResetDSP();
  312.     Dma_Stop(sb_dma);
  313.  
  314.     disable();
  315.     _dos_setvect(sb_int,oldhandler);
  316.     outportb(0x21,PIC1MSK);
  317.     outportb(0xa1,PIC2MSK);
  318.     enable();
  319. }
  320.  
  321.  
  322. DRIVER sbdriver={
  323.     NULL,
  324.     "Soundblaster & compatibles",
  325.     "MikMod Soundblaster Driver v1.0 for 1.0 / 2.0 / Pro / 16",
  326.     SB_IsThere,
  327.     VC_SampleLoad,
  328.     VC_SampleUnload,
  329.     SB_Init,
  330.     SB_Exit,
  331.     SB_PlayStart,
  332.     SB_PlayStop,
  333.     SB_Update
  334. };
  335.