home *** CD-ROM | disk | FTP | other *** search
- {****************************************************************************}
- { }
- { MODULE: SoundBlaster }
- { }
- { DESCRIPTION: An UNIT that provides several routines for handling the }
- { Sound Blaster and Sound Blaster Pro cards and compatibles. }
- { }
- { AUTHOR: Juan Carlos Arévalo }
- { }
- { MODIFICATIONS: Nobody (yet ;-) }
- { }
- { HISTORY: 12-Nov-1992 Documentation. }
- { 26-Nov-1992 Included SB 16 support. }
- { }
- { (C) 1992 VangeliSTeam }
- {____________________________________________________________________________}
-
- UNIT SoundBlaster;
-
- {$R-}
-
- INTERFACE
-
- USES SoundDevices;
-
-
-
-
- { I/O Port offsets. }
-
- CONST
- CMS1DataPortOffset = $00; { CM/S 1-6 Data port. Write Only. }
- CMS1AddrPortOffset = $01; { CM/S 1-6 Address port. Write Only. }
- CMS2DataPortOffset = $02; { CM/S 7-12 Data port. Write Only. }
- CMS2AddrPortOffset = $03; { CM/S 7-12 Address port. Write Only. }
-
- MixAddrPortOffset = $04; { Mixer register port. Write Only. }
- MixDataPortOffset = $05; { Mixer data port. Read/Write. }
-
- FMStatPortOffset = $08; { Mono FM Status port. Read Only. }
- FMAddrPortOffset = $08; { Mono FM Address port. Write Only. }
- FMDataPortOffset = $09; { Mono FM Data port. Write Only. }
-
- LFMStatPortOffset = $00; { Left FM Status port. Read Only. }
- LFMAddrPortOffset = $00; { Left FM Address port. Write Only. }
- LFMDataPortOffset = $01; { Left FM Data port. Write Only. }
-
- RFMStatPortOffset = $02; { Right FM Status port. Read Only. }
- RFMAddrPortOffset = $02; { Right FM Address port. Write Only. }
- RFMDataPortOffset = $03; { Right FM Data port. Write Only. }
-
- DSPResetPortOffset = $06; { DSP Reset port. Write Only. }
- DSPReadPortOffset = $0A; { DSP Read data port. Read Only. }
- DSPLifePortOffset = $0A; { DSP Read data port. Read Only. }
- DSPWStatPortOffset = $0C; { DSP Write buffer status port. Write Only. }
- DSPWritePortOffset = $0C; { DSP Write data port. Write Only. }
- DSPRStatPortOffset = $0E; { DSP Read buffer status port. Read Only. }
- DSP8AckPortOffset = $0E; { 8 bit DMA IRQ Acknowledge port. Write Only. }
- DSP16AckPortOffset = $0F; { 16 bit DMA IRQ Acknowledge port. Write Only. }
-
- CDDataPortOffset = $10; { CD-ROM Data port. Read Only. }
- CDCmdPortOffset = $10; { CD-ROM Command port. Write Only. }
- CDStatPortOffset = $11; { CD-ROM Status port. Read Only. }
- CDResetPortOffset = $12; { CD-ROM Reset port. Write Only. }
- CDEnablePortOffset = $13; { CD-ROM Enable port. Write Only. }
-
-
- { I/O Ports. Same as above. }
-
- CONST
- CMS1DataPort : WORD = $220 + CMS1DataPortOffset;
- CMS1AddrPort : WORD = $220 + CMS1AddrPortOffset;
- CMS2DataPort : WORD = $220 + CMS2DataPortOffset;
- CMS2AddrPort : WORD = $220 + CMS2AddrPortOffset;
-
- MixAddrPort : WORD = $220 + MixAddrPortOffset;
- MixDataPort : WORD = $220 + MixDataPortOffset;
-
- FMStatPort : WORD = $220 + FMStatPortOffset;
- FMAddrPort : WORD = $220 + FMAddrPortOffset;
- FMDataPort : WORD = $220 + FMDataPortOffset;
-
- LFMStatPort : WORD = $220 + LFMStatPortOffset;
- LFMAddrPort : WORD = $220 + LFMAddrPortOffset;
- LFMDataPort : WORD = $220 + LFMDataPortOffset;
-
- RFMStatPort : WORD = $220 + RFMStatPortOffset;
- RFMAddrPort : WORD = $220 + RFMAddrPortOffset;
- RFMDataPort : WORD = $220 + RFMDataPortOffset;
-
- DSPResetPort : WORD = $220 + DSPResetPortOffset;
- DSPReadPort : WORD = $220 + DSPReadPortOffset;
- DSPLifePort : WORD = $220 + DSPLifePortOffset;
- DSPWStatPort : WORD = $220 + DSPWStatPortOffset;
- DSPWritePort : WORD = $220 + DSPWritePortOffset;
- DSPRStatPort : WORD = $220 + DSPRStatPortOffset;
- DSP8AckPort : WORD = $220 + DSP8AckPortOffset;
- DSP16AckPort : WORD = $220 + DSP16AckPortOffset;
-
- CDDataPort : WORD = $220 + CDDataPortOffset;
- CDCmdPort : WORD = $220 + CDCmdPortOffset;
- CDStatPort : WORD = $220 + CDStatPortOffset;
- CDResetPort : WORD = $220 + CDResetPortOffset;
- CDEnablePort : WORD = $220 + CDEnablePortOffset;
-
-
- { Configuration. }
-
- CONST
- SbPort : WORD = $FFFF; { Base port. $FFFF Means Autodetect. }
- SbIrq : WORD = 7; { DMA IRQ level. }
- SbDMAChan : WORD = 1; { DMA channel. }
- SbDefTimeout : WORD = 5000; { Default DSP timeout. }
- SbHiSpeed : BOOLEAN = TRUE; { User Desires HS DMA mode if TRUE. }
- SbForce : BOOLEAN = FALSE; { Force TRUE the detection of the SB. }
- MixerForce : BOOLEAN = FALSE; { Force TRUE the detection of the Mixer. }
- SbProForce : BOOLEAN = FALSE; { Force TRUE the detection of the SB Pro. }
- Sb16Force : BOOLEAN = FALSE; { Force TRUE the detection of the SB 16. }
-
-
- { Card information. }
-
- CONST
- SbVersionMin : BYTE = 0;
- SbVersionMaj : BYTE = 0;
- SbVersionStr : STRING[ 5] = '';
- SbCopyright : STRING[80] = '';
- SbResponse1 : BYTE = 0;
- SbResponse2 : BYTE = 0;
-
- VAR
- SbVersion : WORD ABSOLUTE SbVersionMin;
-
-
- { Run-time information. }
-
- CONST
- SbRegDetected : BOOLEAN = FALSE;
- SbRegInited : BOOLEAN = FALSE;
- SbProDetected : BOOLEAN = FALSE;
- SbProInited : BOOLEAN = FALSE;
- Sb16Detected : BOOLEAN = FALSE;
- Sb16Inited : BOOLEAN = FALSE;
- MixerDetected : BOOLEAN = FALSE;
-
- SbWorksOk : BOOLEAN = TRUE; { Set to FALSE if DSP timeouts. }
- HSBlockSpecified : WORD = 0; { Set to the last hi-speed block size. }
- Sb16BlockSpecified: WORD = 0; { Set to the last Sb 16 block size. }
- SbStereo : BOOLEAN = FALSE; { Stereo DMA mode if TRUE. }
- SbFilter : BOOLEAN = FALSE; { SB Pro output filter ON if TRUE. }
-
- DoHiSpeed : BOOLEAN = FALSE; { Hi speed DMA mode if TRUE. }
- Sb16Bit : BOOLEAN = FALSE; { 16 bit output if TRUE. }
-
- TimeConst : BYTE = 0;
-
- DMAStart : BOOLEAN = FALSE;
- DMAStop : BOOLEAN = FALSE;
- DMAStopped : BOOLEAN = FALSE;
-
- DMAIrqWatch : BYTE = 0;
-
-
-
- { DSP Commands. }
-
- CONST
- sdcSendOneSample = $10; { Send a sample to the DAC directly (mono mode only). }
- sdcStartLSpeedDMA = $14; { Start a low-speed DMA transfer. }
- sdcSetTimeConst = $40; { Set the time constant. }
- sdcSetHSpeedSize = $48; { Set hi-speed DMA transfer length. }
- sdcStartHSpeedDMA = $91; { Start a hi-speed DMA transfer. }
- sdcTurnOnSpeaker = $D1; { Turn on the SB speaker. }
- sdcTurnOffSpeaker = $D3; { Turn off the SB speaker. }
- sdcGetDSPVersion = $E1; { Get the DSP version number. }
- sdcGetCopyright = $E3; { Get the card copyright string. }
-
-
- { Mixer registers. }
-
- CONST
- mxrDataReset = $00;
- mxrDACVolume = $04;
- mxrMicMixing = $0A;
- mxrInSetting = $0C;
- mxrOutSetting = $0E;
- mxrMasterVolume = $22;
- mxrFMVolume = $26;
- mxrCDVolume = $28;
- mxrLineVolume = $2E;
-
-
- { Bit masks for the mixer registers. }
-
- CONST
- mxiFilterVal = $38;
- mxiADCVal = $06;
- mxoFilterNeg = $20;
- mxoStereoOn = $02;
-
- TYPE
- TMixerVolume = (mvMaster,
- mvVoice,
- mvFM,
- mvLine,
- mvMicrophone,
- mvSpeaker,
- mvCD);
-
- CONST
- SbProRegs : ARRAY[mvMaster..mvCD] OF BYTE = ( $22, $04, $26, $2E, $0A, $00, $28 );
- Sb16Regs : ARRAY[mvMaster..mvCD] OF BYTE = ( $30, $32, $34, $38, $3A, $3B, $34 );
-
-
-
-
- { SB basic }
-
- FUNCTION SbReset : BOOLEAN;
-
- PROCEDURE SbWriteLoop (t: WORD);
- PROCEDURE SbWriteByte (t: WORD; b: BYTE);
- PROCEDURE SbReadLoop (t: WORD);
- FUNCTION SbReadByte (t: WORD) : BYTE;
-
-
- { Mixer basic }
-
- PROCEDURE SbWriteMixerReg (Reg, Val: BYTE);
- FUNCTION SbReadMixerReg (Reg: BYTE) : BYTE;
-
-
- { SB Reg }
-
- FUNCTION SbRegDetect : BOOLEAN;
- PROCEDURE SbRegInit;
- PROCEDURE SbRegDone;
-
- PROCEDURE SbGetDSPVersion;
- PROCEDURE SbGetCopyrightString;
- PROCEDURE SbSetTimeConst (tc: BYTE);
- PROCEDURE SbUpdateTimeConst;
- PROCEDURE SbStartSampleLS (Len: WORD; Cont: BOOLEAN);
- PROCEDURE SbStartSampleHS (Len: WORD; Cont: BOOLEAN);
- PROCEDURE SbPlaySample (Len: WORD; Cont: BOOLEAN);
-
-
- { Mixer }
-
- FUNCTION MixerDetect : BOOLEAN;
-
- PROCEDURE MixerSetVolume(Reg: TMixerVolume; VolLeft, VolRight: BYTE);
- FUNCTION MixerGetVolume(Reg: TMixerVolume; VAR VolLeft, VolRight: BYTE) : BOOLEAN;
-
-
- { SB Pro }
-
- FUNCTION SbProDetect : BOOLEAN;
- PROCEDURE SbProInit;
- PROCEDURE SbProDone;
-
- PROCEDURE SbProSetStereo (Stereo: BOOLEAN);
- PROCEDURE SbProSetFilter (Filter: BOOLEAN);
-
-
- { SB 16 }
-
- FUNCTION Sb16Detect : BOOLEAN;
- PROCEDURE Sb16Init;
- PROCEDURE Sb16Done;
-
- PROCEDURE Sb16StartSample(Len: WORD; Cont: BOOLEAN);
-
-
-
-
- IMPLEMENTATION
-
- USES Debugging;
-
-
-
- {----------------------------------------------------------------------------}
- { Sound Blaster basic routines. }
- {____________________________________________________________________________}
-
- FUNCTION SbReset : BOOLEAN;
- CONST
- ready = $AA;
- VAR
- ct, stat : BYTE;
- BEGIN
- PORT[DSPResetPort] := 1;
- FOR ct := 1 TO 100 DO;
- PORT[DSPResetPort] := 0;
-
- stat := 0;
- ct := 0;
- WHILE (stat <> ready) AND (ct < 100) DO BEGIN
- stat := PORT[DSPRStatPort];
- stat := PORT[DSPReadPort];
- INC(ct);
- END;
-
- SbReset := stat = ready;
- END;
-
-
- PROCEDURE SbWriteLoop(t: WORD); ASSEMBLER;
- ASM
-
- MOV BX,t
- MOV DX,[DSPWritePort]
- @@lp: DEC BX
- JZ @@fin
- IN AL,DX
- ADD AL,AL
- JC @@lp
- @@fin: OR BL,BH
- MOV [SbWorksOk],BL
- END;
-
-
- PROCEDURE SbWriteByte(t: WORD; b: BYTE); ASSEMBLER;
- ASM
-
- MOV AL,b
- XOR AH,AH
- PUSH AX
- PUSH $60
- CALL WriteSNum
-
- MOV AX,t
- PUSH AX
- CALL SbWriteLoop
- JNZ @@ya
-
- MOV DX,[DSPLifePort]
- IN AL,DX
-
- MOV AX,t
- PUSH AX
- CALL SbWriteLoop
-
- @@ya: MOV AL,b
- OUT DX,AL
-
- MOV AL,[SbWorksOk]
- ADD AL,'A'
- XOR AH,AH
- PUSH AX
- PUSH $40
- CALL WriteChar
-
- END;
-
-
- PROCEDURE SbReadLoop(t: WORD); ASSEMBLER;
- ASM
-
- MOV BX,t
- MOV DX,[DSPRStatPort]
- @@lp: DEC BX
- JZ @@fin
- IN AL,DX
- ADD AL,AL
- JNC @@lp
- @@fin: OR BL,BH
- MOV [SbWorksOk],BL
- MOV DX,[DSPReadPort]
- END;
-
-
- FUNCTION SbReadByte(t: WORD) : BYTE; ASSEMBLER;
- ASM
- MOV AX,t
- PUSH AX
- CALL SbReadLoop
- JNZ @@ya
- {
- MOV DX,[DSPLifePort]
- IN AL,DX
-
- MOV AX,t
- PUSH AX
- CALL SbReadLoop
- }
- @@ya: IN AL,DX
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Mixer basic routines. }
- {____________________________________________________________________________}
-
- PROCEDURE SbWriteMixerReg(Reg, Val: BYTE); ASSEMBLER;
- ASM
-
- MOV DX,[MixAddrPort]
- MOV AL,[Reg]
- OUT DX,AL
-
- MOV DX,[MixDataPort]
- MOV AL,[Val]
- OUT DX,AL
-
- END;
-
-
- FUNCTION SbReadMixerReg(Reg: BYTE) : BYTE; ASSEMBLER;
- ASM
-
- MOV DX,[MixAddrPort]
- MOV AL,[Reg]
- OUT DX,AL
-
- MOV DX,[MixDataPort]
- IN AL,DX
-
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Regular Sound Blaster generic routines. }
- {____________________________________________________________________________}
-
- FUNCTION SbRegDetect : BOOLEAN;
- VAR
- Port, Lst : WORD;
- BEGIN
-
- SbRegDetect := SbRegDetected;
-
- IF SbRegDetected THEN EXIT;
-
- IF SbPort < $8000 THEN
- BEGIN
- Port := SbPort;
- Lst := SbPort;
- END
- ELSE
- BEGIN
- Port := $210;
- Lst := $280;
- END;
-
- WHILE (NOT SbRegDetected) AND (Port <= Lst) DO BEGIN
- CMS1DataPort := Port + CMS1DataPortOffset;
- CMS1AddrPort := Port + CMS1AddrPortOffset;
- CMS2DataPort := Port + CMS2DataPortOffset;
- CMS2AddrPort := Port + CMS2AddrPortOffset;
-
- MixAddrPort := Port + MixAddrPortOffset;
- MixDataPort := Port + MixDataPortOffset;
-
- FMStatPort := Port + FMStatPortOffset;
- FMAddrPort := Port + FMAddrPortOffset;
- FMDataPort := Port + FMDataPortOffset;
-
- LFMStatPort := Port + LFMStatPortOffset;
- LFMAddrPort := Port + LFMAddrPortOffset;
- LFMDataPort := Port + LFMDataPortOffset;
-
- RFMStatPort := Port + RFMStatPortOffset;
- RFMAddrPort := Port + RFMAddrPortOffset;
- RFMDataPort := Port + RFMDataPortOffset;
-
- DSPResetPort := Port + DSPResetPortOffset;
- DSPReadPort := Port + DSPReadPortOffset;
- DSPLifePort := Port + DSPLifePortOffset;
- DSPWStatPort := Port + DSPWStatPortOffset;
- DSPWritePort := Port + DSPWritePortOffset;
- DSPRStatPort := Port + DSPRStatPortOffset;
- DSP8AckPort := Port + DSP8AckPortOffset;
- DSP16AckPort := Port + DSP16AckPortOffset;
-
- CDDataPort := Port + CDDataPortOffset;
- CDCmdPort := Port + CDCmdPortOffset;
- CDStatPort := Port + CDStatPortOffset;
- CDResetPort := Port + CDResetPortOffset;
- CDEnablePort := Port + CDEnablePortOffset;
-
- SbRegDetected := SbReset;
-
- IF NOT SbRegDetected THEN INC(Port, $10);
- END;
-
- SbRegDetect := SbRegDetected;
-
- END;
-
-
- PROCEDURE SbRegInit;
- BEGIN
-
- IF NOT SbRegDetect THEN EXIT;
-
- IF NOT SbRegInited THEN
- BEGIN
- (*
- SbWriteByte(SbDefTimeout, $E0);
- SbWriteByte(SbDefTimeout, $AA);
- SbResponse1 := SbReadByte (SbDefTimeout); { $55 }
- SbWriteByte(SbDefTimeout, $E4);
- SbWriteByte(SbDefTimeout, $AA);
- SbWriteByte(SbDefTimeout, $E8);
- SbResponse2 := SbReadByte (SbDefTimeout); { $AA }
- *)
- SbGetDSPVersion;
-
- DoHiSpeed := (SbVersion >= $200) AND SbHiSpeed {AND FALSE};
- {
- IF DoHiSpeed THEN
- BEGIN
- SbWriteByte(SbDefTimeout, $48);
- SbWriteByte(SbDefTimeout, $00);
- SbWriteByte(SbDefTimeout, $00);
- SbWriteByte(SbDefTimeout, $91);
- END;
- }
- SbWriteByte(SbDefTimeout, sdcTurnOnSpeaker);
-
- END;
-
- SbRegInited := TRUE;
-
- END;
-
-
- PROCEDURE SbRegDone;
- BEGIN
- IF NOT (SbRegDetected AND SbRegInited) THEN EXIT;
- SbWriteByte(SbDefTimeout, sdcTurnOffSpeaker);
- END;
-
-
-
-
- PROCEDURE SbGetDSPVersion;
- VAR
- i : WORD;
- t : WORD;
- s : STRING[2];
- BEGIN
- SbWriteByte(SbDefTimeout, sdcGetDSPVersion); { Send command. }
- t := 0;
- REPEAT
- SbVersionMaj := SbReadByte($FFFF);
- INC(t);
- UNTIL ((SbVersionMaj <> $AA) AND SbWorksOk) OR (t >= 10);
- SbVersionMin := SbReadByte(SbDefTimeout);
-
- STR(SbVersionMaj, SbVersionStr);
- SbVersionStr := SbVersionStr + '.';
- STR(SbVersionMin, s);
- IF SbVersionMin > 9 THEN SbVersionStr := SbVersionStr + s
- ELSE SbVersionStr := SbVersionStr + '0' + s;
- END;
-
-
- PROCEDURE SbGetCopyrightString;
- VAR
- t : WORD;
- BEGIN
- SbWriteByte(SbDefTimeout, sdcGetCopyright); { Send command. }
- t := 0;
- REPEAT
- SbCopyright := CHAR(SbReadByte($FFFF));
- INC(t);
- UNTIL ((SbCopyright[1] <> #$AA) AND SbWorksOk) OR (t = 10);
-
- WHILE SbWorksOk AND (Length(SbCopyright) < 80) DO
- SbCopyright := SbCopyright + CHAR(SbReadByte(SbDefTimeout));
-
- DEC(SbCopyright[0]);
- END;
-
-
- PROCEDURE SbSetTimeConst(tc: BYTE);
- BEGIN
- WriteChar('T', $04);
- IF Sb16Detected THEN
- BEGIN
- WriteChar('|', $04);
- IF Sb16Bit THEN
- SbWriteByte(SbDefTimeout, $D9) { Send time constant command. }
- ELSE
- SbWriteByte(SbDefTimeout, $DA); { Send time constant command. }
- END;
- SbWriteByte(SbDefTimeout, sdcSetTimeConst); { Send time constant command. }
- SbWriteByte(SbDefTimeout*4, tc); { Send the time constant. }
- TimeConst := 0; { Reset time constant to already changed. }
- IF Sb16Detected THEN
- IF Sb16Bit THEN
- SbWriteByte(SbDefTimeout, $47) { Send time constant command. }
- ELSE
- SbWriteByte(SbDefTimeout, $45); { Send time constant command. }
- END;
-
-
- PROCEDURE SbUpdateTimeConst;
- BEGIN
- IF TimeConst = 0 THEN EXIT; { If not changed then do nothing. }
- SbSetTimeConst(TimeConst);
- END;
-
-
- PROCEDURE SbStartSampleLS(Len: WORD; Cont: BOOLEAN);
- BEGIN
- HSBlockSpecified := 0; { Reset Hi-speed block specifier, just in case. }
-
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- SbWriteByte(SbDefTimeout, sdcStartLSpeedDMA); { Start DMA low speed command. }
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- SbWriteByte(SbDefTimeout, LO(Len)); { Low & high bytes of size. }
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- SbWriteByte(SbDefTimeout, HI(Len));
-
- WriteSNum(Len, $30);
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
-
- END;
-
-
- PROCEDURE SbStartSampleHS(Len: WORD; Cont: BOOLEAN);
- BEGIN
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- IF HSBlockSpecified <> Len THEN Cont := FALSE;
- IF NOT Cont THEN
- BEGIN
- SbWriteByte(SbDefTimeout, sdcSetHSpeedSize); { Set hi speed DMA block command. }
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- SbWriteByte(SbDefTimeout, LO(Len)); { Low & high bytes of size. }
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- SbWriteByte(SbDefTimeout, HI(Len));
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- HSBlockSpecified := Len;
-
- WriteSNum(Len, $30);
-
- END;
-
- IF NOT (Sb16Detected AND Cont) THEN
- SbWriteByte(SbDefTimeout, sdcStartHSpeedDMA); { Start DMA in hi speed mode. }
- {WriteChar(CHAR(BYTE(SbWorksOk) + BYTE('A')), $40);}
- END;
-
-
- PROCEDURE SbPlaySample(Len: WORD; Cont: BOOLEAN);
- BEGIN
-
- IF Len < 10 THEN EXIT; { Too short -> Discard. It wouldn't sound anyway. }
-
- IF SbStereo THEN INC(Len, Len); { Twice as big a buffer if stereo mode. }
- DEC(Len); { DMA sizes are always size - 1. }
-
-
- WriteNum(60, Len, $70);
-
- IF Sb16Detected AND (SbStereo OR Sb16Bit) THEN
- Sb16StartSample(Len, Cont)
- ELSE IF DoHiSpeed THEN
- SbStartSampleHS(Len, Cont)
- ELSE
- SbStartSampleLS(Len, Cont);
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Mixer generic routines. }
- {____________________________________________________________________________}
-
- FUNCTION MixerDetect : BOOLEAN;
- VAR
- SaveReg : WORD;
- NewReg : WORD;
- BEGIN
- MixerDetect := MixerDetected;
- IF NOT SbRegDetect OR MixerDetected THEN EXIT;
-
- SaveReg := SbReadMixerReg($22);
- SbWriteMixerReg($22, 243);
- NewReg := SbReadMixerReg($22);
-
- IF NewReg = 243 THEN
- MixerDetected := TRUE;
-
- SbWriteMixerReg($22, SaveReg);
-
- MixerDetect := MixerDetected;
- END;
-
-
-
-
- PROCEDURE MixerSetVolume(Reg: TMixerVolume; VolLeft, VolRight: BYTE);
- VAR
- Addr : BYTE;
- VolMax : BYTE;
- BEGIN
- IF NOT MixerDetected THEN EXIT;
-
- IF Sb16Detected THEN Addr := Sb16Regs [Reg]
- ELSE Addr := SbProRegs[Reg];
-
- IF VolLeft > VolRight THEN VolMax := VolLeft
- ELSE VolMax := VolRight;
-
- CASE Reg OF
- mvMicrophone : BEGIN
- IF Sb16Detected THEN SbWriteMixerReg(Addr, VolMax)
- ELSE SbWriteMixerReg(Addr, VolMax SHR 5);
- END;
- mvSpeaker : BEGIN
- IF Sb16Detected THEN SbWriteMixerReg(Addr, VolMax);
- END;
- ELSE
-
- IF Sb16Detected THEN
- BEGIN
- SbWriteMixerReg(Addr, VolLeft);
- SbWriteMixerReg(Addr + 1, VolRight);
- END
- ELSE
- SbWriteMixerReg(Addr, (VolLeft AND $F0) +
- (VolRight SHR 4));
-
- END;
-
- END;
-
-
- FUNCTION MixerGetVolume(Reg: TMixerVolume; VAR VolLeft, VolRight: BYTE) : BOOLEAN;
- VAR
- Addr : BYTE;
- VolMax : BYTE;
- BEGIN
- MixerGetVolume := FALSE;
-
- IF NOT MixerDetected THEN EXIT;
-
- IF Sb16Detected THEN Addr := Sb16Regs [Reg]
- ELSE Addr := SbProRegs[Reg];
-
- VolLeft := 0;
- VolRight := 0;
-
- MixerGetVolume := TRUE;
-
- CASE Reg OF
- mvMicrophone : BEGIN
- IF Sb16Detected THEN VolLeft := SbReadMixerReg(Addr)
- ELSE VolLeft := SbReadMixerReg(Addr) SHL 5;
- VolRight := VolLeft;
- END;
- mvSpeaker : BEGIN
- IF Sb16Detected THEN VolLeft := SbReadMixerReg(Addr)
- ELSE MixerGetVolume := FALSE;
- VolRight := VolLeft;
- END;
- ELSE
-
- IF Sb16Detected THEN
- BEGIN
- VolLeft := SbReadMixerReg(Addr);
- VolRight := SbReadMixerReg(Addr + 1);
- END
- ELSE
- BEGIN
- VolLeft := SbReadMixerReg(Addr);
- VolRight := VolLeft SHL 4;
- VolLeft := VolLeft AND $F0;
- END;
-
- END;
-
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Sound Blaster Pro generic routines. }
- {____________________________________________________________________________}
-
- FUNCTION SbProDetect : BOOLEAN;
- BEGIN
- SbProDetect := SbProDetected;
- IF SbProDetected THEN EXIT;
-
- IF NOT SbRegInited THEN SbRegInit;
-
- SbProDetected := SbRegDetect AND MixerDetect AND (SbVersion < $400);
- SbProDetect := SbProDetected;
- END;
-
-
- PROCEDURE SbProInit;
- BEGIN
- IF NOT SbProDetect THEN EXIT;
- SbProInited := TRUE;
- END;
-
-
- PROCEDURE SbProDone;
- BEGIN
- SbRegDone;
- END;
-
-
-
-
- PROCEDURE SbProSetStereo(Stereo: BOOLEAN);
- VAR
- i : BYTE;
- BEGIN
- IF NOT SbProDetected THEN EXIT;
- SbStereo := Stereo;
- i := SbReadMixerReg(mxrOutSetting);
- SbWriteMixerReg(mxrOutSetting, (i AND NOT mxoStereoOn) +
- (BYTE(Stereo) * mxoStereoOn));
- END;
-
-
- PROCEDURE SbProSetFilter(Filter: BOOLEAN);
- VAR
- i : BYTE;
- BEGIN
- IF NOT SbProDetected THEN EXIT;
- SbFilter := Filter;
- i := SbReadMixerReg(mxrOutSetting);
- SbWriteMixerReg(mxrOutSetting, (i AND NOT mxoFilterNeg) +
- (BYTE(Filter) * mxoFilterNeg));
- END;
-
-
-
-
- {----------------------------------------------------------------------------}
- { Sound Blaster 16 generic routines. }
- {____________________________________________________________________________}
-
- FUNCTION Sb16Detect : BOOLEAN;
- BEGIN
- Sb16Detect := Sb16Detected;
- IF Sb16Detected THEN EXIT;
-
- IF NOT SbRegInited THEN SbRegInit;
-
- Sb16Detected := SbRegDetect AND MixerDetect AND (SbVersion >= $400);
- Sb16Detect := Sb16Detected;
- END;
-
-
- PROCEDURE Sb16Init;
- BEGIN
- IF NOT Sb16Detect THEN EXIT;
-
- SbGetCopyrightString;
-
- Sb16Inited := TRUE;
- END;
-
-
- PROCEDURE Sb16Done;
- BEGIN
- SbRegDone;
- END;
-
-
-
-
- PROCEDURE Sb16StartSample(Len: WORD; Cont: BOOLEAN);
- BEGIN
-
- IF (NOT Cont) OR (Sb16BlockSpecified <> Len){ OR TRUE }THEN
- BEGIN
- IF Sb16Bit THEN
- SbWriteByte(SbDefTimeout, $B6) { Set 16 bit DMA transfer command. }
- ELSE
- SbWriteByte(SbDefTimeout, $C6); { Set 8 bit DMA transfer command. }
- IF SbStereo THEN
- SbWriteByte(SbDefTimeout, $20) { Set stereo mode. }
- ELSE
- SbWriteByte(SbDefTimeout, $00); { Set mono mode. }
- SbWriteByte(SbDefTimeout, LO(Len));
- SbWriteByte(SbDefTimeout, HI(Len)); { Low & high bytes of size. }
- Sb16BlockSpecified := Len;
- END
- ELSE
- BEGIN
- IF Sb16Bit THEN
- SbWriteByte(SbDefTimeout, $47) { 16 bit DMA continue command. }
- ELSE
- SbWriteByte(SbDefTimeout, $45); { 8 bit DMA continue command. }
- END;
-
- END;
-
-
-
-
- END.
-