'===========================================================================
' Subject: SOUNDBLASTER DETECTION             Date: 02-24-00 (16:07)       
'  Author: Alexander Verhaeghe                Code: QB, QBasic, PDS        
'  Origin: Alexander@ibase.be               Packet: SOUND.ABC
'===========================================================================
' The following functions will detect the soundblaster by using OUT and INP
' and not by simply reading the autoexec.bat
' Some code was found in a C program and from Ethan Brodky (http://www.xraylith.wisc.edu/~ebrodsky/)
' Reactions can be sent to AlexanderVerhaeghe@yahoo.com, so is my name Alexander Verhaeghe
' Works in QBASIC and QuickBASIC, probably PowerBASIC and Visual Basic for DOS
'
DEFINT A-Z
DECLARE FUNCTION DspRead ()
DECLARE FUNCTION DspReset ()
DECLARE SUB DspWrite (byte AS INTEGER)
DECLARE SUB GetDspVersion (returnmajorversion AS INTEGER, returnminorversion AS INTEGER)
DECLARE FUNCTION GetSbBaseport ()
DECLARE FUNCTION GetSbIrq ()
DECLARE FUNCTION GetSbLowerDma ()
DECLARE FUNCTION GetSbUpperDma ()
DECLARE FUNCTION IsSb ()
DIM minorversion AS INTEGER, majorversion AS INTEGER
CLS
IF IsSb = 0 THEN
  PRINT "Baseport: "; HEX$(GetSbBaseport)
  PRINT "IRQ:"; GetSbIrq
  PRINT "Lower DMA:"; GetSbLowerDma
  PRINT "Upper DMA:"; GetSbUpperDma
  GetDspVersion majorversion, minorversion
  PRINT "Lower DSP version:"; minorversion
  PRINT "Upper DSP version:"; majorversion
ELSE
  PRINT "Soundblaster not detected"
END IF

FUNCTION DspRead
  SHARED baseport AS INTEGER
  DO
  LOOP UNTIL INP(baseport + &HE) AND &H80
  DspRead = INP(baseport + &HA)
END FUNCTION

FUNCTION DspReset
  SHARED baseport AS INTEGER
  DIM ct AS INTEGER, stat AS INTEGER
  OUT baseport + &H6, &H1
  FOR ct = 1 TO 100
  NEXT ct
  OUT baseport + &H6, &H0
  ct = 0
  stat = 0
  WHILE (stat <> &HAA) AND (ct < 100)
    stat = INP(baseport + &HE)
    stat = INP(baseport + &HA)
    ct = ct + 1
  WEND
  IF stat = &HAA THEN DspReset = 0 ELSE DspReset = -1
END FUNCTION

SUB DspWrite (byte AS INTEGER)
  SHARED baseport AS INTEGER
  DO
  LOOP UNTIL (INP(baseport + &HC) AND &H80) = 0
  OUT baseport + &HC, byte
END SUB

SUB GetDspVersion (returnmajorversion AS INTEGER, returnminorversion AS INTEGER)
  DspWrite &HE1
  returnmajorversion = DspRead
  returnminorversion = DspRead
END SUB

FUNCTION GetSbBaseport
  SHARED baseport AS INTEGER
  GetSbBaseport = baseport
END FUNCTION

FUNCTION GetSbIrq
  SHARED baseport AS INTEGER
  OUT baseport + &H4, &H80
  SELECT CASE INP(baseport + &H5) AND &HF
    CASE &H1
      GetSbIrq = 2
    CASE &H2
      GetSbIrq = 5
    CASE &H4
      GetSbIrq = 7
    CASE &H8
      GetSbIrq = 10
    CASE ELSE
      GetSbIrq = -1
  END SELECT
END FUNCTION

FUNCTION GetSbLowerDma
  SHARED baseport AS INTEGER
  OUT baseport + &H4, &H81
  SELECT CASE INP(baseport + &H5) AND &HB
    CASE &H1
      GetSbLowerDma = 0
    CASE &H2
      GetSbLowerDma = 1
    CASE &H8
      GetSbLowerDma = 3
    CASE ELSE
      GetSbLowerDma = -1
  END SELECT
END FUNCTION

FUNCTION GetSbUpperDma
  SHARED baseport AS INTEGER
  DIM lowerdma AS INTEGER
  lowerdma = GetSbLowerDma
  OUT baseport + &H4, &H81
  SELECT CASE INP(baseport + &H5) \ &H20
    CASE &H1
      GetSbUpperDma = 5
    CASE &H2
      GetSbUpperDma = 6
    CASE &H4
      GetSbUpperDma = 7
    CASE ELSE
      GetSbUpperDma = lowerdma
  END SELECT
END FUNCTION

FUNCTION IsSb
  SHARED baseport AS INTEGER
  DIM sbdetected AS INTEGER
  baseport = &H220
  sbdetected = -1
  WHILE (baseport <= &H280) AND (sbdetected = -1)
    sbdetected = DspReset
    IF sbdetected = -1 THEN baseport = baseport + &H20
  WEND
  IsSb = sbdetected
END FUNCTION
