DECLARE FUNCTION Capital! (L$)
DECLARE SUB NewWord (W$)
DECLARE SUB GuessWord (WS$)
DECLARE FUNCTION WordArray! (WORD$)
DECLARE SUB sayword (W$)
DECLARE SUB SAY (e$)
' when using this program be sure to use the qbasic/h option to get the best
'  veiw of the source code
'

DECLARE SUB talk ()
DECLARE SUB meter (byte!, h!, v!)
DECLARE SUB MicVolume (volume%, Getvol%)
DECLARE SUB LineVolume (right%, left%, Getvol%)
DECLARE SUB MasterVolume (right%, left%, Getvol%)
DECLARE SUB WriteDSP (byte%)
DECLARE SUB speakerstate (OnOff%)
DECLARE FUNCTION speakerstatus% ()
DECLARE SUB SHOWREGISTERS ()
DECLARE SUB sendbyte (PA$)
DECLARE SUB getblaster (DMA%, baseport%, IRQ%)
DECLARE SUB INNOISE (byte!)
DECLARE SUB micnoise (byte!)
DECLARE SUB INPUTSOURCE (InputSrc%, GetSrc%)
DECLARE SUB linenoise (bytel!, byter!)
DECLARE SUB SHOEREGISTERS
DECLARE SUB PlayWav (wavefile$)
DECLARE SUB ValidWavHeader (file$, LenHeader%, dataLen&, nChannels%, nSamplesPerSec&, nAvgBytesPerSec&, ok%)
DECLARE SUB WriteToDSP (v%)
DECLARE SUB PlayBack (buffer$, size%, freq&, BytesPerSec&, chans%, num%)
DECLARE SUB delay (tdelay!)
DECLARE SUB speak (phr$)
DECLARE FUNCTION GetBlasterAddr% ()
DECLARE FUNCTION SBreset% ()

COMMON SHARED baseport%, LENPORT%, channel%
COMMON SHARED BlasterAddr%, DMA%, repeats%

RANDOMIZE TIMER
' DEF SEG = &HA000
DIM SHARED M1%(300), M2%(300), M3%(300), M4%(300)
DIM SHARED E1%(300), E2%(300), E4%(300), CC$, A1$(19), A2$(9)
TYPE WORDTYPE
WORD AS STRING * 20
SND AS STRING * 20
END TYPE


COLOR 15
BlasterAddr% = GetBlasterAddr%

extlop = 0

CLS
DO

ke$ = INKEY$
 IF ke$ = CHR$(27) THEN xetlop = 1
  SHOWREGISTERS




LOOP UNTIL extlop = 1




NUMDATA:
DATA "ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE","TEN","ELEVEN","TWELVE"
DATA "THIRTEEN","FOURTEEN","FIFTEEN","SIXTEEN","SEVENTEEN","EIGHTEEN","NINETEEN"
DATA "TEN","TWENTY","THIRTY","FORTY","FIFTY","SIXTY","SEVENTY","EIGHTY","NINETY"
DEFINT A-Z

DEFSNG A-Z
FUNCTION Capital (L$)

IF L$ = UCASE$(L$) THEN Capital = 1 ELSE Capital = 0
END FUNCTION

DEFINT A-Z
'------------------------------------------------------------------------------
SUB delay (tdelay!)
time1! = TIMER
DO
LOOP WHILE (TIMER - time1! < tdelay!) OR (time1! > TIMER)
END SUB

DEFSNG A-Z
SUB getblaster (DMA%, baseport%, IRQ%)
' This subroutine parses the BLASTER environment string and returns settings.
IF LEN(ENVIRON$("BLASTER")) = 0 THEN PRINT "BLASTER environment variable not set.": EXIT SUB
FOR length% = 1 TO LEN(ENVIRON$("BLASTER"))
   SELECT CASE MID$(ENVIRON$("BLASTER"), length%, 1)
      CASE "A"
        baseport% = VAL("&H" + MID$(ENVIRON$("BLASTER"), length% + 1, 3))
      CASE "I"
        IRQ% = VAL(MID$(ENVIRON$("BLASTER"), length% + 1, 1))
      CASE "D"
        DMA% = VAL(MID$(ENVIRON$("BLASTER"), length% + 1, 1))
   END SELECT
NEXT

END SUB

DEFINT A-Z
'------------------------------------------------------------------------------
FUNCTION GetBlasterAddr%
'Get Blaster Address and DMA channel from Environment Variable
tmp% = 0  'No Environment Variable Set...default
blast$ = UCASE$(ENVIRON$("BLASTER"))
IF LEN(blast$) THEN
   tmp% = INSTR(blast$, "A")
   tmp1$ = MID$(blast$, tmp% + 1, 3)
   tmp% = VAL("&H" + tmp1$)
   IF tmp% = 203 THEN tmp% = -1    'If there is no value assigned
   IF tmp% > 0 THEN
      tmp2% = INSTR(blast$, "D")
      DMA% = VAL(MID$(blast$, tmp2% + 1))        'dma% is a global variable
      IF DMA% < 0 OR DMA% > 7 THEN tmp% = -2
   END IF
END IF
GetBlasterAddr% = tmp%
END FUNCTION

DEFSNG A-Z
SUB INNOISE (byte)
        OUT commaddr, &H20
        
        byte = INP(DataAddr)
'

END SUB

SUB INPUTSOURCE (InputSrc%, GetSrc%)
OUT baseport% + 4, &HC
IF GetSrc% THEN
   InputSrc% = INP(baseport% + 5) AND 2 + INP(baseport% + 5) AND 4
ELSE
   OUT baseport% + 5, InputSrc% AND 7
END IF
END SUB

SUB linenoise (bytel, byter)
        OUT commaddr, &H20
       
    
    
     CALL INPUTSOURCE(&H2E, GetSrc%)

CALL INNOISE(byte)
byter = byte
bytel = byte


'LOCATE 4, 6: PRINT "selected noise "; byte

END SUB

SUB LineVolume (right%, left%, Getvol%)
OUT baseport% + 4, &H2E
nn = INP(&H2E)

LOCATE 10, 10
'PRINT nn

IF Getvol% THEN
   left% = INP(baseport% + 5) \ 16
   right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (right% + left% * 16) AND &HFF
END IF
END SUB

SUB MasterVolume (right%, left%, Getvol%)
OUT baseport% + 4, &H22
'PRINT BasePort%
IF Getvol% THEN
   left% = INP(baseport% + 5) \ 16
   right% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, (right% + left% * 16) AND &HFF
END IF
END SUB

SUB meter (byte, h, v)

c = byte

LINE (h, v)-(h + 258, v + 11), 1, B
LINE (h + 1, v + 1)-(h + byte + 1, v + 10), c, BF
LINE (h + byte, v + 1)-(h + 256, v + 10), 0, BF





END SUB

SUB micnoise (byte)

        OUT commaddr, &H20
       


CALL INPUTSOURCE(&H20, GetSrc%)
      
CALL INNOISE(byte)
END SUB

SUB MicVolume (volume%, Getvol%)
OUT baseport% + 4, &HA
IF Getvol% THEN
   volume% = INP(baseport% + 5) AND &HF
   EXIT SUB
ELSE
   OUT baseport% + 5, volume% AND &HF
END IF
END SUB

DEFINT A-Z
'------------------------------------------------------------------------------
SUB PlayBack (buffer$, size%, freq&, BytesPerSec&, chans%, num%)
size% = size% - 1
segment& = VARSEG(buffer$)
offset& = SADD(buffer$)
IF segment& < 0 THEN segment& = segment& + 65536
IF offset& < 0 THEN offset& = offset& + 65536
baseaddr& = segment& * 16 + offset&
look1% = VARPTR(baseaddr&)
look2% = VARPTR(size%)
SELECT CASE DMA%
   CASE 0
      dmapage% = &H87   '135 decimal
      dmaaddr% = 0
      dmalen% = 1
   CASE 1
      dmapage% = &H83   '131 decimal
      dmaaddr% = 2
      dmalen% = 3
   CASE 2
      dmapage% = &H81
      dmaaddr% = 4
      dmalen% = 5
   CASE 3
      dmapage% = &H82
      dmaaddr% = 6
      dmalen% = 7
   CASE 4
      dmapage% = &H8F
      dmaaddr% = &HC0
      dmalen% = &HC2
   CASE 5
      dmapage% = &H8B
      dmaaddr% = &HC4
      dmalen% = &HC6
   CASE 6
      dmapage% = &H89
      dmaaddr% = &HC8
      dmalen% = &HCA
   CASE 7
      dmapage% = &H8A
      dmaaddr% = &HCC
      dmalen% = &HCE
END SELECT
SELECT CASE DMA%
   CASE 0 TO 3
      dmamask% = &HA
      dmamode% = &HB
      dmaclear% = &HC
      dmastatus% = &H8
   CASE 4 TO 7
      dmamask% = &HD4
      dmamode% = &HD6
      dmaclear% = &HD8
      dmastatus% = &HD0
END SELECT
SELECT CASE DMA%
   CASE 0, 4
      dmaterminal% = 1   'bit 0 of status register (&H08 or &HD0)
   CASE 1, 5
      dmaterminal% = 2   'bit 1
   CASE 2, 6
      dmaterminal% = 4   'bit 2
   CASE 3, 7
      dmaterminal% = 8   'bit 3
END SELECT

OUT dmamask%, DMA% + 4   'mask the dma channel
OUT dmaclear%, &H0       '(clear the internal DMA flip/flop)
OUT dmamode%, 72 + DMA%  '  72=010010XX where XX=dmachannel%
OUT dmaaddr%, PEEK(look1%)      'bits 0-7 of  the 20bit address
OUT dmaaddr%, PEEK(look1% + 1)  'bits 8-15 of the 20bit address
OUT dmapage%, PEEK(look1% + 2)  'bits 16-19 of the 20 bit address
OUT dmalen%, PEEK(look2%)       'bits 0-7 of size%
OUT dmalen%, PEEK(look2% + 1)   'bits 8-15  of size%
OUT dmamask%, DMA%              'enable channel

IF num% = 1 THEN  'only need to Write out time constant once
   timeconst% = 256 - 1000000 / (freq& * chans%)
   CALL WriteToDSP(&H40)
   CALL WriteToDSP(timeconst%)
   'Reset Mixer    DSPmixeraddress = Blasteraddr% + &H4
   OUT BlasterAddr% + &H4, &H0
   OUT BlasterAddr% + &H4 + 1, 0
   'Set Volume to Maximum...255
   OUT BlasterAddr% + &H4, &H22
   OUT BlasterAddr% + &H4 + 1, 255
   IF chans% = 2 THEN
      'Set mixer to Stereo Output
      OUT BlasterAddr% + &H4, &HE
      OUT BlasterAddr% + &H4 + 1, 34      '34=2^5+2^1
   END IF
END IF
IF BytesPerSec& > 22000 THEN
   CALL WriteToDSP(&H48)   'Set Block Size
ELSE
   CALL WriteToDSP(&H14)   'DMA Mode 8-bit DAC
END IF
CALL WriteToDSP(PEEK(look2%))      'Lo byte of address
CALL WriteToDSP(PEEK(look2% + 1))  'High byte of address
IF BytesPerSec& > 22000 THEN CALL WriteToDSP(&H91)  'High Speed DMA mode 8-bit
dummy% = INP(dmastatus%)    'Read status byte once to make sure DMA is going.
WAIT dmastatus%, dmaterminal%   'Loop until terminal count bit set in DMA status register

'DMA Transfer is Now Complete
'Acknowledge the DSP interrupt by reading the DATA AVAILABLE port once
dummy% = INP(BlasterAddr% + &HE)    'DSP Available address
END SUB

DEFSNG A-Z
SUB PlayWav (wavefile$)


repeats% = 1
BlasterAddr% = GetBlasterAddr%
SELECT CASE BlasterAddr%
   CASE -2
      PRINT "Bad DMA Channel specified!"
      END
   CASE -1
      PRINT "No Port Base Address Given!"
      END
   CASE 0
      PRINT "No BLASTER Environment Variable Set!"
      END
   CASE ELSE
      'Assume a valid Address Exists
'      PRINT "Blaster Address = "; HEX$(BlasterAddr%)
END SELECT
IF NOT SBreset% THEN
   PRINT "SoundBlaster Card Would Not Reset!"
   END
END IF

sp% = INSTR(Spec$, " ")
IF sp% THEN
   wavefile$ = LEFT$(Spec$, sp% - 1)
   repeats% = VAL(RIGHT$(Spec$, LEN(Spec$) - sp%))
   IF repeats% = 0 THEN repeats% = 1
ELSE
   IF LEN(Spec$) THEN
      wavefile$ = Spec$
      repeats% = 1
   END IF
END IF

IF LEN(wavefile$) = 0 THEN
END IF
'wavefile$ = "C:\QBASIC\THEME.WAV"
CALL ValidWavHeader(wavefile$, LenHeader%, WavLen&, Channels%, Sampling&, bytes&, ok%)
    'PRINT "< "; byte%; " > "
IF NOT ok% THEN
   PRINT "Bad Wave File Format"
   END
END IF

MaxBuffer% = 7053

CALL WriteToDSP(&HD1)  'Speaker ON
FOR repeat% = 1 TO repeats%    'This can loop to play the file ii% times]
filenum% = FREEFILE
   OPEN wavefile$ FOR BINARY AS filenum%
      num% = 0
      SEEK filenum%, LenHeader% + 1
      Remaining& = WavLen&
      DO
         num% = num% + 1
         IF Remaining& > MaxBuffer% THEN
            BufferLen% = MaxBuffer%
         ELSE
            BufferLen% = Remaining&
         END IF
         Remaining& = Remaining& - BufferLen%
         buffer$ = SPACE$(BufferLen%)
         GET filenum%, , buffer$
         CALL PlayBack(buffer$, BufferLen%, Sampling&, bytes&, Channels%, num%)
 
     
      LOOP WHILE Remaining& > 0
      OUT &H20, &H20   'Reset Normal Interrupt Service
   CLOSE filenum%
NEXT repeat%
CALL WriteToDSP(&HD3)  'Speaker OFF

END SUB

DEFINT A-Z
'------------------------------------------------------------------------------
FUNCTION SBreset%
'DSPreset% = address% + &H6
'DSPread% = address% + &HA
'DSPwrite% = address% + &HC
'DSPavail% = address% + &HE
'DSPmixer% = address% + &H4
OUT BlasterAddr% + &H6, 1   'Reset address
delay .1
OUT BlasterAddr% + &H6, 0
time1! = TIMER: noreset% = 0
DO
   'Read Data Available port until bit 7 is set
   'This should take about 100 micro seconds...give it 1 full second
   IF TIMER - time1! > 1! THEN noreset% = -1
LOOP UNTIL ((INP(BlasterAddr% + &HE) AND 128) = 128) OR noreset%
IF NOT noreset% THEN
   IF INP(BlasterAddr% + &HA) = &HAA THEN
      SBreset% = -1
   ELSE
      SBreset% = 0
   END IF
ELSE
   SBreset% = 0
END IF
END FUNCTION

DEFSNG A-Z
SUB sendbyte (PA$)
'
'SEND BINARY INFORMATION TO LINE OUT (SPEAKERS)
'
  DIM BIT(10)
FOR OUPL = 1 TO LEN(PA$)

   CH$ = MID$(PA$, OUPL, 1)
   BYTEVAL = ASC(CH$)
   'PRINT "< "; BYTEVAL; " >";
           
FOR K = 10 TO 0 STEP -1
 IF (BYTEVAL AND 2 ^ K) <> 0 THEN BIT(K) = 1 ELSE BIT(K) = 0
 IF BIT(0) = 1 THEN BIT0$ = "1" ELSE BIT0$ = "0"
 IF BIT(1) = 1 THEN BIT1$ = "1" ELSE BIT1$ = "0"
 IF BIT(2) = 1 THEN BIT2$ = "1" ELSE BIT2$ = "0"
 IF BIT(3) = 1 THEN BIT3$ = "1" ELSE BIT3$ = "0"
 IF BIT(4) = 1 THEN BIT4$ = "1" ELSE BIT4$ = "0"
 IF BIT(5) = 1 THEN BIT5$ = "1" ELSE BIT5$ = "0"
 IF BIT(6) = 1 THEN BIT6$ = "1" ELSE BIT6$ = "0"
 IF BIT(7) = 1 THEN BIT7$ = "1" ELSE BIT7$ = "0"
 IF BIT(8) = 1 THEN BIT8$ = "1" ELSE BIT8$ = "0"
 IF BIT(9) = 1 THEN BIT9$ = "1" ELSE BIT9$ = "0"
 IF BIT(10) = 1 THEN BIT10$ = "1" ELSE BIT10$ = "0"




NEXT K
   



   byte$ = BIT10$ + BIT9$ + BIT8$ + BIT7$ + BIT6$ + BIT5$ + BIT4$ + BIT3$ + BIT2$ + BIT1$ + BIT0$



    PRINT byte$; " . ";
   
       L = LEN(byte$)
     
       FOR CC = 1 TO (L)
     
       BIT$ = MID$(byte$, CC, 1)
      
        IF BIT$ = "1" THEN
      
         CALL PlayWav("C:\WINDOWS\SOUND\BIT.WAV")

      
        END IF

        IF BIT$ = "0" THEN

         CALL PlayWav("C:\WINDOWS\SOUND\NOBIT.WAV")



        END IF



       NEXT CC
    byte$ = ""








NEXT OUPL




END SUB

SUB SHOWREGISTERS

REM GET ALL CURRENT REGISTERS OF IMPORTANCE
REM SHOW THEIR CURRENT STATUS
REM CODING UTILITY SBLASTER
CALL getblaster(DMA%, baseport%, IRQ%)

LOCATE 1, 1: PRINT "BASEPORT% "; baseport%
LOCATE 2, 6: PRINT "DMA% "; DMA%
LOCATE 3, 6: PRINT "IRC% "; IRQ%
CALL linenoise(bytel, byter)

LOCATE 6, 6: PRINT "line -L"; bytel; " -R "; byter

CALL micnoise(byte)
LOCATE 8, 5: PRINT "( mic ) ;"; byte

PRINT getscr%
CALL linenoise(bytel, byter)

END SUB

SUB speakerstate (OnOff%)
' Turns speaker on or off.
IF OnOff% THEN WriteDSP (&HD1) ELSE WriteDSP (&HD3)

END SUB

FUNCTION speakerstatus%
OUT baseport% + 4, &HD8
IF INP(baseport% + 5) = &HFF THEN speakerstatus% = -1 ELSE speakerstatus% = 0
END FUNCTION

DEFINT A-Z
'------------------------------------------------------------------------------
SUB ValidWavHeader (file$, LenHeader%, dataLen&, nChannels%, nSamplesPerSec&, nAvgBytesPerSec&, ok%)
rID$ = SPACE$(4)
wID$ = SPACE$(4)
fID$ = SPACE$(4)
dat$ = SPACE$(4)
dummy$ = SPACE$(1)

filenum% = FREEFILE
OPEN file$ FOR BINARY AS filenum%
  GET filenum%, , rID$
  GET filenum%, , rLen&
  GET filenum%, , wID$
  GET filenum%, , fID$
  GET filenum%, , fLen&
  GET filenum%, , wFormatTag%       '2 bytes
  GET filenum%, , nChannels%        '2 bytes
  GET filenum%, , nSamplesPerSec&   '4 bytes
  GET filenum%, , nAvgBytesPerSec&  '4 bytes
  GET filenum%, , nBlockAlign%      '2 bytes
  GET filenum%, , FormatSpecific%   '2 bytes
  'Read bytes until have read fLen& total bytes.
  'I have no idea what these next bytes are used for (if they even exist).
  FOR i% = 1 TO fLen& - 16          '16 bytes is what we have read in so far
     GET filenum%, , dummy$         'read in 1 byte at a time
  NEXT i%
  GET filenum%, , dat$
  IF UCASE$(dat$) = "FACT" THEN
     'funny format...
     GET filenum%, , dummy&
     GET filenum%, , dummy&
     GET filenum%, , dat$
  END IF
  GET filenum%, , dataLen&
  LenHeader% = LOC(1)
CLOSE filenum%
'  PRINT rID$;
'  PRINT rLen&;
'  PRINT wID$;
'  PRINT fID$;
'  PRINT fLen&;
'  PRINT wFormatTag%;       '2 bytes
'  PRINT nChannels%;        '2 bytes
'  PRINT nSamplesPerSec&;   '4 bytes
'  PRINT nAvgBytesPerSec&;  '4 bytes
'  PRINT nBlockAlign%;      '2 bytes
'  PRINT FormatSpecific%;   '2 bytes
'  PRINT dat$;
'  PRINT dataLen&;
'  PRINT LenHeader%
IF UCASE$(rID$) = "RIFF" THEN
   IF UCASE$(wID$) = "WAVE" THEN
      IF UCASE$(dat$) = "DATA" THEN
         IF UCASE$(fID$) = "FMT " THEN
           IF FormatSpecific% = 8 THEN ok% = -1
         END IF
      END IF
   END IF
END IF
END SUB

DEFSNG A-Z
SUB WriteDSP (byte%)
' Writes a byte to the DSP
DO
LOOP WHILE INP(baseport% + 12) AND &H80
OUT baseport% + 12, byte%
END SUB

DEFINT A-Z
'------------------------------------------------------------------------------
SUB WriteToDSP (v%)
DO
LOOP UNTIL (INP(BlasterAddr% + &HC) AND 128) = 0
OUT BlasterAddr% + &HC, v%
END SUB

