📄 snd.h
字号:
#include <stdio.h>
#include <i86.h>
#include <dos.h>
#include <conio.h>
#include <mem.h>
#include "dma.h"
short lk_sb_irq=-1, lk_sb_dma=-1;
short lk_sb_stereo=0, lk_sb_16bit=0;
char snd_init(short addr,short irq,short dma);
void snd_rest();
void _isr();
void snd_play(Voc *buf,int sample);
Voc *load_voc(char *file);
int flen=0;
///////////////////////////////////////////////////////////////////////////
struct
{ long phy;
short size;
short selector;
char *data;
} dma_buf[2];
struct
{ int sample;
unsigned long len_to_play;
char *data_to_play;
} snd_buf;
extern short lk_sb_stereo, lk_sb_16bit;
short IntNumbers[] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 };
long int lk_dma_mix_size;
//long lk_dma_size=0x10000/8;
unsigned short lk_dma_size=32767;
#define BUFSIZE lk_dma_size
int lk_sb_freq=-1;
int sb_bufnum=0;
int sb_init_flag=0;
char snd_playing=0;
char snd_create_buffers(int size,int block);
void snd_release_buffers();
void set_isr();
void rest_isr();
void snd_stop();
void interrupt interrupt_isr();
void interrupt far (*old_interrupt)()=NULL;
void snd_play_buffer(char buf,unsigned short size,int sampleRate);
///////////////////////////////////////////////////////
char snd_create_buffers(int size,int block)
{ int first_size;
char i;
if (size<16384L) size=16384L;
if (block==1) first_size=size*2; else first_size=size;
i=grp_dma_alloc(first_size,&dma_buf[0].phy,&dma_buf[0].selector);
if (i) { dma_buf[0].phy=0; return 1; }
dma_buf[0].size=first_size; dma_buf[0].data=(char*)dma_buf[0].phy;
if (block==2)
{ i=grp_dma_alloc(size,&dma_buf[1].phy,&dma_buf[1].selector);
if (i) {
grp_dma_free(size,dma_buf[0].phy,dma_buf[0].selector);
dma_buf[0].phy=dma_buf[1].phy=0;
} dma_buf[1].size=size; dma_buf[1].data=(char*)dma_buf[1].phy;
}
else {
dma_buf[1].data=dma_buf[0].data+size;
dma_buf[1].phy=dma_buf[0].phy+size;
dma_buf[1].size=0; dma_buf[1].selector=dma_buf[0].selector;
}
return 0;
}
void snd_release_buffers()
{ int i;
for (i=0;i<2;i++) if (dma_buf[i].phy&&dma_buf[i].size>0) {
grp_dma_free(dma_buf[i].size,dma_buf[i].phy,dma_buf[i].selector);
dma_buf[i].phy=dma_buf[i].size=0;
}
}
char snd_init(short addr,short irq,short dma)
{ short dma8,dma16;
int block=2;
timer_init();
if (sb_init_flag) return 0;
if (addr<0||irq<0||dma<0) {
GetBlasterEnv(&addr,&dma8,&dma16,&irq);
dma=dma8;
}
if (addr<0||irq<0||dma<0) return -1;
lk_sb_port=addr; lk_sb_dma=dma; lk_sb_irq=irq;
if (ResetDsp(1)) return -2;
if (snd_create_buffers(lk_dma_size,block)) return -3;
set_isr();
WritePortC(0xd1);
sb_init_flag=1;
atexit(snd_rest);
return 0;
}
void snd_rest()
{ if (sb_init_flag==0) return ;
snd_stop();
rest_isr();
snd_release_buffers();
WritePortC(0xd3);
}
#define PIC1MODE 0x20 // for irq 0 - 7
#define PIC1MASK 0x21
#define PIC2MODE 0xA0 // for irq 8 - 15
#define PIC2MASK 0xA1
#define PICEOI 0x20 // End Of Interrupt
void set_isr()
{ int Intr_num;
int Intr_mask;
if (old_interrupt!=NULL) return ;
Intr_num = IntNumbers[lk_sb_irq];
Intr_mask = 1 << lk_sb_irq;
old_interrupt=_dos_getvect(Intr_num);
_disable();
_dos_setvect(Intr_num,interrupt_isr);
_enable();
outp(PIC1MASK, inp(PIC1MASK) & ~Intr_mask);
outp(PIC2MASK, inp(PIC2MASK) & ~(Intr_mask >> 8));
}
void rest_isr()
{ int Intr_num;
int Intr_mask;
if (old_interrupt==NULL) return ;
Intr_num = IntNumbers[lk_sb_irq];
Intr_mask = 1 << lk_sb_irq;
outp(PIC1MASK, inp(PIC1MASK) | Intr_mask);
outp(PIC2MASK, inp(PIC2MASK) | (Intr_mask >> 8));
#ifdef TEST
remove_int(_isr);
#endif
_disable();
_dos_setvect(Intr_num,old_interrupt);
_enable();
old_interrupt=NULL;
}
///////////////////////////////////////////////////////
void snd_sample_rate(unsigned int rate)
{ WritePortC(0x40);
WritePortC((unsigned char)(256-1000000/rate));
}
void snd_play_buffer(int size)
{ WritePortC(0x14);
WritePortC((size-1) & 0xFF);
WritePortC((size-1) >> 8);
}
void snd_play_buffer(char buf,unsigned short size, int sampleRate)
{
if (dma_buf[buf].phy==0)return;
snd_sample_rate(sampleRate);
if (size>dma_buf[buf].size) size=dma_buf[buf].size;
sb_bufnum=buf;
grp_dma_start(lk_sb_dma,dma_buf[buf].phy,size,0,0);
snd_play_buffer(size);
}
///////////////////////////////////////////////////////////////////////////
void snd_playA()
{ memset(dma_buf[0].data,0,lk_dma_size);
snd_play_buffer(0,1,snd_buf.sample);
WritePortC(0xd1);
}
void snd_stop()
{ResetDsp(1);
}
void snd_play(Voc *buf,int sample)
{
snd_buf.sample=sample;
if(buf->size>lk_dma_size)
snd_buf.len_to_play=lk_dma_size;
else
snd_buf.len_to_play=buf->size;
snd_buf.data_to_play=buf->dat;
buf->same=sample;
#ifdef TEST
install_int(_isr,4000);
#endif
memset(dma_buf[0].data,0,lk_dma_size);
snd_play_buffer(0,1,sample);
WritePortC(0xd1);
}
///////////////////////////////////////////////////////
void _isr()
{
if(flen>0&&snd_playing)
{
if(flen-lk_dma_size>0)
{
flen-=lk_dma_size;
snd_buf.len_to_play=lk_dma_size;
}
else
{
snd_buf.len_to_play=flen;
}
ResetDsp(1);
snd_playA();
snd_playing=0;
}
}
void interrupt interrupt_isr()
{ int len;
char cont=1;
len=snd_buf.len_to_play;
if (len>lk_dma_size) len=lk_dma_size;
if(snd_buf.len_to_play==0||len==0||snd_buf.data_to_play==NULL)cont=0;
snd_playing=1;
if (cont) {
snd_playing=0;
sb_bufnum = 1 - sb_bufnum;
memcpy(dma_buf[sb_bufnum].data,snd_buf.data_to_play,len);
grp_dma_start(lk_sb_dma, dma_buf[sb_bufnum].phy, lk_dma_size, FALSE, FALSE);
snd_buf.len_to_play-=len;
snd_buf.data_to_play+=len;
snd_play_buffer(sb_bufnum,len,snd_buf.sample);
snd_playing=1;
}
outp(0x20, 0x20);
}
Voc *load_voc(char *file)
{FILE *fp;
int len;
Voc *voc=new Voc;
if((fp=fopen(file,"rb"))==NULL){
sprintf(grp_err,"Load Voc File %s Error.",file);
return FALSE;
}
fseek(fp,0L,SEEK_END);
len=ftell(fp)-27;
flen=len;
if(flen>lk_dma_size)flen-=lk_dma_size;
voc->size=len;
rewind(fp);
voc->dat=new char [len];
if(voc->dat==NULL){
sprintf(grp_err,"Malloc Snd System memony Error.");return FALSE;
}
fseek(fp,27L,SEEK_SET);
fread(voc->dat,1,len,fp);
fclose(fp);
return voc;
}
void destroy_voc(Voc *voc)
{if(voc!=NULL)
{ if(voc->dat!=NULL)delete []voc->dat;
delete voc;
}
}
short AutoDetect()
{ short found=0, i=10, b;
static detect=0;
if (detect) return lk_sb_port;
for (lk_sb_port=0x210;lk_sb_port<=0x260&&!found;)
{ outp(lk_sb_port+0x6,1);
delay(3); for (b=3;b>=0;b--);
outp(lk_sb_port+0x06,0);
for (b=50;b>0&&inp(lk_sb_port+0x0e)<128;b--);
if ((b==0)||inp(lk_sb_port+0x0a)!=0xaa)
{ i--;
if (!i); {i=10; lk_sb_port+=0x10; }
}
else { found=1; detect=1; }
}
return ((found==1)?lk_sb_port:0);
}
short ResetDsp(short data)
{ int x;
outp(0x06+lk_sb_port, data);
for (x=0; x<8; x++) inp(0x06+lk_sb_port);
outp(0x06+lk_sb_port, 0);
if (ReadPortC() != 0xAA) return -1;
return 0;
}
short GetBlasterEnv(short *_sb_port,short *_sb_dma8,short *_sb_dma16,short *_sb_irq)
{ char *blaster=getenv("BLASTER");
*_sb_port=*_sb_dma8=*_sb_dma16=*_sb_irq=-1;
if (blaster) {
while (*blaster) {
while ((*blaster == ' ') || (*blaster == '\t'))
blaster++;
if (*blaster) {
switch (*blaster) {
case 'a': case 'A':
*_sb_port = strtol(blaster+1, NULL, 16);
break;
case 'i': case 'I':
*_sb_irq = strtol(blaster+1, NULL, 10);
break;
case 'd': case 'D':
*_sb_dma8 = strtol(blaster+1, NULL, 10);
break;
case 'h': case 'H':
*_sb_dma16 = strtol(blaster+1, NULL, 10);
break;
}
while ((*blaster) && (*blaster != ' ') && (*blaster != '\t'))
blaster++;
}
}
return 1;
}
return 0;
}
char WritePortC(unsigned char value)
{ int i;
for (i=0;i<0xffff ;i++ )
{ if (!(inp(0x0C+lk_sb_port) & 0x80)) {
outp(lk_sb_port+0x0c,value);
return 0;
}
} return -1;
}
unsigned char ReadPortC()
{ short b;
for (b=50;b>0&&inp(lk_sb_port+0x0e)<128;b--);
return inp(lk_sb_port+0x0a);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -