-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 001d590
Showing
33 changed files
with
7,616 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,248 @@ | ||
/****************************************************************************** | ||
*File: dig.c | ||
*Copyright: 1995 DiamondWare, Ltd. All rights reserved. | ||
*Written: Erik Lorenzen & Keith Weiner | ||
*Purpose: To control SB dig | ||
*Notes: This code will only handle IRQ's 2, 3, 5, and 7 (1st PIC) | ||
*****************************************************************************/ | ||
|
||
|
||
|
||
#pragma check_stack(off) | ||
|
||
|
||
|
||
#include <stdio.h> | ||
#include <conio.h> | ||
#include <dos.h> | ||
|
||
#include "sound.h" | ||
#include "env.h" | ||
#include "dig.h" | ||
#include "sb.h" | ||
#include "dma.h" | ||
|
||
|
||
|
||
#define dig_EOI 0x20 | ||
#define dig_PICPORT 0x20 | ||
#define dig_IMRPORT 0x21 | ||
|
||
#define dig_NUMSOUNDS 0x10 | ||
|
||
#define dig_SAMPLERATE 11000 //reasonable number for a .WAV | ||
|
||
#define dig_BUFFSIZE 256 | ||
#define dig_ALLOCSIZE (dig_BUFFSIZE * 2 + 16) //Minimum size buffer | ||
//needed to guarantee finding | ||
//suitable DMA buffer | ||
|
||
//INTERRUPT REQUEST NUMBER #0 #1 #2 #3 #4 #5 #6 #7 | ||
static BYTE intnum[8] = {0x00, 0x00, 0x0a, 0x0b, 0x00, 0x0d, 0x00, 0x0f}; | ||
static BYTE onmask[8] = {0x00, 0x00, 0xfb, 0xf7, 0x00, 0xdf, 0x00, 0x7f}; | ||
|
||
|
||
static INT8 unadjustedbuffer[dig_ALLOCSIZE]; | ||
static INT8 *buffer; | ||
|
||
static void (_interrupt *oldisr)(); | ||
static BYTE old_imr; | ||
|
||
static WORD sb_base; | ||
static BYTE sb_irq; | ||
static BYTE sb_dma; | ||
|
||
static volatile INT8 numsnds; | ||
static volatile INT8 *sndptr[dig_NUMSOUNDS]; | ||
static volatile DWORD sndlen[dig_NUMSOUNDS]; | ||
|
||
|
||
|
||
static INT8 *BuffAdjust(INT8 *somebuffer) | ||
{ | ||
DWORD x, ptr, page1, page2, off, seg; | ||
|
||
for (x=0;x<=(dig_BUFFSIZE);x++) //check to make sure that we | ||
{ //have a buffer w/o a page break | ||
ptr = (DWORD)(somebuffer + x); | ||
|
||
off = (*((WORD *)&(ptr))); //break the ptr up into segment | ||
seg = (*((WORD *)&(ptr)+1)); //and offset | ||
|
||
printf(""); //work-around for Watcom 10 bug!!! | ||
//as per KW. | ||
seg <<= 4; | ||
|
||
page1 = seg + off; //calculate physical address | ||
page1 >>= 16; //shift right by 16 to get page | ||
//number of begining of buffer | ||
off += (dig_BUFFSIZE); | ||
page2 = seg + off; //do it again ,but this time for | ||
page2 >>= 16; //the end of the buffer | ||
|
||
if (page1 == page2) //if the begining and end of the | ||
{ //buffer are in the same 64k | ||
return ((INT8 *)ptr); //page we have our address | ||
} | ||
} | ||
|
||
//printf("\n\nFatal horrible error!!"); //we shouldn't get here | ||
//printf("\nUnable to find buffer without page break?"); | ||
return(NULL); | ||
} | ||
|
||
|
||
static void IntOn(BYTE irqlevel) | ||
{ | ||
BYTE temp; | ||
|
||
temp = (BYTE)inp(dig_IMRPORT); //read the IMR (Interrupt Mask Reg) | ||
old_imr = temp; //save IMR for later. | ||
temp &= onmask[irqlevel]; //make sure to reset our bit | ||
outp(dig_IMRPORT, temp); //write the new IMR | ||
} | ||
|
||
|
||
static void IntOff(BYTE irqlevel) | ||
{ | ||
int temp; | ||
|
||
old_imr |= onmask[irqlevel]; //by ORing & XORing we leave only | ||
old_imr ^= onmask[irqlevel]; //the bit we have used untouched | ||
|
||
temp = inp(dig_IMRPORT); //read the IMR again | ||
|
||
temp |= old_imr; //make sure our channel is left in the | ||
//state we found it in. | ||
outp(dig_IMRPORT, temp); //write the new IMR | ||
} | ||
|
||
|
||
static void _interrupt SBISR(void) | ||
{ | ||
WORD smpnum; | ||
INT8 sound; | ||
INT8 x; | ||
INT16 temp; | ||
|
||
for (smpnum=0;smpnum<dig_BUFFSIZE;smpnum++) | ||
{ | ||
temp = 0x80; //reset the accumulator | ||
|
||
for (sound=0;sound<numsnds;sound++) | ||
{ | ||
temp += (INT16)*(sndptr[sound]++);//add a sample from all active voices | ||
sndlen[sound]--; //decrease sound len by one sample | ||
|
||
if (!sndlen[sound]) //if length is 0, the sound is done | ||
{ | ||
for (x=sound;x<numsnds;x++) //get rid of it | ||
{ | ||
sndptr[x] = sndptr[x + 1]; | ||
sndlen[x] = sndlen[x + 1]; | ||
} | ||
|
||
numsnds--; | ||
} | ||
} | ||
|
||
if (temp < 0) //clip the accumulator if out of range | ||
{ | ||
temp = 0; | ||
} | ||
else if (temp > 0xff) | ||
{ | ||
temp = 0xff; | ||
} | ||
|
||
buffer[smpnum] = (INT8)temp; //write data to the buffer | ||
} | ||
|
||
inp(sb_base+sb_ACKIRQ); //clear the IRQ from the SB | ||
outp(dig_PICPORT, dig_EOI); //send EOI to pic | ||
} | ||
|
||
|
||
static void Hook(BYTE irqlevel) | ||
{ | ||
/* Save the old vector and give our ISR control */ | ||
oldisr = _dos_getvect(intnum[irqlevel]); | ||
_dos_setvect((WORD)intnum[irqlevel], SBISR); | ||
} | ||
|
||
|
||
static void UnHook(BYTE irqlevel) | ||
{ | ||
/* Restore control to the old ISR */ | ||
_dos_setvect((WORD)intnum[irqlevel], oldisr); | ||
} | ||
|
||
|
||
void dig_Play(SOUND *sound) | ||
{ | ||
BYTE x; | ||
|
||
if (numsnds >= dig_NUMSOUNDS) | ||
{ | ||
for (x=0;x<dig_NUMSOUNDS;x++) | ||
{ | ||
sndptr[x] = sndptr[x + 1]; | ||
sndlen[x] = sndlen[x + 1]; | ||
} | ||
|
||
numsnds--; | ||
} | ||
|
||
sndptr[numsnds] = sound->samples; | ||
sndlen[numsnds] = sound->length; | ||
|
||
numsnds++; | ||
} | ||
|
||
|
||
INT8 dig_Init(env_BLASTER *blaster) | ||
{ | ||
WORD x; | ||
|
||
numsnds = 0; | ||
|
||
sb_dma = blaster->dmachan; | ||
sb_base = blaster->ioaddr; //setup globals right away | ||
sb_irq = blaster->irqlev; //some are needed in the ISR | ||
|
||
if ((buffer = BuffAdjust(unadjustedbuffer)) == NULL) | ||
{ | ||
return (0); | ||
} | ||
|
||
for (x=0;x<dig_BUFFSIZE;x++) //init buffer so we don't get an extra pop | ||
{ //on startup | ||
buffer[x] = (INT8)0x80; | ||
} | ||
|
||
if (!sb_Reset(sb_base)) //reset SB, insure the DSP is in its default | ||
{ //state and make sure the DSP is really there. | ||
//printf("No Sound Blaster found.\n"); //init didn't find a DSP at the port | ||
return (0); //fail! | ||
} | ||
|
||
Hook(sb_irq); //hook our interrupt vector | ||
IntOn(sb_irq); //turn our IRQ on at PIC | ||
|
||
sb_DacSpkrOn(sb_base); //make sure we hear the sounds | ||
dma_ProgramChan(sb_dma, buffer, dig_BUFFSIZE); | ||
sb_Speed(sb_base, dig_SAMPLERATE, 1); | ||
sb_Play(sb_base, dig_BUFFSIZE);//send the DSP commands to start playing | ||
|
||
return (1); //success! | ||
} | ||
|
||
|
||
void dig_Kill(void) | ||
{ | ||
sb_DacSpkrOff(sb_base); | ||
dma_ChanOff(sb_dma); //disable our DMA channel | ||
IntOff(sb_irq); //mask (disable) our IRQ at PIC | ||
UnHook(sb_irq); //unhook our interrupt vector | ||
sb_Reset(sb_base); //leave the SB in a known "good" state | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/****************************************************************************** | ||
*File: dig.h | ||
*Copyright: 1995 DiamondWare, Ltd. All rights reserved. | ||
*Written: Erik Lorenzen & Keith Weiner | ||
*Purpose: Declares prototypes and structs for DIG | ||
******************************************************************************/ | ||
|
||
|
||
|
||
INT8 dig_Init(env_BLASTER *blaster); | ||
|
||
void dig_Kill(void); | ||
|
||
|
||
void dig_Play(SOUND *sound); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/****************************************************************************** | ||
*File: dma.c | ||
*Copyright: 1995 DiamondWare, Ltd. All rights reserved. | ||
*Written: Erik Lorenzen & Keith Weiner | ||
*Purpose: Contains code to manage DMA controller | ||
*Note: This code requires an AT-Class machine or higher! | ||
* This code will handle all DMA channels | ||
******************************************************************************/ | ||
|
||
|
||
|
||
#include <conio.h> | ||
#include <dos.h> | ||
|
||
#include "sound.h" | ||
#include "dma.h" | ||
|
||
|
||
|
||
/* masks for use in controlling the DMA chip */ | ||
/* DMA CHANNEL #0 #1 #2 #3 #4 #5 #6 #7 */ | ||
static BYTE dma_on[8] = {0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03}; | ||
static BYTE dma_off[8] = {0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07}; | ||
static BYTE dma_mode[8] = {0x58, 0x59, 0x5a, 0x5b, 0x58, 0x59, 0x5a, 0x5b}; | ||
|
||
/* DMA controller ports */ | ||
static BYTE dma_page[8] = {0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a}; | ||
static BYTE dma_bnca[8] = {0x00, 0x02, 0x04, 0x06, 0xc0, 0xc4, 0xc8, 0xcc}; | ||
static BYTE dma_bncc[8] = {0x01, 0x03, 0x05, 0x07, 0xc2, 0xc6, 0xca, 0xce}; | ||
static BYTE dma_maskreg[8] = {0x0a, 0x0a, 0x0a, 0x0a, 0xd4, 0xd4, 0xd4, 0xd4}; | ||
static BYTE dma_modereg[8] = {0x0b, 0x0b, 0x0b, 0x0b, 0xd6, 0xd6, 0xd6, 0xd6}; | ||
static BYTE dma_flipflop[8] = {0x0c, 0x0c, 0x0c, 0x0c, 0xd8, 0xd8, 0xd8, 0xd8}; | ||
|
||
|
||
|
||
void dma_ChanOff(BYTE chan) | ||
{ | ||
outp(dma_maskreg[chan], dma_off[chan]); //disable DMA channel | ||
} | ||
|
||
|
||
void dma_ProgramChan(BYTE chan, INT8 *sound, WORD numsamps) | ||
{ | ||
DWORD padd; | ||
DWORD page; | ||
DWORD off; | ||
DWORD seg; | ||
|
||
_disable(); //disable interrupts | ||
|
||
outp(dma_maskreg[chan], dma_off[chan]); //disable DMA channel | ||
//before programming | ||
outp(dma_flipflop[chan], 0x00); //reset flip-flop | ||
|
||
outp(dma_modereg[chan], dma_mode[chan]); //set DMA mode | ||
|
||
off = (*((WORD *)&(sound))); | ||
seg = (*((WORD *)&(sound) + 1)); | ||
seg <<= 4; | ||
|
||
padd = seg + off; //calc physical address | ||
page = padd >> 16; //calc page number | ||
|
||
outp(dma_bnca[chan], (BYTE)(padd)); | ||
outp(dma_bnca[chan], (BYTE)(padd >> 8)); | ||
outp(dma_page[chan], (BYTE)page); | ||
|
||
numsamps--; //DMA cntrlr expects 1 less | ||
outp(dma_bncc[chan], (BYTE)(numsamps & 0x00ff)); //low byte | ||
outp(dma_bncc[chan], (BYTE)(numsamps >> 8)); //high byte | ||
|
||
outp(dma_maskreg[chan], dma_on[chan]); //enable DMA channel | ||
|
||
_enable(); //re-enable interrupts | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/****************************************************************************** | ||
*File: dma.h | ||
*Copyright: 1995 DiamondWare, Ltd. All rights reserved. | ||
*Written: Erik Lorenzen & Keith Weiner | ||
*Purpose: Declares prototypes for DMA | ||
******************************************************************************/ | ||
|
||
|
||
|
||
void dma_ProgramChan(BYTE chan, INT8 *sound, WORD numsamps); | ||
void dma_ChanOff(BYTE chan); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef __DOSTIME_H | ||
#define __DOSTIME_H | ||
|
||
#pragma library(utils); | ||
|
||
// Get the DOS tick count. Returns 1/18ths since midnight | ||
long cdecl GetDosTicks(void); | ||
|
||
#endif | ||
|
||
|
Oops, something went wrong.