510 lines
12 KiB
C++
510 lines
12 KiB
C++
|
/************************************************************************
|
|||
|
* This program is free software; you can redistribute it and/or modify *
|
|||
|
* it under the terms of the GNU General Public License as published by *
|
|||
|
* the Free Software Foundation; either version 2 of the License, or *
|
|||
|
* (at your option) any later version. *
|
|||
|
************************************************************************/
|
|||
|
|
|||
|
// Nicoso<73>t Galactic Poly-Sounds Player Driver - (C)1997 Nicoso<73>t
|
|||
|
|
|||
|
#include <dos.h>
|
|||
|
#include "std.hpp"
|
|||
|
#include "3dsdriv.hpp"
|
|||
|
|
|||
|
// DSP Commands
|
|||
|
#define DSPC_SPEAKER_ON 0xd1
|
|||
|
#define DSPC_SPEAKER_OFF 0xd3
|
|||
|
#define DSPC_DMA_STOP 0xd0
|
|||
|
#define DSPC_DMA_CONTINUE 0xd4
|
|||
|
|
|||
|
// DSP I/O Ports
|
|||
|
#define DSP_MIXER_ADDR 0x04
|
|||
|
#define DSP_MIXER_DATA 0x05
|
|||
|
#define DSP_RESET 0x06
|
|||
|
#define DSP_READ_DATA 0x0a
|
|||
|
#define DSP_WRITE_DATA 0x0c
|
|||
|
#define DSP_WRITE_STATUS 0x0c
|
|||
|
#define DSP_DATA_AVAIL 0x0e
|
|||
|
|
|||
|
#define MIXER_IRQ_NR 0x80
|
|||
|
#define MIXER_DMA_NR 0x81
|
|||
|
#define MIXER_AGC_ON 0
|
|||
|
#define MIXER_AGC_OFF 1
|
|||
|
|
|||
|
// SB16 Mixer output defs
|
|||
|
#define MIX16_OUTPUT_LINE_LEFT 0x10
|
|||
|
#define MIX16_OUTPUT_LINE_RIGHT 0x08
|
|||
|
#define MIX16_OUTPUT_CD_LEFT 0x04
|
|||
|
#define MIX16_OUTPUT_CD_RIGHT 0x02
|
|||
|
#define MIX16_OUTPUT_LINE (MIX16_OUTPUT_LINE_LEFT | MIX16_OUTPUT_LINE_RIGHT)
|
|||
|
#define MIX16_OUTPUT_CD (MIX16_OUTPUT_CD_LEFT | MIX16_OUTPUT_CD_RIGHT)
|
|||
|
#define MIX16_OUTPUT_MIC 0x01
|
|||
|
#define MIX16_DEFAULT_OUTPUT (MIX16_OUTPUT_LINE)
|
|||
|
// SB16 Mixer input defs
|
|||
|
#define MIX16_INPUT_MIC_LEFT 0x01
|
|||
|
#define MIX16_INPUT_CD_LEFT 0x04
|
|||
|
#define MIX16_INPUT_LINE_LEFT 0x10
|
|||
|
#define MIX16_INPUT_MIDI_LEFT 0x40
|
|||
|
#define MIX16_DEFAULT_INPUT_LEFT (MIX16_INPUT_MIC_RIGHT|MIX16_INPUT_LINE_LEFT)
|
|||
|
#define MIX16_INPUT_MIC_RIGHT 0x01
|
|||
|
#define MIX16_INPUT_CD_RIGHT 0x02
|
|||
|
#define MIX16_INPUT_LINE_RIGHT 0x08
|
|||
|
#define MIX16_INPUT_MIDI_RIGHT 0x20
|
|||
|
#define MIX16_DEFAULT_INPUT_RIGHT (MIX16_INPUT_MIC_RIGHT|MIX16_INPUT_LINE_RIGHT)
|
|||
|
// SBPRO Mixer input defs
|
|||
|
#define MIXPRO_INPUT_MIC 0x11
|
|||
|
#define MIXPRO_INPUT_LINE 0x13
|
|||
|
#define MIXPRO_INPUT_CD 0x17
|
|||
|
/*
|
|||
|
#define DMA_VERIFY_TRANSFER_MODE 0x00
|
|||
|
#define DMA_WRITE_TRANSFER_MODE 0x04
|
|||
|
#define DMA_READ_TRANSFER_MODE 0x08
|
|||
|
#define DMA_AUTOINIT_MODE 0x10
|
|||
|
#define DMA_ADDRESS_DECREMENT_MODE 0x20
|
|||
|
#define DMA_ADDRESS_INCREMENT_MODE 0x00
|
|||
|
#define DMA_DEMAND_MODE 0x00
|
|||
|
#define DMA_SINGLE_MODE 0x40
|
|||
|
#define DMA_BLOCK_MODE 0x80
|
|||
|
#define DMA_CASCADE_MODE 0xc0
|
|||
|
*/
|
|||
|
typedef struct {
|
|||
|
byte left, right;
|
|||
|
} TMixIndxTab;
|
|||
|
|
|||
|
// SB1 Mixer table ???
|
|||
|
TMixIndxTab SB1tab[MIXER_DEVICE_NUM]={
|
|||
|
//Left Right
|
|||
|
{0x22,0x22}, //MIXER MASTER
|
|||
|
{0x00,0x00}, //MIXER_BASS
|
|||
|
{0x00,0x00}, //MIXER_TREBLE
|
|||
|
{0x26,0x26}, //MIXER_MIDI
|
|||
|
{0x04,0x04}, //MIXER_VOICE
|
|||
|
{0x00,0x00}, //MIXER_SPEAKER
|
|||
|
{0x2e,0x2e}, //MIXER_LINE
|
|||
|
{0x0a,0x00}, //MIXER_MIC
|
|||
|
{0x28,0x28}, //MIXER_CD
|
|||
|
{0x00,0x00}, //MIXER_IMIX
|
|||
|
{0x00,0x00}, //MIXER_ALTPCM
|
|||
|
{0x00,0x00}, //MIXER_AGC
|
|||
|
{0x00,0x00}, //MIXER_OUTPUTGAIN
|
|||
|
{0x00,0x00} //MIXER_INPUTGAIN
|
|||
|
};
|
|||
|
|
|||
|
// SBPro Mixer table
|
|||
|
TMixIndxTab SBPROtab[MIXER_DEVICE_NUM]={
|
|||
|
//Left Right
|
|||
|
{0x22,0x22}, //MIXER MASTER
|
|||
|
{0x00,0x00}, //MIXER_BASS
|
|||
|
{0x00,0x00}, //MIXER_TREBLE
|
|||
|
{0x26,0x26}, //MIXER_MIDI
|
|||
|
{0x04,0x04}, //MIXER_VOICE
|
|||
|
{0x00,0x00}, //MIXER_SPEAKER
|
|||
|
{0x2e,0x2e}, //MIXER_LINE
|
|||
|
{0x0a,0x00}, //MIXER_MIC
|
|||
|
{0x28,0x28}, //MIXER_CD
|
|||
|
{0x00,0x00}, //MIXER_IMIX
|
|||
|
{0x00,0x00}, //MIXER_ALTPCM
|
|||
|
{0x00,0x00}, //MIXER_AGC
|
|||
|
{0x00,0x00}, //MIXER_OUTPUTGAIN
|
|||
|
{0x00,0x00} //MIXER_INPUTGAIN
|
|||
|
};
|
|||
|
|
|||
|
// SB16 Mixer table
|
|||
|
TMixIndxTab SB16tab[MIXER_DEVICE_NUM]={
|
|||
|
//Left Right
|
|||
|
{0x30,0x31}, //MIXER MASTER
|
|||
|
{0x46,0x47}, //MIXER_BASS
|
|||
|
{0x44,0x45}, //MIXER_TREBLE
|
|||
|
{0x34,0x35}, //MIXER_MIDI
|
|||
|
{0x32,0x33}, //MIXER_VOICE
|
|||
|
{0x3b,0x00}, //MIXER_SPEAKER
|
|||
|
{0x38,0x39}, //MIXER_LINE
|
|||
|
{0x3a,0x00}, //MIXER_MIC
|
|||
|
{0x36,0x37}, //MIXER_CD
|
|||
|
{0x00,0x00}, //MIXER_IMIX
|
|||
|
{0x00,0x00}, //MIXER_ALTPCM
|
|||
|
{0x43,0x00}, //MIXER_AGC
|
|||
|
{0x41,0x42}, //MIXER_OUTPUTGAIN
|
|||
|
{0x3f,0x40} //MIXER_INPUTGAIN
|
|||
|
};
|
|||
|
|
|||
|
// SB Defaults
|
|||
|
/*
|
|||
|
unsigned SBdefault[MIXER_DEVICE_NUM] =
|
|||
|
{// L R
|
|||
|
0xf0f0, // Master (SB16 Max 0xf8)
|
|||
|
0x9090, // Bass (SB16 Max 0xf0)
|
|||
|
0xd0d0, // Treble (SB16 Max 0xf0)
|
|||
|
0x0000, // MIDI (SB16 Max 0xf8)
|
|||
|
0xe0e0, // Voice (SB16 Max 0xf8)
|
|||
|
0x0000, // PC Speaker (SB16 Max 0xc0)
|
|||
|
0xc0c0, // Ext Line
|
|||
|
0x0000, // Mic
|
|||
|
0x0000, // CD
|
|||
|
0x0000, // Recor. Monitor
|
|||
|
0x0000, // SB PCM
|
|||
|
0x0000, // Agc On (AGC on = 0, off = 1)
|
|||
|
0x4040, // Output Gain = 2 (2^)
|
|||
|
0x0000 // Input Gain = 2 (Gain=1->0x00 2->0x40 4->0x80 8->0xc0)
|
|||
|
};
|
|||
|
*/
|
|||
|
unsigned SBdefault[MIXER_DEVICE_NUM] =
|
|||
|
{// L R
|
|||
|
0xc0c0, // Master (SB16 Max 0xf8)
|
|||
|
0xa0a0, // Bass (SB16 Max 0xf0)
|
|||
|
0x7070, // Treble (SB16 Max 0xf0)
|
|||
|
0x7070, // MIDI (SB16 Max 0xf8)
|
|||
|
0xc0c0, // Voice (SB16 Max 0xf8)
|
|||
|
0x0000, // PC Speaker (SB16 Max 0xc0)
|
|||
|
0x9090, // Ext Line
|
|||
|
0x0000, // Mic
|
|||
|
0x0000, // CD
|
|||
|
0x0000, // Recor. Monitor
|
|||
|
0x0000, // SB PCM
|
|||
|
0x0000, // Agc On (AGC on = 0, off = 1)
|
|||
|
0x4040, // Output Gain = 2 (2^)
|
|||
|
0x0000 // Input Gain = 2 (Gain=1->0x00 2->0x40 4->0x80 8->0xc0)
|
|||
|
};
|
|||
|
|
|||
|
int sb_ioaddr = 0;
|
|||
|
byte sb_DMA8ch = 1, // (1) 0..3
|
|||
|
sb_DMA16ch = 1, // (6) 4..7 NOT ACTIVE, not yet
|
|||
|
sb_IRQnum = 5;
|
|||
|
byte sb_type;
|
|||
|
int DMApage[4] = {0x87,0x83,0x81,0x82},
|
|||
|
DMAaddr[4] = { 0, 2, 4, 6},
|
|||
|
DMAlen[4] = { 1, 3, 5, 7};
|
|||
|
TMixIndxTab *mixtab;
|
|||
|
word DMAbuffer_size;
|
|||
|
byte far *DMAbuffer, far *DMAbufhalf;
|
|||
|
byte Old8259Mask;
|
|||
|
void interrupt far (*oldsbvect)(...);
|
|||
|
|
|||
|
#pragma warn -rvl
|
|||
|
byte sbmix_read(byte port) {
|
|||
|
asm {
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_MIXER_ADDR
|
|||
|
MOV AL, port
|
|||
|
OUT DX, AL
|
|||
|
|
|||
|
// Delay
|
|||
|
MOV CX, 16
|
|||
|
CLD
|
|||
|
REP IN AL, 0x80
|
|||
|
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_MIXER_DATA
|
|||
|
IN AL, DX
|
|||
|
}}
|
|||
|
#pragma warn +rvl
|
|||
|
|
|||
|
void sbmix_write(byte port, byte data) {
|
|||
|
asm {
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_MIXER_ADDR
|
|||
|
MOV AL, port
|
|||
|
OUT DX, AL
|
|||
|
|
|||
|
// Delay
|
|||
|
MOV CX, 16
|
|||
|
CLD
|
|||
|
REP IN AL, 0x80
|
|||
|
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_MIXER_DATA
|
|||
|
MOV AL, data
|
|||
|
OUT DX, AL
|
|||
|
}}
|
|||
|
/*
|
|||
|
byte sbmix_detect() {
|
|||
|
// !!! Pu<50> provocare uno spike in output ???
|
|||
|
// ...ma tutto ci<63> serve a qualcosa ? Secondo me no
|
|||
|
sbmix_write(0x26,0xff); // MIDI
|
|||
|
sbmix_write(0x04,0x33); // VOICE
|
|||
|
if (sbmix_read(0x26) != 0xff) return 0;
|
|||
|
if (sbmix_read(0x04) != 0x33) return 0;
|
|||
|
sbmix_write(0x26,0x00); // off MIDI
|
|||
|
sbmix_write(0x04,0x00); // off VOICE
|
|||
|
return 1;
|
|||
|
}
|
|||
|
*/
|
|||
|
char sbmix_setvol(byte dev, unsigned data) {
|
|||
|
byte left = data & 0x00ff,
|
|||
|
right = (data & 0xff00) >> 8;
|
|||
|
if (sb_type == SBT_SBPRO) {
|
|||
|
left >>= 4;
|
|||
|
right >>= 4;
|
|||
|
}
|
|||
|
SBdefault[dev] = ((unsigned)right << 8) | left; // Questione visuale
|
|||
|
if (mixtab[dev].left != 0x00) {
|
|||
|
if (mixtab[dev].left == mixtab[dev].right) {
|
|||
|
sbmix_write(mixtab[dev].left,(left<<4)|right);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
sbmix_write(mixtab[dev].left,left);
|
|||
|
}
|
|||
|
if (mixtab[dev].right != 0x00)
|
|||
|
sbmix_write(mixtab[dev].right,right);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
/*
|
|||
|
void sbmix_reset() {
|
|||
|
!!!
|
|||
|
for (int i=0; i<MIXER_DEVICE_NUM; i++)
|
|||
|
sbmix_setvol(i, SBdefault[i]);
|
|||
|
}
|
|||
|
*/
|
|||
|
void sbmix_setIRQ() {
|
|||
|
char data;
|
|||
|
switch (sb_IRQnum) {
|
|||
|
case 2: data = 0xf1; break;
|
|||
|
case 5: data = 0xf2; break;
|
|||
|
case 7: data = 0xf4; break;
|
|||
|
case 10: data = 0xf8; break;
|
|||
|
// default: error("?");
|
|||
|
}
|
|||
|
sbmix_write(MIXER_IRQ_NR,data);
|
|||
|
}
|
|||
|
|
|||
|
void sbmix_init() {
|
|||
|
//sbmix_write(0,0); // Reset
|
|||
|
if (sb_type>=SBT_SB16) mixtab=SB16tab; else
|
|||
|
if (sb_type==SBT_SBPRO) mixtab=SBPROtab; else
|
|||
|
mixtab=SB1tab; //error("No Mixer ?\n"); return;
|
|||
|
//sbmix_reset();
|
|||
|
|
|||
|
if (sb_type >= SBT_SB16) {
|
|||
|
//sbmix_write(0x3c,MIX16_DEFAULT_OUTPUT);
|
|||
|
//sbmix_write(0x3d,MIX16_DEFAULT_INPUT_LEFT);
|
|||
|
//sbmix_write(0x3e,MIX16_DEFAULT_INPUT_RIGHT);
|
|||
|
sbmix_setIRQ();
|
|||
|
sbmix_write(MIXER_DMA_NR,(1<<sb_DMA16ch) | (1<<sb_DMA8ch));
|
|||
|
} else
|
|||
|
if (sb_type == SBT_SBPRO) {
|
|||
|
//sbmix_write(0x0c,MIXPRO_INPUT_LINE); // Input = LINE IN
|
|||
|
sbmix_write(0x0e,0x13 /* = STEREO; 0x11 = MONO */); // Output = STEREO
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#pragma warn -rvl
|
|||
|
byte sb_readDSPsafe() {
|
|||
|
asm {
|
|||
|
MOV CX, 0x200
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_DATA_AVAIL
|
|||
|
} cic1: asm {
|
|||
|
IN AL, DX
|
|||
|
OR AL, AL
|
|||
|
JS ready
|
|||
|
LOOP cic1
|
|||
|
XOR AL, AL
|
|||
|
JMP end
|
|||
|
} ready: asm {
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_READ_DATA
|
|||
|
IN AL, DX
|
|||
|
} end:; }
|
|||
|
#pragma warn +wrvl
|
|||
|
|
|||
|
void sb_writeDSPsafe(byte data) {
|
|||
|
asm {
|
|||
|
MOV CX, 0x200
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_WRITE_STATUS // == WRITE_DATA
|
|||
|
} cic1: asm {
|
|||
|
IN AL, DX
|
|||
|
OR AL, AL
|
|||
|
JNS ready
|
|||
|
LOOP cic1
|
|||
|
JMP end
|
|||
|
} ready: asm {
|
|||
|
MOV AL, data
|
|||
|
OUT DX, AL
|
|||
|
} end:; }
|
|||
|
|
|||
|
void sb_ackDMA() {
|
|||
|
inp(sb_ioaddr+DSP_DATA_AVAIL);
|
|||
|
}
|
|||
|
|
|||
|
char sb_resetDSP() {
|
|||
|
asm {
|
|||
|
MOV DX, sb_ioaddr
|
|||
|
ADD DX, DSP_RESET
|
|||
|
MOV AL, 1
|
|||
|
OUT DX, AL
|
|||
|
/*
|
|||
|
IN AL, DX // ritardo (3<>s ?)
|
|||
|
IN AL, DX
|
|||
|
IN AL, DX
|
|||
|
IN AL, DX
|
|||
|
*/
|
|||
|
// Delay
|
|||
|
MOV CX, 16
|
|||
|
} lp: asm {
|
|||
|
IN AL, 0x80
|
|||
|
LOOP lp
|
|||
|
|
|||
|
MOV AL, 0
|
|||
|
OUT DX, AL
|
|||
|
}
|
|||
|
for (register int i=0x20; i && sb_readDSPsafe() != 0xaa; i--);
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
char sb_check() {
|
|||
|
sb_resetDSP();
|
|||
|
sb_writeDSPsafe(0xe0);
|
|||
|
sb_writeDSPsafe(0xc6);
|
|||
|
return (sb_readDSPsafe() == 0x39);
|
|||
|
}
|
|||
|
|
|||
|
char sb_autodetect() {
|
|||
|
sb_ioaddr = 0x220;
|
|||
|
while (sb_ioaddr <= 0x260) {
|
|||
|
if (sb_check()) return 1;
|
|||
|
sb_ioaddr += 0x10;
|
|||
|
}
|
|||
|
sb_ioaddr = 0x210;
|
|||
|
return sb_check();
|
|||
|
}
|
|||
|
|
|||
|
void setDMA() {
|
|||
|
asm {
|
|||
|
XOR BH, BH
|
|||
|
MOV BL, sb_DMA8ch
|
|||
|
MOV CH, BL
|
|||
|
SHL BX, 1
|
|||
|
MOV AL, 4
|
|||
|
ADD AL, CH
|
|||
|
OUT 0x0a, AL
|
|||
|
XOR AL, AL
|
|||
|
OUT 0x0c, AL
|
|||
|
MOV AL, 0x58 // + AUTOINIT = 0x10
|
|||
|
OR AL, CH
|
|||
|
OUT 0x0b, AL
|
|||
|
// Calc page-offset
|
|||
|
MOV AX, WORD PTR DMAbuffer
|
|||
|
MOV DX, WORD PTR DMAbuffer[2]
|
|||
|
MOV CL, DH
|
|||
|
SHR CL, 4
|
|||
|
SHL DX, 4
|
|||
|
ADD AX, DX
|
|||
|
ADC CL, 0
|
|||
|
// CL:AX = page:offset
|
|||
|
MOV DX, WORD PTR DMAaddr[BX]
|
|||
|
// LEA SI, DMAaddr
|
|||
|
// MOV DX, [SI+BX]
|
|||
|
OUT DX, AL
|
|||
|
MOV AL, AH
|
|||
|
OUT DX, AL
|
|||
|
INC DL // !!! scorciatoia !!!
|
|||
|
//MOV AX, ((DMA_BUFFER_SIZE*2)-1) // !!! ocio: 1 buffer diviso 2
|
|||
|
MOV AX, DMAbuffer_size
|
|||
|
SHL AX, 1
|
|||
|
DEC AX
|
|||
|
OUT DX, AL
|
|||
|
MOV AL, AH
|
|||
|
OUT DX, AL
|
|||
|
MOV DX, WORD PTR DMApage[BX]
|
|||
|
// LEA SI, DMApage
|
|||
|
// MOV DX, [SI+BX]
|
|||
|
MOV AL, CL
|
|||
|
OUT DX, AL
|
|||
|
MOV AL, CH
|
|||
|
OUT 0x0a, AL
|
|||
|
}}
|
|||
|
|
|||
|
void sb_enableDMA() {
|
|||
|
switch (sb_type) {
|
|||
|
case SBT_SB16:
|
|||
|
sb_writeDSPsafe(0xc6);
|
|||
|
sb_writeDSPsafe(0x20);
|
|||
|
break;
|
|||
|
default:
|
|||
|
sb_writeDSPsafe(0x14); // it's DMA 8 bit !
|
|||
|
break;
|
|||
|
}
|
|||
|
sb_writeDSPsafe((DMAbuffer_size-1) & 0xff);
|
|||
|
sb_writeDSPsafe((DMAbuffer_size-1) >> 8);
|
|||
|
}
|
|||
|
|
|||
|
void sb_settimeconst(byte tc) {
|
|||
|
sb_writeDSPsafe(0x40);
|
|||
|
sb_writeDSPsafe(tc);
|
|||
|
}
|
|||
|
|
|||
|
void sb_setsamplerate(unsigned sr) {
|
|||
|
sb_writeDSPsafe(0x42); // = PLAY; 0x41 = REC
|
|||
|
sb_writeDSPsafe(sr >> 8); // high
|
|||
|
sb_writeDSPsafe(sr & 0xff); // low
|
|||
|
}
|
|||
|
|
|||
|
char sb_init(byte dma8, byte dma16, byte irq) {
|
|||
|
if (sb_autodetect()) {
|
|||
|
// SB identify
|
|||
|
sb_resetDSP();
|
|||
|
sb_writeDSPsafe(0xe1);
|
|||
|
sb_type = sb_readDSPsafe();
|
|||
|
sb_readDSPsafe(); // !!! non serve
|
|||
|
if (sb_type<SBT_SBPRO) DMAbuffer_size=1024;
|
|||
|
else DMAbuffer_size=2048;
|
|||
|
if ((DMAbuffer = new char[DMAbuffer_size<<1]) == NULL) return 0;
|
|||
|
// Adjust DMAbuffer ptr
|
|||
|
asm {
|
|||
|
MOV AX, WORD PTR DMAbuffer
|
|||
|
MOV DX, WORD PTR DMAbuffer[2]
|
|||
|
MOV BX, AX
|
|||
|
SHR BX, 4
|
|||
|
ADD DX, BX
|
|||
|
AND AX, 0x000f
|
|||
|
MOV WORD PTR DMAbuffer, AX
|
|||
|
MOV WORD PTR DMAbuffer[2], DX
|
|||
|
}
|
|||
|
DMAbufhalf = DMAbuffer+DMAbuffer_size;
|
|||
|
|
|||
|
Old8259Mask=inp(0x21);
|
|||
|
outp(0x21,Old8259Mask & ~(1<<sb_IRQnum));
|
|||
|
disable();
|
|||
|
oldsbvect=getvect(sb_IRQnum+0x08);
|
|||
|
setvect(sb_IRQnum+0x08,soundISR);
|
|||
|
enable();
|
|||
|
sb_DMA8ch = dma8;
|
|||
|
sb_DMA16ch = dma16;
|
|||
|
sb_IRQnum = irq;
|
|||
|
|
|||
|
//if (sbmix_detect())
|
|||
|
sbmix_init();
|
|||
|
|
|||
|
if (sb_type < SBT_SBPRO) sb_settimeconst(256-1000000L/11025); else
|
|||
|
if (sb_type == SBT_SBPRO) sb_settimeconst(256-1000000L/22050); else
|
|||
|
sb_setsamplerate(11025);
|
|||
|
sb_writeDSPsafe(DSPC_SPEAKER_ON);
|
|||
|
setDMA();
|
|||
|
} else return 0;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
void sb_stopDMA() {
|
|||
|
sb_writeDSPsafe(0xd0);
|
|||
|
}
|
|||
|
|
|||
|
void sb_continueDMA() {
|
|||
|
sb_writeDSPsafe(0xd4);
|
|||
|
}
|
|||
|
|
|||
|
void sb_done() {
|
|||
|
if (sb_ioaddr) {
|
|||
|
sb_writeDSPsafe(DSPC_SPEAKER_OFF);
|
|||
|
|
|||
|
if(Old8259Mask & (1<<sb_IRQnum) != 0x00)
|
|||
|
outp(0x21,(inp(0x21)|(1<<sb_IRQnum)));
|
|||
|
disable();
|
|||
|
setvect(sb_IRQnum+0x08,oldsbvect);
|
|||
|
enable();
|
|||
|
|
|||
|
sb_resetDSP();
|
|||
|
}
|
|||
|
}
|
|||
|
|