'=========================================================================== ' 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