'===========================================================================
' Subject: ADLIB SOUND EFFECTS                Date: 08-05-96 (18:39)       
'  Author: Lloyd Chang                        Code: QB, QBasic, PDS        
'  Origin: FidoNet QUIK_BAS Echo            Packet: SOUND.ABC
'===========================================================================
' > Anyway,  I really need to get adlib sound into my Qb4.5 programs. 

'I hope ADLIB.BAS will help.  It's included at the bottom of this
'message.

'As to making your own sound effects (in non-mathematical form),
'I have not yet figured out how to do that.  Tim Truman's
'defender game comes with six sound effects.  Perhaps you want
'to examine those first.

'Just in case you want to contact Tim Truman, his AOL account
'is "Tim Truman" and his Compuserve address is "74734,2203"

'I have not contacted him yet but the addresses should still
'work since his Defender game was written in 1995 and revised
'in 1996.

'I believe you can also reach him via the internet through his
'Compuserve address (but I don't really know how Compuserve
'converts its user addresses into Internet addresses).

'------------------------------ CUT HERE ------------------------------

'ADLIB.BAS
'Written by Lloyd Chang

'ADLIB.BAS is meant to provide
'a skeleton to the use of an adlib
'sound effects in QuickBASIC

'.---------.
'| NOTICE: |
'`---------'
'The functions, sub-routines, and adlib detection
'are stripped from Defender, a QuickBASIC game
'written by Tim Truman (based on the Defender
'game on the Atari 2600).

DECLARE FUNCTION adlib ()               ' detects presence of adlib
DECLARE SUB WriteReg (reg, value)       ' write to adlibs registers
DECLARE SUB adlibfx (num)               ' plays the sounds

DEFINT A-Z

IF adlib THEN
  adlibsound = TRUE
  PRINT "Adlib detected"
  SLEEP (1)
END IF

adlibfx (0)
SLEEP 1
adlibfx (1)
SLEEP 2
adlibfx (0)
SLEEP 3
adlibfx (1)
SLEEP 4
adlibfx (0)
SLEEP 5
adlibfx (1)
SLEEP 6

DEFSNG A-Z
FUNCTION adlib

  '  Detects an AdLib-compatible card.
  '  Returns 1 (true) if detected and 0 (false) if not.
  
 
   CALL WriteReg(&H4, &H60)  '  Resets both Timers
   CALL WriteReg(&H4, &H80)  '  Enables Interrupts
   b = INP(&H388)            '  Store the result
   CALL WriteReg(&H2, &HFF)  '  Write FFh to register 2 (Timer 1)
   CALL WriteReg(&H4, &H21)  '  Start Timer 1

   FOR x = 0 TO 130          '  Delay for 80 Microseconds
      a = INP(&H388)
   NEXT x

   c = INP(&H388)                 '  Store the result
   CALL WriteReg(&H4, &H60)       '  Reset Timers
   CALL WriteReg(&H4, &H80)       '  Reset Interrrupts
   Success = 0
   IF (b AND &HE0) = &H0 THEN     '  Test result
     IF (c AND &HE0) = &HC0 THEN  '  Test Result
       Success = 1
       FOR q = 1 TO &HF5          '  clear registers
         CALL WriteReg(q, 0)
       NEXT q
     END IF
   END IF
   adlib = Success


END FUNCTION

SUB adlibfx (num)

 SELECT CASE (num)

 CASE (0)                    '   mutant exploding

 
   WriteReg &HB0, &H0
   numberl = 60
   numberh = 1
   block = 0
                                 ' Modulator
   CALL WriteReg(&H20, &H0)      ' Multiple - 0 to F
   CALL WriteReg(&H40, &H0)      ' Attenuation Level -  0 to 3F
   CALL WriteReg(&H60, &HA5)     ' Attack: (High byte)    Decay: (Low byte)
   CALL WriteReg(&H80, &H0)      ' Sustain: (High byte)   Release: (Low byte)
   CALL WriteReg(&HE0, &HF0)     ' Waveform select  0 to 3
                                ' Carrier
   CALL WriteReg(&H23, &H0)      ' Multiple  - 0 to F
   CALL WriteReg(&H43, &H0)      ' Attenuation level -  0 to 3F
   CALL WriteReg(&H63, &HA6)     ' Attack: (High byte)   Decay:(low byte)
   CALL WriteReg(&H83, &HAA)     ' Sustain: (High Byte)  Release:(low byte)
   CALL WriteReg(&HE1, &HF0)     ' Waveform select  0 to 3

   keyon% = &H20

   Byte = keyon% + (block * 4) + numberh%

   CALL WriteReg(&HA0, numberl)     ' F-Number(L)  0 to 255
   CALL WriteReg(&HB0, Byte)     ' Sound voice ,Set block ,Set F-Number(H)


 CASE 1                 'hero firing

  WriteReg &HB1, &H0

  numberl = 230
  numberh = 1
  block = 1
                              ' Modulator
  CALL WriteReg(&H21, &H10)    ' Multiple - 0 to F
  CALL WriteReg(&H41, &H0)    ' Attenuation Level -  0 to 3F
  CALL WriteReg(&H61, &H66)   ' Attack: (High byte)    Decay: (Low byte)
  CALL WriteReg(&H81, &HF6)   ' Sustain: (High byte)   Release: (Low byte)
  CALL WriteReg(&HE1, &HF2)   ' Waveform select  0 to 3
                              ' Carrier
  CALL WriteReg(&H24, &H0)    ' Multiple  - 0 to F
  CALL WriteReg(&H44, &H6)    ' Attenuation level -  0 to 3F
  CALL WriteReg(&H64, &H63)   ' Attack: (High byte)   Decay:(low byte)
  CALL WriteReg(&H84, &HF8)    ' Sustain: (High Byte)  Release:(low byte)
  CALL WriteReg(&HE4, &HF0)   ' Waveform select  0 to 3

  keyon = &H20

  Byte = keyon + (block * 4) + (numberh)

  CALL WriteReg(&HC1, 0)            ' conection
  CALL WriteReg(&HC1, 0)            ' conection
  CALL WriteReg(&HA1, numberl)     ' F-Number(L)  0 to 255
  CALL WriteReg(&HB1, Byte)     ' Sound voice ,Set block ,Set F-Number(H)

  '  WriteReg &HB1, &H0          ' stop noise

  '  numberl = 10
  '  numberh = 0
   ' block = 7
                                ' Modulator
  '  CALL WriteReg(&H21, &H3)     ' Multiple - 0 to F
  '  CALL WriteReg(&H41, &H0)    ' Attenuation Level -  0 to 3F
  '  CALL WriteReg(&H61, &H99)   ' Attack: (High byte)    Decay: (Low byte)
  '  CALL WriteReg(&H81, &HFF)   ' Sustain: (High byte)   Release: (Low byte)
  '  CALL WriteReg(&HE1, &HF0)   ' Waveform select  0 to 3
                                ' Carrier
  '  CALL WriteReg(&H24, &H1)    ' Multiple  - 0 to F
  '  CALL WriteReg(&H44, &H0)    ' Attenuation level -  0 to 3F
  '  CALL WriteReg(&H64, &HAD)   ' Attack: (High byte)   Decay:(low byte)
   ' CALL WriteReg(&H84, &H55)   ' Sustain: (High Byte)  Release:(low byte)
  '  CALL WriteReg(&HE4, &HF0)   ' Waveform select  0 to 3

  '  keyon% = &H20

  '  Byte = keyon% + (block * 4) + numberh

  ' CALL WriteReg(&HA1, numberl)     ' F-Number(L)  0 to 255
  ' CALL WriteReg(&HB1, Byte)     ' Sound voice ,Set block ,Set F-Number(H)



 CASE 2                       ' colonist pick up warning

  WriteReg &HB2, &H0          ' stop noise

  numberl = 255
  numberh = 3
  block = 2
                              ' Modulator
  CALL WriteReg(&H22, &H3)    ' Multiple - 0 to F
  CALL WriteReg(&H42, &H0)    ' Attenuation Level -  0 to 3F
  CALL WriteReg(&H62, &H5F)   ' Attack: (High byte)    Decay: (Low byte)
  CALL WriteReg(&H82, &HFF)   ' Sustain: (High byte)   Release: (Low byte)
  CALL WriteReg(&HE2, &HF0)   ' Waveform select  0 to 3
                              ' Carrier
  CALL WriteReg(&H25, &H0)    ' Multiple  - 0 to F
  CALL WriteReg(&H45, &H9)    ' Attenuation level -  0 to 3F
  CALL WriteReg(&H65, &H5F)   ' Attack: (High byte)   Decay:(low byte)
  CALL WriteReg(&H85, &HFF)   ' Sustain: (High Byte)  Release:(low byte)
  CALL WriteReg(&HE5, &HF0)   ' Waveform select  0 to 3

  keyon% = &H20

  Byte = keyon% + (block * 4) + numberh

  CALL WriteReg(&HA2, numberl)     ' F-Number(L)  0 to 255
  CALL WriteReg(&HB2, Byte)     ' Sound voice ,Set block ,Set F-Number(H)


 CASE 3                         ' mutant converted
    WriteReg &HB3, &H0

    numberl = 10
    numberh = 0
    block = 5
                                ' Modulator
    CALL WriteReg(&H28, &H5)     ' Multiple - 0 to F
    CALL WriteReg(&H48, &H0)    ' Attenuation Level -  0 to 3F
    CALL WriteReg(&H68, &H99)   ' Attack: (High byte)    Decay: (Low byte)
    CALL WriteReg(&H88, &HFF)   ' Sustain: (High byte)   Release: (Low byte)
    CALL WriteReg(&HE8, &HF0)   ' Waveform select  0 to 3
                                ' Carrier
    CALL WriteReg(&H2B, &H0)    ' Multiple  - 0 to F
    CALL WriteReg(&H4B, &H0)    ' Attenuation level -  0 to 3F
    CALL WriteReg(&H6B, &HAD)   ' Attack: (High byte)   Decay:(low byte)
    CALL WriteReg(&H8B, &H55)   ' Sustain: (High Byte)  Release:(low byte)
    CALL WriteReg(&HEB, &HF0)   ' Waveform select  0 to 3

    keyon% = &H20
 
    Byte = keyon% + (block * 4) + numberh

   CALL WriteReg(&HA3, numberl)     ' F-Number(L)  0 to 255
   CALL WriteReg(&HB3, Byte)     ' Sound voice ,Set block ,Set F-Number(H)

 CASE 4           ' mutant firing

    WriteReg &HB4, &H0          ' stop noise

    numberl = 10
    numberh = 0
    block = 1
                                ' Modulator
    CALL WriteReg(&H29, &H5)     ' Multiple - 0 to F
    CALL WriteReg(&H49, &H0)    ' Attenuation Level -  0 to 3F
    CALL WriteReg(&H69, &H87)   ' Attack: (High byte)    Decay: (Low byte)
    CALL WriteReg(&H89, &HFF)   ' Sustain: (High byte)   Release: (Low byte)
    CALL WriteReg(&HE9, &HF0)   ' Waveform select  0 to 3
                                ' Carrier
    CALL WriteReg(&H2C, &H1)    ' Multiple  - 0 to F
    CALL WriteReg(&H4C, &H9)    ' Attenuation level -  0 to 3F
    CALL WriteReg(&H6C, &HA5)   ' Attack: (High byte)   Decay:(low byte)
    CALL WriteReg(&H8C, &H55)   ' Sustain: (High Byte)  Release:(low byte)
    CALL WriteReg(&HEC, &HF0)   ' Waveform select  0 to 3

    keyon% = &H20

    Byte = keyon% + (block * 4) + numberh

   CALL WriteReg(&HA4, numberl)     ' F-Number(L)  0 to 255
   CALL WriteReg(&HB4, Byte)     ' Sound voice ,Set block ,Set F-Number(H)
 
 CASE 5

   'PRINT " bomer noise"
   WriteReg &HB5, &H0          ' stop noise

    numberl = 60
    numberh = 1
    block = 2
                                ' Modulator
    CALL WriteReg(&H2A, &H0)    ' Multiple - 0 to F
    CALL WriteReg(&H4A, &H0)    ' Attenuation Level -  0 to 3F
    CALL WriteReg(&H6A, &H55)   ' Attack: (High byte)    Decay: (Low byte)
    CALL WriteReg(&H8A, &HAA)   ' Sustain: (High byte)   Release: (Low byte)
    CALL WriteReg(&HEA, &HF3)   ' Waveform select  0 to 3
                                ' Carrier
    CALL WriteReg(&H2D, &H0)    ' Multiple  - 0 to F
    CALL WriteReg(&H4D, &H0)    ' Attenuation level -  0 to 3F
    CALL WriteReg(&H6D, &HFF)   ' Attack: (High byte)   Decay:(low byte)
    CALL WriteReg(&H8D, &HAA)   ' Sustain: (High Byte)  Release:(low byte)
    CALL WriteReg(&HED, &HF3)   ' Waveform select  0 to 3


   CALL WriteReg(&HC5, 1)            ' conection

   keyon% = &H20

   Byte = keyon% + (block * 4) + numberh

   CALL WriteReg(&HA5, numberl)     ' F-Number(L)  0 to 255
   CALL WriteReg(&HB5, Byte)     ' Sound voice ,Set block ,Set F-Number(H)


  CASE 6

   WriteReg &HB4, &H0
   numberl = 130
   numberh = 0
   block = 0
                                 ' Modulator
   CALL WriteReg(&H29, &H0)      ' Multiple - 0 to F
   CALL WriteReg(&H49, &H0)      ' Attenuation Level -  0 to 3F
   CALL WriteReg(&H69, &HA5)     ' Attack: (High byte)    Decay: (Low byte)
   CALL WriteReg(&H89, &H0)      ' Sustain: (High byte)   Release: (Low byte)
   CALL WriteReg(&HE9, &HF0)     ' Waveform select  0 to 3
                                ' Carrier
   CALL WriteReg(&H2C, &H0)      ' Multiple  - 0 to F
   CALL WriteReg(&H4C, &H0)      ' Attenuation level -  0 to 3F
   CALL WriteReg(&H6C, &HA6)     ' Attack: (High byte)   Decay:(low byte)
   CALL WriteReg(&H8C, &H55)     ' Sustain: (High Byte)  Release:(low byte)
   CALL WriteReg(&HEC, &HF0)     ' Waveform select  0 to 3

   keyon% = &H20

   Byte = keyon% + (block * 4) + numberh%

   CALL WriteReg(&HA4, numberl)     ' F-Number(L)  0 to 255
   CALL WriteReg(&HB4, Byte)     ' Sound voice ,Set block ,Set F-Number(H)



 END SELECT

END SUB

SUB WriteReg (reg, value)

' Writes to AdLib's registers the delays required when writing to these
' ports are present.
'
' Reg is the register to write to. Value is the data to send.


OUT &H388, reg     '  388h = Register/Status port
                   '  Tells the SB what register we want to write to

                   '  Calling the register port 6 times creates an
                   '  accurate delay of 3.3ms. This delay is required
FOR x = 0 TO 5     '  after writing to the register port.
   a = INP(&H388)
NEXT x

OUT &H389, value   '  389h = data port
                   '  send data that corrisponds with the requested register.

                   '  Calling the data port 35 times creates an
                   '  accurate delay of 23ms. This delay is required.
FOR x = 0 TO 34    '  after writing to the data port.
   a = INP(&H388)
NEXT x


END SUB
