'===========================================================================
' Subject: CREATIVE MUSIC FILE PLAYER         Date: 05/93 (00:00)          
'  Author: Rich Dersheimer                    Code: QB, PDS                
'  Origin: SB CMF PLAYER                    Packet: SOUND.ABC
'===========================================================================
'============================================================================
' If you want to use QuickBASIC, you will have to remove statements that PDS
' uses that QB doesn't, like DIR$, SADD, and SSEG, and substitute QB code.

' If you use this code in your programs, remember that the DEF SEG is not
' reset until the music is done playing, so don't do anything to change
' the SEG while the music is playing.  Also, if the SBFMDRV.COM is not
' loaded, then your system may lock up.  I have put in a simple test to
' see if interrupt 80h is not being used, this MAY stop lockups.

' Feel free to modify ANY of the code, it's yours to keep!

' I'm putting this code in the public domain for any sound/music programmers.
' Needless to say (but I'm still gonna say it), use RPLAY code at your
' own risk, I will not be held responsible for ANYTHING that happens when
' you hack this code.  Send comments, questions, love notes to:

' Rich Dersheimer
' 72123,1521 on CIS
'============================================================================

        ' ***************************************
        ' *             RPLAY.BAS               *
        ' *   QuickBASIC/PDS source code for a  *
        ' *   program to play CMF files on the  *
        ' *   Sound Blaster sound card.         *
        ' *                                     *
        ' *   Written in May of 1993 by Rich    *
        ' *   Dersheimer.  72123,1521 on CIS    *
        ' *                                     *
        ' *   WARNING: You must start QB/PDS    *
        ' *   with the /L switch to load the    *
        ' *   proper library for InterruptX!    *
        ' *                                     *
        ' *   MORE WARNING: You must already    *
        ' *   have loaded SBFMDRV.COM to run    *
        ' *   RPLAY.EXE!  Or risk lockup!       *
        ' ***************************************
        
        DEFINT A-Z
        
        TYPE RegTypeX
                ax      AS INTEGER
                bx      AS INTEGER
                cx      AS INTEGER
                dx      AS INTEGER
                bp      AS INTEGER
                si      AS INTEGER
                di      AS INTEGER
                flags   AS INTEGER
                ds      AS INTEGER
                es      AS INTEGER
        END TYPE

        DECLARE SUB InterruptX (intnum%, iReg AS RegTypeX, oReg AS RegTypeX)

        DIM iReg AS RegTypeX
        DIM oReg AS RegTypeX

        RANDOMIZE -TIMER

        '********* Check for the SBFMDRV driver ***************
        DEF SEG = 0
        SegmentCheck = PEEK(512) + PEEK(513) * 256
        AddressCheck = PEEK(514) + PEEK(515) * 256
        DEF SEG

        IF SegmentCheck = 0 AND AddressCheck = 0 THEN
            PRINT                                ' This is a check of
            PRINT                                ' the interrupt vector
            PRINT "  SBFMDRV.COM is not loaded!" ' at address 80h.  It
            PRINT                                ' MAY keep your program
            END                                  ' from locking up if
        END IF                                   ' SBFMDRV is not loaded
        '******************************************************


        '********* Get the file name **************************
        FileName$ = COMMAND$

        IF FileName$ = "" THEN
            PRINT
            PRINT
            PRINT "     RPLAY written by Rich Dersheimer"
            PRINT "     usage: RPLAY FILENAME"
            PRINT "     WARNING!  SBFMDRV.COM *MUST* be loaded!"
            PRINT
            END
        END IF

        IF INSTR(FileName$, ".") = 0 THEN
            FileName$ = FileName$ + ".CMF"
        END IF

                                             '***
        IF DIR$(FileName$) = "" THEN           '*
            PRINT                              '*
            PRINT                              '*
            PRINT "     File ";                '*
            PRINT FileName$; " not found!"     '**** Take this code out
            PRINT                              '*    For QuickBASIC 4.5
            END                                '*
        END IF                                 '*
                                             '***

        '******************************************************


        '********* Load in the file ***************************
        OPEN FileName$ FOR BINARY AS #1
        FileLength& = LOF(1)

        IF FileLength& > 32767 THEN
            PRINT
            PRINT
            PRINT "     "; FileName$;
            PRINT " is too big for RPLAY!"
            PRINT
            END
        END IF

        A$ = STRING$(FileLength&, "r")
        GET #1, 1, A$
        CLOSE #1

        IF LEFT$(A$, 4) <> "CTMF" THEN
            PRINT
            PRINT
            PRINT "     "; FileName$;
            PRINT " does not appear to be a CMF file!"
            PRINT
            END
        END IF
        '******************************************************

        
        '********* Find the file in memory ********************
        Offset = SADD(A$)           ' offset in the segment
        Segment = SSEG(A$)          ' segment of the file
                                    ' this is different QB 4.5

        DEF SEG = Segment           ' DON'T change the segment
                                    ' while the music is playing!

        NumberIns = PEEK(Offset + &H24) + PEEK(Offset + &H25) * 256
        InsOffset = PEEK(Offset + 6) + PEEK(Offset + 7) * 256
        InsStart = Offset + InsOffset
        MusicOffset = PEEK(Offset + 8) + PEEK(Offset + 9) * 256
        MusicStart = Offset + MusicOffset
        Ticks = PEEK(Offset + &HC) + PEEK(Offset + &HD) * 256
        '******************************************************


        '***** Tell soundblaster where to return info *********
        iReg.bx = 1                     ' I'm sending the return
        iReg.dx = Segment               ' info to the first byte
        iReg.ax = Offset                ' of the music file area
        InterruptX &H80, iReg, oReg
        '******************************************************

        
        '************ Setup instruments ***********************
        'IF NumberIns > 0 AND NumberIns < 17 THEN
            iReg.bx = 2
            iReg.cx = NumberIns         ' if you get an invalid
            iReg.dx = Segment           ' # of instruments, use
            iReg.ax = InsStart          ' default instruments
            InterruptX &H80, iReg, oReg
        'END IF
        '******************************************************


        '************* Set System Clock Rate ******************
        iReg.bx = 3                     ' I'm not really sure
        iReg.ax = &HFFFF                ' you have to do this
        InterruptX &H80, iReg, oReg     ' but it doesn't hurt
        '******************************************************


        '************* Set Driver Clock Rate ******************
        iReg.bx = 4
        iReg.ax = (1193180 / Ticks)
        InterruptX &H80, iReg, oReg
        '******************************************************


        '************* Play some music! ***********************
        iReg.bx = 6
        iReg.dx = Segment
        iReg.ax = MusicStart
        InterruptX &H80, iReg, oReg
        '******************************************************


        '*********** Music should be playing by now ***********
        COLOR 9, 0
        CLS
        PRINT TAB(20); "RPLAY CMF Music Player by Rich Dersheimer"
        PRINT
        PRINT
        PRINT
        PRINT "                         ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
        PRINT "                         ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³"
        PRINT "                         ³ ³                        ³ ³"
        PRINT "                         ³ ³                        ³ ³"
        PRINT "                         ³ ³                        ³ ³"
        PRINT "                         ³ ³                        ³ ³"
        PRINT "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿     ³ ³                        ³ ³";
        PRINT "     ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"
        PRINT "³                ³     ³ ³                        ³ ³";
        PRINT "     ³                ³"
        PRINT "ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´     ³ ³                        ³ ³";
        PRINT "     ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"
        PRINT "³         ³     ³ ³                        ³ ³";
        PRINT "     ³         ³"
        PRINT "³         ³     ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³";
        PRINT "     ³         ³"
        PRINT "³         ³     ³  þþþ            o o  ÛÛÛÝ  ³";
        PRINT "     ³         ³"
        PRINT "³         ³     ÀÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÙ";
        PRINT "     ³         ³"
        PRINT "³         ³         ÚÄÄÄÄÄÙ        ÀÄÄÄÄÄ¿    ";
        PRINT "     ³         ³"
        PRINT "³         ³ÚÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄ";
        PRINT "ÄÄÄÄ¿³         ³"
        PRINT "³         ³³ ÚÄÄÄ¿                 ÄÄÄÛÛÛÛÛÛÄÄ";
        PRINT "ÄÄÄ ³³         ³"
        PRINT "³         ³³ ³   ³                  ÄÜÜÜÜÜÜÜÜÄ";
        PRINT "    ³³         ³"
        PRINT "³         ³³ ÀÄÄÄÙ                            ";
        PRINT "    ³³         ³"
        PRINT "³         Ã´                                  ";
        PRINT "    Ã´         ³"
        PRINT "ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ";
        PRINT "ÄÄÄÄÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ";

        K$ = ""
        DO UNTIL K$ <> ""

            K$ = INKEY$

            RandC = INT(RND(1) * 15 + 1)        ' Groovy light show
            RandX = INT(RND(1) * 12 + 1)
            RandY = INT(RND(1) * 4 + 1)

            COLOR RandC

            LOCATE 10 + RandY, 40 + RandX
            PRINT "þ";
            LOCATE 10 + RandY, 41 - RandX
            PRINT "þ";
            LOCATE 11 - RandY, 40 + RandX
            PRINT "þ";
            LOCATE 11 - RandY, 41 - RandX
            PRINT "þ";

            IF PEEK(Offset) = 0 THEN EXIT DO   ' Check for end
                                               ' of music file
        LOOP
        '******************************************************


        '********* Stop music *********************************
        iReg.bx = 7
        InterruptX &H80, iReg, oReg
        '******************************************************


        '********* Reset driver *******************************
        iReg.bx = 8
        InterruptX &H80, iReg, oReg
        '******************************************************

        DEF SEG

        COLOR 7, 0

        END

                                          

