⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tl_sb.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
📖 第 1 页 / 共 2 页
字号:
}/*** Probe for an SB*/static int sb_probe(void){   int retval;   retval = parse_blaster_env();   /* if environment parse failed, try brute force autodetection */   if (-1 == retval)      retval = sb_detect();   /* no blaster found */   if (-1 == retval)   {      thin_printf("thin@sb: no sound blaster found\n");      return -1;   }   if (dsp_reset())   {      thin_printf("thin@sb: could not reset SB DSP: check BLASTER= variable\n");      return -1;   }   sb.dsp_version = dsp_getversion();   return 0;}/*** Interrupt handler for 8/16-bit audio */static void sb_isr(void){   uint32 address, offset;   dma.count++;   /* NOTE: this only works with 8-bit, as one-shot mode   ** does not seem to work with 16-bit transfers   */   if (false == dma.autoinit)   {      dsp_write(DSP_DMA_DAC_8BIT);      dsp_write(LOW_BYTE(sb.buf_size - 1));      dsp_write(HIGH_BYTE(sb.buf_size - 1));   }   /* indicate we got the interrupt */   inportb(dma.ackport);   /* determine the current playback position */   address = inportb(dma.addrport);   address |= (inportb(dma.addrport) << 8);   address -= dos.offset;   if (address < sb.buf_size)      offset = sb.buf_chunk;   else      offset = 0;   sb.callback(sb.buffer + offset, sb.buf_size);   if (0 == thinlib_nearptr)      dosmemput(sb.buffer + offset, sb.buf_chunk, dos.bufaddr + offset);   /* acknowledge interrupt was taken */   if (sb.irq > 7)      outportb(0xA0, 0x20);   outportb(0x20, 0x20);}THIN_LOCKED_STATIC_FUNC(sb_isr)/* install the SB ISR */static void sb_setisr(void){   /* lock variables, routines */   THIN_LOCK_VAR(dma);   THIN_LOCK_VAR(dos);   THIN_LOCK_VAR(sb);   THIN_LOCK_FUNC(sb_isr);   if (sb.format & SB_FORMAT_16BIT)   {      dma.ackport = sb.baseio + DSP_DMA_ACK_16BIT;      dma.addrport = DMA_ADDRBASE_16BIT + (4 * (sb.dma16 - 4));   }   else   {      dma.ackport = sb.baseio + DSP_DMA_ACK_8BIT;      dma.addrport = DMA_ADDRBASE_8BIT + (2 * sb.dma);   }   if (sb.irq < 8)   {      /* PIC 1 */      intr.irq_vector = 0x08 + sb.irq;      intr.pic_rotateport = 0x20;      intr.pic_maskport = 0x21;   }   else   {      /* PIC 2 */      intr.irq_vector = 0x70 + (sb.irq - 8);      intr.pic_rotateport = 0xA0;      intr.pic_maskport = 0xA1;   }   intr.irq_stopmask = 1 << (sb.irq & 7);   intr.irq_startmask = ~intr.irq_stopmask;   /* reset DMA count */   dma.count = 0;   THIN_DISABLE_INTS();   outportb(intr.pic_maskport, inportb(intr.pic_maskport) | intr.irq_stopmask);   _go32_dpmi_get_protected_mode_interrupt_vector(intr.irq_vector, &intr.old_interrupt);   intr.new_interrupt.pm_offset = (int) sb_isr;   intr.new_interrupt.pm_selector = _go32_my_cs();   _go32_dpmi_allocate_iret_wrapper(&intr.new_interrupt);   _go32_dpmi_set_protected_mode_interrupt_vector(intr.irq_vector, &intr.new_interrupt);   /* unmask the PIC, get things ready to roll */   outportb(intr.pic_maskport, inportb(intr.pic_maskport) & intr.irq_startmask);   THIN_ENABLE_INTS();}/* remove SB ISR, restore old */static void sb_resetisr(void){   THIN_DISABLE_INTS();   outportb(intr.pic_maskport, inportb(intr.pic_maskport) | intr.irq_stopmask);   _go32_dpmi_set_protected_mode_interrupt_vector(intr.irq_vector, &intr.old_interrupt);   _go32_dpmi_free_iret_wrapper(&intr.new_interrupt);   THIN_ENABLE_INTS();}/* allocate sound buffers */static int sb_allocate_buffers(int buf_size){   int double_bufsize;   sb.buf_size = buf_size;   if (sb.format & SB_FORMAT_16BIT)      sb.buf_chunk = sb.buf_size * sizeof(uint16);   else      sb.buf_chunk = sb.buf_size * sizeof(uint8);   double_bufsize = 2 * sb.buf_chunk;   dos.buffer.size = (double_bufsize + 15) >> 4;   if (_go32_dpmi_allocate_dos_memory(&dos.buffer))      return -1;   /* calc linear address */   dos.bufaddr = dos.buffer.rm_segment << 4;   if (sb.format & SB_FORMAT_16BIT)   {      dos.page = (dos.bufaddr >> 16) & 0xFF;      dos.offset = (dos.bufaddr >> 1) & 0xFFFF;   }   else   {      dos.page = (dos.bufaddr >> 16) & 0xFF;      dos.offset = dos.bufaddr & 0xFFFF;   }   if (thinlib_nearptr)   {      sb.buffer = (uint8 *) THIN_PHYS_ADDR(dos.bufaddr);   }   else   {      sb.buffer = malloc(double_bufsize);      if (NULL == sb.buffer)         return -1;   }   /* clear out the buffers */   if (sb.format & SB_FORMAT_16BIT)      memset(sb.buffer, SILENCE_SIGNED, double_bufsize);   else      memset(sb.buffer, SILENCE_UNSIGNED, double_bufsize);   if (0 == thinlib_nearptr)      dosmemput(sb.buffer, double_bufsize, dos.bufaddr);   return 0;}/* free them buffers */static void sb_free_buffers(void){   sb.callback = NULL;   _go32_dpmi_free_dos_memory(&dos.buffer);   if (0 == thinlib_nearptr)   {      free(sb.buffer);      sb.buffer = NULL;   }   sb.buffer = NULL;}/* get rid of all things SB */void thin_sb_shutdown(void){   if (true == sb.initialized)   {      sb.initialized = false;      dsp_reset();      sb_resetisr();      sb_free_buffers();   }}/* initialize sound bastard */int thin_sb_init(int *sample_rate, int *buf_size, int *format){#define  CLAMP_RATE(in_rate, min_rate, max_rate) \                    (in_rate < min_rate ? min_rate : \                    (in_rate > max_rate ? max_rate : in_rate))      /* don't init twice! */   if (true == sb.initialized)      return 0;   memset(&sb, 0, sizeof(sb));      if (sb_probe())      return -1;   /* try autoinit DMA first */   dma.autoinit = true;   sb.format = (uint8) *format;   /* determine which SB model we have, and act accordingly */   if (sb.dsp_version < DSP_VERSION_SB_15)   {      /* SB 1.0 */      sb.sample_rate = CLAMP_RATE(*sample_rate, 4000, 22050);      sb.format &= ~(SB_FORMAT_16BIT | SB_FORMAT_STEREO);      dma.autoinit = false;   }   else if (sb.dsp_version < DSP_VERSION_SB_20)   {      /* SB 1.5 */      sb.sample_rate = CLAMP_RATE(*sample_rate, 5000, 22050);      sb.format &= ~(SB_FORMAT_16BIT | SB_FORMAT_STEREO);   }   else if (sb.dsp_version < DSP_VERSION_SB_PRO)   {      /* SB 2.0 */      sb.sample_rate = CLAMP_RATE(*sample_rate, 5000, 44100);      sb.format &= ~(SB_FORMAT_16BIT | SB_FORMAT_STEREO);   }   else if (sb.dsp_version < DSP_VERSION_SB16)   {      /* SB Pro */      if (sb.format & SB_FORMAT_STEREO)         sb.sample_rate = CLAMP_RATE(*sample_rate, 5000, 22050);      else         sb.sample_rate = CLAMP_RATE(*sample_rate, 5000, 44100);      sb.format &= ~SB_FORMAT_16BIT;   }   else   {      /* SB 16 */      sb.sample_rate = CLAMP_RATE(*sample_rate, 5000, 44100);   }   /* sanity check for 16-bit */   if ((sb.format & SB_FORMAT_16BIT) && ((uint8) INVALID == sb.dma16))   {      sb.format &= ~SB_FORMAT_16BIT;      thin_printf("thin@sb: 16-bit DMA channel not available, dropping to 8-bit\n");   }   /* clamp buffer size to something sane */   if ((uint16) *buf_size > sb.sample_rate)   {      *buf_size = sb.sample_rate;      thin_printf("thin@sb: buffer size too big, dropping to %d bytes\n", *buf_size);   }   /* allocate buffer / DOS memory */   if (sb_allocate_buffers(*buf_size))   {      thin_printf("thin@sb: failed allocating sound buffers\n");      return -1;   }   /* set the new IRQ vector! */   sb_setisr();   sb.initialized = true;   /* return the actual values */   *sample_rate = sb.sample_rate;   *buf_size = sb.buf_size;   *format = sb.format;   return 0;}void thin_sb_stop(void){   if (true == sb.initialized)   {      if (sb.format & SB_FORMAT_16BIT)      {         dsp_write(DSP_DMA_PAUSE_16BIT);  /* pause 16-bit DMA */         dsp_write(DSP_DMA_STOP_8BIT);         dsp_write(DSP_DMA_PAUSE_16BIT);      }      else      {         dsp_write(DSP_DMA_PAUSE_8BIT);  /* pause 8-bit DMA */         dsp_write(DSP_SPEAKER_OFF);      }   }}/* return time constant for older sound bastards */static uint8 get_time_constant(int rate){   return ((65536 - (256000000L / rate)) / 256);}static void init_samplerate(int rate){   if ((sb.format & SB_FORMAT_16BIT) || sb.dsp_version >= DSP_VERSION_SB16)   {      dsp_write(DSP_DMA_DAC_RATE);      dsp_write(HIGH_BYTE(rate));      dsp_write(LOW_BYTE(rate));   }   else   {      dsp_write(DSP_DMA_TIME_CONST);      dsp_write(get_time_constant(rate));   }}/* set the sample rate */void thin_sb_setrate(int rate){   if (sb.format & SB_FORMAT_16BIT)   {      dsp_write(DSP_DMA_PAUSE_16BIT);  /* pause 16-bit DMA */      init_samplerate(rate);      dsp_write(DSP_DMA_CONT_16BIT);   /* continue 16-bit DMA */   }   else   {      dsp_write(DSP_DMA_PAUSE_8BIT);   /* pause 8-bit DMA */      init_samplerate(rate);      dsp_write(DSP_DMA_CONT_8BIT);    /* continue 8-bit DMA */   }   sb.sample_rate = rate;}/* start SB DMA transfer */static void start_transfer(void){   uint8 dma_mode, start_command, mode_command;   int dma_length;   dma.count = 0;   dma_length = sb.buf_size * 2;   if (true == dma.autoinit)   {      start_command = DSP_DMA_DAC_MODE;   /* autoinit DMA */      dma_mode = DMA_AUTOINIT_MODE;   }   else   {      start_command = 0;      dma_mode = DMA_ONESHOT_MODE;   }   /* things get a little bit nasty here, look out */   if (sb.format & SB_FORMAT_16BIT)   {      uint8 dma_base = sb.dma16 - 4;      dma_mode |= dma_base;       start_command |= DSP_DMA_START_16BIT;      mode_command = DSP_DMA_SIGNED;      outportb(DMA_MASKPORT_16BIT, DMA_STOPMASK_BASE | dma_base);      outportb(DMA_MODEPORT_16BIT, dma_mode);      outportb(DMA_CLRPTRPORT_16BIT, 0x00);      outportb(DMA_ADDRBASE_16BIT + (4 * dma_base), LOW_BYTE(dos.offset));      outportb(DMA_ADDRBASE_16BIT + (4 * dma_base), HIGH_BYTE(dos.offset));      outportb(DMA_COUNTBASE_16BIT + (4 * dma_base), LOW_BYTE(dma_length - 1));      outportb(DMA_COUNTBASE_16BIT + (4 * dma_base), HIGH_BYTE(dma_length - 1));      outportb(dma16_ports[dma_base], dos.page);      outportb(DMA_MASKPORT_16BIT, DMA_STARTMASK_BASE | dma_base);   }   else   {      dma_mode |= sb.dma;      start_command |= DSP_DMA_START_8BIT;      mode_command = DSP_DMA_UNSIGNED;      outportb(DMA_MASKPORT_8BIT, DMA_STOPMASK_BASE + sb.dma);      outportb(DMA_MODEPORT_8BIT, dma_mode);      outportb(DMA_CLRPTRPORT_8BIT, 0x00);      outportb(DMA_ADDRBASE_8BIT + (2 * sb.dma), LOW_BYTE(dos.offset));      outportb(DMA_ADDRBASE_8BIT + (2 * sb.dma), HIGH_BYTE(dos.offset));      outportb(DMA_COUNTBASE_8BIT + (2 * sb.dma), LOW_BYTE(dma_length - 1));      outportb(DMA_COUNTBASE_8BIT + (2 * sb.dma), HIGH_BYTE(dma_length - 1));      outportb(dma8_ports[sb.dma], dos.page);      outportb(DMA_MASKPORT_8BIT, DMA_STARTMASK_BASE + sb.dma);   }   /* check stereo */   if (sb.format & SB_FORMAT_STEREO)      mode_command |= DSP_DMA_STEREO;   else      mode_command |= DSP_DMA_MONO;   init_samplerate(sb.sample_rate);   /* start things going */   if ((sb.format & SB_FORMAT_16BIT) || sb.dsp_version >= DSP_VERSION_SB16)   {      dsp_write(start_command);      dsp_write(mode_command);      dsp_write(LOW_BYTE(sb.buf_size - 1));      dsp_write(HIGH_BYTE(sb.buf_size - 1));   }   else   {      /* turn on speaker */      dsp_write(DSP_SPEAKER_ON);      if (true == dma.autoinit)      {         dsp_write(DSP_DMA_BLOCK_SIZE);  /* set buffer size */         dsp_write(LOW_BYTE(sb.buf_size - 1));         dsp_write(HIGH_BYTE(sb.buf_size - 1));         if (sb.dsp_version < DSP_VERSION_SB_20)            dsp_write(DSP_DMA_DAC_AI_8BIT); /* low speed autoinit */         else            dsp_write(DSP_DMA_DAC_HS_8BIT);      }      else      {         dsp_write(DSP_DMA_DAC_8BIT);         dsp_write(LOW_BYTE(sb.buf_size - 1));         dsp_write(HIGH_BYTE(sb.buf_size - 1));      }   }}/* start playing the output buffer */int thin_sb_start(sbmix_t fillbuf){   clock_t count;   int projected_dmacount;   /* make sure we really should be here... */   if (false == sb.initialized || NULL == fillbuf)      return -1;   /* stop any current processing */   thin_sb_stop();   /* set the callback routine */   sb.callback = fillbuf;   /* calculate how many DMAs we should have in one second    ** and scale it down just a tad   */   projected_dmacount = (int) ((0.8 * sb.sample_rate) / sb.buf_size);   if (projected_dmacount < 1)      projected_dmacount = 1;   /* get the transfer going, so we can ensure interrupts are firing */   start_transfer();   count = clock();   while ((clock() - count) < CLOCKS_PER_SEC && dma.count < projected_dmacount)	; /* spin */   if (dma.count < projected_dmacount)   {      if (true == dma.autoinit)      {         thin_printf("thin@sb: Autoinit DMA failed, trying one-shot mode.\n");         dsp_reset();         dma.autoinit = false;         dma.count = 0;         return (thin_sb_start(fillbuf));      }      else      {         thin_printf("thin@sb: One-shot DMA mode failed, sound will not be heard.\n");         thin_printf("thin@sb: DSP version: %d.%d baseio: %X IRQ: %d DMA: %d High: %d\n",                     sb.dsp_version >> 8, sb.dsp_version & 0xFF,                     sb.baseio, sb.irq, sb.dma, sb.dma16);         return -1;      }   }   return 0;}/*** $Log: tl_sb.c,v $** Revision 1.11  2001/03/12 06:06:55  matt** better keyboard driver, support for bit depths other than 8bpp**** Revision 1.10  2001/02/19 03:38:32  matt** stereo buffer overrun**** Revision 1.9  2001/02/01 06:28:26  matt** thinlib now works under NT/2000**** Revision 1.8  2001/01/15 05:25:52  matt** i hate near pointers**** Revision 1.7  2000/12/17 21:49:24  matt** whose idea was it to have functions returning bool all over the place?**** Revision 1.6  2000/12/16 21:18:11  matt** thinlib cleanups**** Revision 1.5  2000/12/13 14:14:27  matt** DJGPP_USE_NEARPTR -> THINLIB_NEARPTR**** Revision 1.4  2000/12/11 12:32:25  matt** buffer allocation size miscalculation**** Revision 1.3  2000/11/25 20:27:48  matt** typo**** Revision 1.2  2000/11/05 16:32:36  matt** thinlib round 2**** Revision 1.1  2000/11/05 06:29:03  matt** initial revision***/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -