home *** CD-ROM | disk | FTP | other *** search
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * DOS Sound interface
- *
- * (c) 1996 Gustavo Goedert
- */
-
- #include <go32.h>
- #include <dpmi.h>
- #include <pc.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- int DetectInitSound(int *bits, int *rate, int *bufsize);
- int SB_DetectInitSound(int *bits, int *rate, int *bufsize);
- void (*PlaySample)(void *buffer);
-
- int DetectInitSound(int *bits, int *rate, int *bufsize) {
- return(SB_DetectInitSound(bits, rate, bufsize));
- }
-
- /*
- * Sound Blaster Interface
- */
-
- int SB_BufferSize = -1;
- int SB_Port = -1;
- int SB_Irq = -1;
- int SB_Dma = -1;
- volatile int SB_IsPlaying = 0;
- unsigned int SB_BufAddr[2];
- int SB_BufNum = 0;
- _go32_dpmi_seginfo SB_OldIrq, SB_NewIrq, SB_Buf[2];
-
- void SB_MyHandler(void);
- int SB_AllocateBuffer(int num);
- inline void SB_WriteDSP(char data);
- inline unsigned char SB_ReadDSP(void);
- void SB_Exit(void);
- void SB_PlaySample(void *buffer);
-
- int SB_DetectInitSound(int *bits, int *rate, int *bufsize) {
- char *SB_Env, *tmp;
- unsigned char SB_Pic1, SB_Pic2;
- int i;
-
- *bits = 8;
- *rate = 22050;
- if ((*bufsize) > 65536)
- *bufsize = 65536;
- if ((*bufsize) < 4)
- *bufsize = 4;
- *bufsize = ((*bufsize)>>2)<<2;
- SB_BufferSize = *bufsize;
- /* Get SB parameters */
- SB_Env = getenv("BLASTER");
- do {
- tmp = strchr(SB_Env, ' ');
- if (tmp!=NULL) {
- *tmp = '\0';
- tmp++;
- }
- switch (*SB_Env) {
- case 'a':
- case 'A':
- SB_Port = strtol(SB_Env + 1, NULL, 16);
- break;
- case 'i':
- case 'I':
- SB_Irq = atoi(SB_Env + 1);
- break;
- case 'd':
- case 'D':
- SB_Dma = atoi(SB_Env + 1);
- break;
- }
- SB_Env = tmp;
- } while(SB_Env != NULL);
- if ((SB_Port == -1) || (SB_Irq == -1) || (SB_Dma == -1))
- return(0);
- if (SB_Irq > 7) {
- fprintf(stderr, "Currently Sound Blaster IRQ must be either 5 or 7.\n");
- return(0);
- }
- if (SB_Dma != 1) {
- fprintf(stderr, "Currently Sound Blaster DMA must be equal to 1.\n");
- return(0);
- }
- /* Reset SB */
- inportb(SB_Port + 0x0A);
- outportb(SB_Port + 0x06, 1);
- inportb(SB_Port + 0x06);
- inportb(SB_Port + 0x06);
- inportb(SB_Port + 0x06);
- inportb(SB_Port + 0x06);
- outportb(SB_Port + 0x06, 0);
- for (i=0; i<100; i++) {
- if (inportb(SB_Port + 0x0E) & 0x08)
- if (inportb(SB_Port + 0x0A) == 0xAA)
- break;
- }
- if (i == 100)
- return(0);
- /* Install IRQ Handler */
- SB_NewIrq.pm_offset = (int)SB_MyHandler;
- _go32_dpmi_allocate_iret_wrapper(&SB_NewIrq);
- _go32_dpmi_get_protected_mode_interrupt_vector(SB_Irq + 8, &SB_OldIrq);
- _go32_dpmi_set_protected_mode_interrupt_vector(SB_Irq + 8, &SB_NewIrq);
- /* Alocate Buffers */
- if ((SB_AllocateBuffer(0) == 0) || (SB_AllocateBuffer(1) == 0))
- return(0);
- /* Enable interrupts on PIC */
- SB_Pic1 = inportb(0x21);
- SB_Pic2 = ~(1 << SB_Irq);
- outportb(0x21, SB_Pic1 & SB_Pic2);
- /* Set Sample Rate */
- inportb(SB_Port + 0x0E);
- SB_WriteDSP(0x40);
- SB_WriteDSP(256-(1000000/(*rate)));
- /* Turn Speaker On */
- SB_WriteDSP(0xd1);
- /* Register Cleanup Function */
- atexit(SB_Exit);
- /* Register Play Sample Function */
- PlaySample=SB_PlaySample;
- /* Lock Memory Touched by Handler */
- _go32_dpmi_lock_code(SB_MyHandler, (unsigned int)SB_AllocateBuffer-(unsigned int)SB_MyHandler);
- _go32_dpmi_lock_data(&SB_Port, sizeof(SB_Port));
- _go32_dpmi_lock_data(&SB_IsPlaying, sizeof(SB_IsPlaying));
- /* All ok */
- return(1);
- }
-
- void SB_MyHandler(void) {
- inportb(SB_Port + 0x0E);
- outportb(0x20, 0x20);
- SB_IsPlaying = 0;
- }
-
- int SB_AllocateBuffer(int num) {
- unsigned int Page;
-
- SB_Buf[num].size = SB_BufferSize >> 3;
- if (_go32_dpmi_allocate_dos_memory(&SB_Buf[num]))
- return(0);
- SB_BufAddr[num] = SB_Buf[num].rm_segment << 4;
- /* Force a don't cross 64k boundary */
- Page = SB_BufAddr[num] & 0xFFFF;
- if ((Page + SB_BufferSize) > 0xFFFF)
- SB_BufAddr[num] = (SB_BufAddr[num] - Page) + 0x10000;
- return(1);
- }
-
- inline void SB_WriteDSP(char data) {
- while(inportb(SB_Port + 0x0C) & 0x80);
- outportb(SB_Port + 0x0C, data);
- }
-
- inline unsigned char SB_ReadDSP(void) {
- while(!(inportb(SB_Port + 0x0E) & 0x80));
- return(inportb(SB_Port + 0x0A));
- }
-
- void SB_Exit(void) {
- /* Turn Speaker Off */
- SB_WriteDSP(0xD3);
- /* Stop any DMA transfer */
- SB_WriteDSP(0xD0);
- /* Free DOS memory */
- _go32_dpmi_free_dos_memory(&SB_Buf[0]);
- _go32_dpmi_free_dos_memory(&SB_Buf[1]);
- /* Restore old IRQ Handler */
- _go32_dpmi_set_protected_mode_interrupt_vector(SB_Irq + 8, &SB_OldIrq);
- }
-
- void SB_PlaySample(void *buffer) {
- unsigned int Size = SB_BufferSize - 1;
-
- asm ("
- push %%es
- cld
- movw %0, %%es
- shrl $2, %%ecx
- rep
- movsl
- pop %%es
- "
- :
- : "g" (_dos_ds),
- "S" (buffer), "D" (SB_BufAddr[SB_BufNum]), "c" (SB_BufferSize)
- : "%esi", "%edi", "%ecx", "cc"
- );
- /* Wait current sample stop playing */
- while(SB_IsPlaying);
- /* Start DMA */
- outportb(0x0A, 0x05);
- outportb(0x0C, 0x00);
- outportb(0x0B, 0x59);
- outportb(0x02, SB_BufAddr[SB_BufNum]);
- outportb(0x02, SB_BufAddr[SB_BufNum] >> 8);
- outportb(0x83, SB_BufAddr[SB_BufNum] >> 16);
- outportb(0x03, Size);
- outportb(0x03, Size >> 8);
- outportb(0x0A, 0x01);
- SB_WriteDSP(0x14);
- SB_WriteDSP(Size);
- SB_WriteDSP(Size >> 8);
- SB_IsPlaying = 1;
- SB_BufNum = !SB_BufNum;
- }
-