home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE fxTP.ASM -- PCX Effects
- SUBTTL Copyright (c) Genus Microprogramming, Inc. 1988-89
-
- ; fxTP.ASM ;
- ; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
-
- ;****************************************************************************;
- ; ;
- ; This file contains procedures for creating tones and playing strings ;
- ; through the computer's sound chip and speaker. ;
- ; ;
- ; Procedures: fxSetSpeaker ;
- ; fxSetFrequency ;
- ; fxTone ;
- ; fxPlay ;
- ; fxPlayLeft ;
- ; fxPlayKill ;
- ; fxPlayLoop ;
- ; ;
- ; ;
- ; Microsoft ASM 5.x version. Programmer: Chris Howard 4/15/89 ;
- ; ;
- ;****************************************************************************;
-
- ; Include files
- INCLUDE ..\inc\pcxDefs.inc
- INCLUDE ..\inc\pcxMacs.inc
- INCLUDE ..\inc\pcxErrs.inc
-
- INCLUDE ..\inc\fxDefs.inc
- INCLUDE ..\inc\fxMacs.inc
- INCLUDE ..\inc\fxErrs.inc
-
- @SetModel
-
- @BegData
-
- ; C C# D D# E F F# G G# A A# B
- fxNotes dw 0
- dw 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62
- dw 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123
- dw 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247
- dw 262, 277, 294, 311, 330, 349, 370, 392, 416, 440, 466, 494
- dw 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988
- dw 1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976
- dw 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951
- dw 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6646, 7040, 7459, 7902
- dw 8372, 8870, 9398, 9956,10548,11176,11840,12544,13292,14080,14918,15804
- dw 16744,17740,18796,19912,21096,22352,23680,25088,26584,28160,29836,31608
-
- fxNoteBuf dw 4*128 dup(?)
-
- fxOctave db 4*OCTAVE ;Current note octave
- fxNoteLen dw 45 ;Current note length
- fxNoteDel dw 5 ;Current note delay
- fxTempo dw 200 ;Tempo value (whole note, in ms)
- fxMusic dw PLAYNORM ;Music mode (MN, ML, MS)
- fxMode dw PLAYFORE ;Play mode (MF, MB)
-
- fxClkOfs dw ? ;Address of old clock vector
- fxClkSeg dw ?
-
- fxCount dw 0 ;Current background note count
- fxNotePtr dw ? ;Pointer into note buffer
-
- fxLoopCnt dw 0 ;Original count, if later looping
- fxLoopNum dw 0 ;Current loop number
-
- fxDelay dw ? ;Current delay count
-
- @EndData
-
- @BegCode
-
- EXTRN fxEffectDelay : FAR
-
- PUBLIC fxSetSpeaker
- PUBLIC fxSetFrequency
- PUBLIC fxTone
- PUBLIC fxPlay
- PUBLIC fxPlayLeft
- PUBLIC fxPlayKill
- PUBLIC fxPlayLoop
- PUBLIC fxInitPData
-
- ;**********
-
- ;
- ; This procedure turns the computer speaker on and off.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- ssflag equ <[bp+ 6]> ;Speaker flag
- ssparm equ 2
-
- ;Define local variables
- ssret equ <[bp- 2]> ;Time Delay
- sslocal equ 2 ;Total local space needed
-
- fxSetSpeaker PROC FAR
-
- @Entry sslocal ;Set up frame and save regs
-
- mov ax,ssflag ;Get the flag
- cmp ax,fxON ;Turn speaker on?
- je fxSS_on
-
- in al,PPIPORT ;No, so read port
- and al,NOT PPIBITS ; mask bits
- @Port PPIPORT,al ; and send value back
-
- jmp SHORT fxSS_exit
-
- fxSS_on:
-
- in al,PPIPORT ;No, so read port
- or al,PPIBITS ; mask bits
- @Port PPIPORT,al ; and send value back
-
- fxSS_exit:
-
- @SetRet ssret,fxSUCCESS ;Set return code
-
- @Exit ssret,ssparm ;Return
-
- fxSetSpeaker ENDP
-
- ;**********
-
- ;
- ; This procedure sets the frequency on the timer chip.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- sffreq equ <[bp+ 6]> ;Speaker freq
- sfparm equ 2
-
- ;Define local variables
- sfret equ <[bp- 2]> ;Time Delay
- sflocal equ 2 ;Total local space needed
-
- fxSetFrequency PROC FAR
-
- @Entry sflocal ;Set up frame and save regs
-
- mov dx,COUNTHI ;Get the maximum count
- mov ax,COUNTLO
-
- mov bx,sffreq ;Get the requested frequency
-
- cmp bx,MINFREQ ;Make sure above minimum freq
- jae fxSF_convert
-
- jmp SHORT fxSF_exit ;Otherwise, just exit
-
- fxSF_convert:
-
- div bx ;Convert to a count
-
- mov bx,ax ;Move to safe register
-
- @Port TIMERPORT,COUNTRDY ;Get timer ready for count
-
- @Port FREQPORT,bl ;Output low count
- @Port FREQPORT,bh ; then high
-
- fxSF_exit:
-
- @SetRet sfret,fxSUCCESS ;Set return code
-
- @Exit sfret,sfparm ;Return
-
- fxSetFrequency ENDP
-
- ;**********
-
- ;
- ; This procedure sounds a tone for a specified duration.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- stfreq equ <[bp+ 8]> ;Frequency
- stdur equ <[bp+ 6]> ;Duration
- stparm equ 4
-
- ;Define local variables
- stret equ <[bp- 2]> ;Time Delay
- stlocal equ 2 ;Total local space needed
-
- fxTone PROC FAR
-
- @Entry stlocal ;Set up frame and save regs
-
- mov ax,stfreq ;Get the requested frequency
-
- cmp ax,0 ;If zero, just delay
- je fxST_delay
-
- push ax ;Set the frequency
- call fxSetFrequency
-
- mov ax,fxON ;Turn speaker on
- push ax
- call fxSetSpeaker
-
- fxST_delay:
-
- mov ax,stdur ;Get duration
- push ax
- call fxEffectDelay ;Delay
-
- mov ax,fxOFF ;Turn speaker off
- push ax
- call fxSetSpeaker
-
- @SetRet stret,fxSUCCESS ;Set return code
-
- @Exit stret,stparm ;Return
-
- fxTone ENDP
-
- ;**********
-
- ;
- ; This is a short internal subprocedure for converting an ASCII number to
- ; its numerical equivalent.
- ;
- ; Entry: es:[di] points to ASCII string
- ; Exit: bx contains number
- ;
- ;
-
- fxPlayNum PROC FAR
-
- xor ax,ax ;Clear number to zero
- xor bx,bx
-
- fxPN_loop:
-
- mov bl,es:[di] ;Get a digit
-
- cmp bl,0 ;If end of string, we are done
- jne fxPN_chknum
- jmp SHORT fxPN_exit
-
- fxPN_chknum:
-
- cmp bl,'0' ;Check limits
- jb fxPN_exit
-
- cmp bl,'9'
- ja fxPN_exit
-
- inc di ;Bump our pointer
-
- sub bl,'0' ;Convert to a number
-
- mov dx,10 ;Multiply existing number by 10
- mul dx
-
- add ax,bx ; and add this one in
-
- jmp SHORT fxPN_loop
-
- fxPN_exit:
-
- mov bx,ax ;Move into BX for return
-
- ret
-
- fxPlayNum ENDP
-
- ;**********
-
- ;
- ; This procedure parses a string and plays the associated tones.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- ptplayseg equ <[bp+ 8]> ;Play string segment
- ptplayofs equ <[bp+ 6]> ; and offset
- ptparm equ 4
-
- ;Define local variables
- ptret equ <[bp- 2]> ;Time Delay
- ptcount equ <[bp- 4]> ;Note count
- ptstr equ <pcxstrmax+4> ;Offset from bp (start at bottom)
- ptlocal equ <pcxstrmax+4> ;Total local space needed
-
- fxPlay PROC FAR
-
- @Entry ptlocal ;Set up frame and save regs
-
- @CString ptplayseg,ptplayofs,ptstr ;Convert to C string format
-
- fxPT_playwait:
-
- cmp fxCount,0 ;Loop until all background notes
- jg fxPT_playwait ; are played
-
- fxPT_init:
-
- @@LoadSeg es,ptplayseg ;Point to the string
- mov di,ptplayofs
-
- @@Data ds ;Point to the note buffer
- mov si,OFFSET fxNoteBuf
-
- mov WORD PTR ptcount,0 ;Initialize number of notes
-
- fxPT_parse:
-
- mov bl,es:[di] ;Get a note
- xor bh,bh
- inc di ; and bump pointer
-
- cmp bl,'a' ;Check if we need to capitalize
- jb fxPT_limits
-
- cmp bl,'z'
- ja fxPT_limits
-
- and bl,capmask ;Lower case, so mask to upper
-
- fxPT_limits:
-
- cmp bl,'A' ;Check limits
- jb fxPT_notnote
-
- cmp bl,'G'
- ja fxPT_notnote
-
- cmp bl,'C' ;C note
- jne fxPT_D
-
- mov bl,1
- jmp SHORT fxPT_setnote
-
- fxPT_D:
-
- cmp bl,'D' ;D note
- jne fxPT_E
-
- mov bl,3
- jmp SHORT fxPT_setnote
-
- fxPT_E:
-
- cmp bl,'E' ;E note
- jne fxPT_F
-
- mov bl,5
- jmp SHORT fxPT_setnote
-
- fxPT_F:
-
- cmp bl,'F' ;F note
- jne fxPT_G
-
- mov bl,6
- jmp SHORT fxPT_setnote
-
- fxPT_G:
-
- cmp bl,'G' ;G note
- jne fxPT_A
-
- mov bl,8
- jmp SHORT fxPT_setnote
-
- fxPT_A:
-
- cmp bl,'A' ;A note
- jne fxPT_B
-
- mov bl,10
- jmp SHORT fxPT_setnote
-
- fxPT_B:
-
- mov bl,12 ;Default to B note
-
- fxPT_setnote:
-
- add bl,fxOctave ;Add current octave
-
- mov ds:[si],bx ;Store the note number
-
- mov ax,fxNoteLen ;Default length
- mov ds:[si+2],ax
-
- xor ax,ax ;Add a pause note
- mov ds:[si+4],ax
-
- mov ax,fxNoteDel ; with the default delay
- mov ds:[si+6],ax
-
- add si,8 ;Bump
-
- inc WORD PTR ptcount ;Count this note
- inc WORD PTR ptcount
-
- jmp fxPT_chkparse
-
- fxPT_notnote:
-
- cmp bl,0 ;Is this the end of the string?
- jne fxPT_chksharp ;If not, check if a sharp
-
- jmp fxPT_play ;Otherwise, now play it
-
- cmp WORD PTR ptcount,0 ;Make sure we have counted a note
- ja fxPT_chksharp
-
- jmp SHORT fxPT_chkmusic ;If not, jump to music check
-
- fxPT_chksharp:
-
- cmp bl,'+' ;Is this a sharp?
- je fxPT_sharp ;If so, process it
-
- cmp bl,'#' ;Is this an alternate sharp?
- jne fxPT_chkflat ;If not, check for flat
-
- fxPT_sharp:
-
- inc WORD PTR ds:[si-8] ;Bump previous note up
-
- jmp fxPT_chkparse
-
- fxPT_chkflat:
-
- cmp bl,'-' ;Is this a flat?
- jne fxPT_chknotelen ;If not, check for a pause
-
- dec WORD PTR ds:[si-8] ;Bump previous note up
-
- jmp fxPT_chkparse
-
- fxPT_chknotelen:
-
- cmp bl,'0' ;Check if in number range
- jb fxPT_chkmusic
-
- cmp bl,'9'
- ja fxPT_chkmusic
-
- dec di ;Back up
- call fxPlayNum ; and convert to a number
-
- cmp bx,MINLENGTH
- jae fxPT_chknotemax
-
- mov bx,MINLENGTH
- jmp SHORT fxPT_setnotelen
-
- fxPT_chknotemax:
-
- cmp bx,MAXLENGTH ; and maximum
- jbe fxPT_setnotelen
-
- mov bx,MAXLENGTH
-
- fxPT_setnotelen:
-
- mov ax,fxTempo ;Get the current tempo
-
- xor dx,dx ;Clear high word
-
- div bx ;Divide whole note by note length
-
- push ax ;Save result
-
- mov bx,fxMusic ;Get the music mode
- mul bx ; multiply
- mov bx,8 ; and divide (to get mode)
- div bx
-
- mov ds:[si-6],ax ;Store note length
-
- pop bx ;Restore original full value
- sub bx,ax ; and sub note length
-
- mov ds:[si-2],bx ;Store the note delay
-
- jmp fxPT_chkparse
-
- fxPT_chkdot:
-
- cmp bl,'.' ;Dot?
- jne fxPT_chkmusic
-
- mov ax,ds:[si-6] ;Get the current count
- shr ax,1 ; divide by half
- add ds:[si-6],ax ; and add it back in
- jmp fxPT_chkparse
-
- fxPT_chkmusic:
-
- cmp bl,'M' ;Music command?
- jne fxPT_chkpause
-
- mov bl,es:[di] ;Get the command
- inc di
-
- cmp bl,0 ;If end of string, exit
- jne fxPT_command
- jmp fxPT_play
-
- fxPT_command:
-
- cmp bl,'a' ;Check if we need to capitalize
- jb fxPT_chkfore
-
- cmp bl,'z'
- ja fxPT_chkfore
-
- and bl,capmask ;Lower case, so mask to upper
-
- fxPT_chkfore:
-
- cmp bl,'F' ;Music Foreground?
- jne fxPT_chkback
-
- mov fxMode,PLAYFORE ;Yes, so set flag
- jmp fxPT_chkparse
-
- fxPT_chkback:
-
- cmp bl,'B' ;Music Background?
- jne fxPT_chknorm
-
- mov fxMode,PLAYBACK ;Yes, so set flag
- jmp fxPT_chkparse
-
- fxPT_chknorm:
-
- cmp bl,'N' ;Music Normal?
- jne fxPT_chkleg
-
- mov fxMusic,PLAYNORM ;Yes, so set flag
- jmp SHORT fxPT_musiclen ; and recalc defaults
-
- fxPT_chkleg:
-
- cmp bl,'L' ;Music Legato?
- jne fxPT_chkstac
-
- mov fxMusic,PLAYLEG ;Yes, so set flag
- jmp SHORT fxPT_musiclen ; and recalc defaults
-
- fxPT_chkstac:
-
- cmp bl,'S' ;Music Staccato?
- je fxPT_staccato
-
- jmp fxPT_chkparse ;No, so ignore
-
- fxPT_staccato:
-
- mov fxMusic,PLAYSTAC ;Yes, so set flag
-
- fxPT_musiclen:
-
- mov ax,fxNoteLen ;Get the default length
- add ax,fxNoteDel ; and add in the delay, for total
-
- jmp fxPT_setlen ;Now recalc under new music
-
- fxPT_chkpause:
-
- cmp bl,'P' ;Is this a pause?
- jne fxPT_chknumber ;If not, unknown
-
- mov WORD PTR ds:[si],0 ;If so, store a 0 for a pause
-
- mov ax,fxNoteLen ;Default length
- mov ds:[si+2],ax
-
- xor ax,ax ;Store a delay of zero
- mov ds:[si+4],ax
-
- mov ds:[si+6],ax
-
- add si,8
-
- inc WORD PTR ptcount ;Count this note
- inc WORD PTR ptcount
- jmp fxPT_chkparse
-
- fxPT_chknumber:
-
- cmp bl,'N' ;Is this a note number?
- jne fxPT_chkoctave ;If not, check if octave
-
- mov bl,es:[di] ;Get the number
-
- cmp bl,0 ;If end of string, exit
- jne fxPT_number
- jmp fxPT_play
-
- fxPT_number:
-
- call fxPlayNum ;Convert to a number
-
- cmp bx,MAXNOTE ;Make sure it is within limits
- jbe fxPT_setnum
-
- mov bx,MAXNOTE ;Set to max if above maximum
-
- fxPT_setnum:
-
- mov ds:[si],bx ;Store the note number
-
- mov ax,fxNoteLen ;Default length
- mov ds:[si+2],ax
-
- xor ax,ax ;Add a pause note
- mov ds:[si+4],ax
-
- mov ax,fxNoteDel ; with the default delay
- mov ds:[si+6],ax
-
- add si,8 ;Bump
-
- inc WORD PTR ptcount ;Count this note
- inc WORD PTR ptcount
-
- jmp fxPT_chkparse
-
- fxPT_chkoctave:
-
- cmp bl,'O' ;Is this an octave change?
- jne fxPT_chkupoct ;If not, check if up octave
-
- mov bl,es:[di] ;Get the octave number
- inc di
-
- cmp bl,0 ;If end of string, exit
- jne fxPT_octave
- jmp fxPT_play
-
- fxPT_octave:
-
- sub bl,'0' ;Convert to a number
-
- cmp bl,MINOCTAVE ;Check lower limit
- ja fxPT_octmax
-
- mov bl,MINOCTAVE ;If below min, set to min
-
- fxPT_octmax:
-
- cmp bl,MAXOCTAVE ;Check upper limit
- jbe fxPT_octset
-
- mov bl,MAXOCTAVE ;If above max, set to max
-
- fxPT_octset:
-
- mov ax,OCTAVE ;Move number of notes/octave
- mul bl ; and multiply by octave
-
- mov fxOctave,al ;Store
- jmp fxPT_chkparse
-
- fxPT_chkupoct:
-
- cmp bl,'>' ;Going up an octave?
- jne fxPT_chkdownoct ;If not, check if down octave
-
- mov al,fxOctave ;Get the current octave
- xor ah,ah
-
- mov bl,OCTAVE ; and notes/octave
- div bl ; and divide
-
- mov bl,al ;Get the quotient
- inc bl ; and bump it up
-
- cmp bl,MAXOCTAVE ;Is the new octave within limits?
- jbe fxPT_octset ;If so, set it using above
-
- jmp fxPT_chkparse
-
- fxPT_chkdownoct:
-
- cmp bl,'<' ;Going down an octave?
- jne fxPT_chklength ;If not, check if length
-
- mov al,fxOctave ;Get the current octave
- xor ah,ah
-
- mov bl,OCTAVE ; and notes/octave
- div bl ; and divide
-
- mov bl,al ;Get the quotient
- dec bl ; and bump it down
-
- cmp bl,MINOCTAVE ;Is the new octave within limits?
- jae fxPT_octset ;If so, set it using above
-
- jmp fxPT_chkparse
-
- fxPT_chklength:
-
- cmp bl,'L' ;Is this a length default?
- jne fxPT_chktempo ;If not, check for tempo
-
- mov bl,es:[di] ;Get the number
-
- cmp bl,0 ;If end of string, exit
- jne fxPT_length
- jmp SHORT fxPT_play
-
- fxPT_length:
-
- call fxPlayNum ;Convert to a number
-
- cmp bx,MINLENGTH ;Check minimum
- jae fxPT_chklenmax
-
- mov bx,MINLENGTH
- jmp SHORT fxPT_calclen
-
- fxPT_chklenmax:
-
- cmp bx,MAXLENGTH ; and maximum
- jbe fxPT_calclen
-
- mov bx,MAXLENGTH
-
- fxPT_calclen:
-
- mov ax,fxTempo ;Get the current tempo
- xor dx,dx ;Clear high word
-
- div bx ;Divide whole note by note length
-
- fxPT_setlen:
-
- push ax ;Save result
-
- mov bx,fxMusic ;Get the music mode
- mul bx ; multiply
- mov bx,8 ; and divide (to get mode)
- div bx
-
- mov fxNoteLen,ax ;Store note length
-
- pop bx ;Restore original full value
- sub bx,ax ; and sub note length
-
- mov fxNoteDel,bx ;Store the note delay
-
- jmp SHORT fxPT_chkparse
-
- fxPT_chktempo:
-
- cmp bl,'T' ;Is this a length default?
- jne fxPT_chkparse ;If not, check for tempo
-
- mov bl,es:[di] ;Get the number
-
- cmp bl,0 ;If end of string, exit
- jne fxPT_tempo
- jmp SHORT fxPT_play
-
- fxPT_tempo:
-
- call fxPlayNum ;Convert to a number
-
- cmp bx,MINTEMPO ;Check minimum
- jae fxPT_chktempomax
-
- mov bx,MINTEMPO
- jmp SHORT fxPT_settempo
-
- fxPT_chktempomax:
-
- cmp bx,MAXTEMPO ; and maximum
- jbe fxPT_settempo
-
- mov bx,MAXTEMPO
-
- fxPT_settempo:
-
- mov ax,60*100 ;Number of milliseconds/second
- xor dx,dx
-
- div bx ;Divide by quarternotes/second
-
- shl ax,1 ;Get a whole note value, in ms
- shl ax,1
-
- mov fxTempo,ax ;Store the new tempo
-
- mov ax,fxNoteLen ;Get the default length
- add ax,fxNoteDel ; and add in the delay, for total
-
- jmp fxPT_setlen ;Now recalc under new tempo
-
- fxPT_chkparse:
-
- jmp fxPT_parse ;Continue parsing
-
- fxPT_play:
-
- mov ax,ptcount ;Get number of notes
- cmp ax,0 ;If not zero,
- jg fxPT_getptrs ; continue
-
- jmp fxPT_exit ; otherwise exit
-
- fxPT_getptrs:
-
- @@Data es
- mov si,OFFSET fxNotes ;Point to tone frequencies
- mov di,OFFSET fxNoteBuf
-
- cmp fxMode,PLAYBACK ;Play in background?
- jne fxPT_playfore
- jmp SHORT fxPT_playback ;If yes, do it
-
- fxPT_playfore:
-
- mov cx,ptcount ;Get number of notes
-
- fxPT_loop:
-
- mov bx,WORD PTR es:[di] ;Get a tone
- shl bx,1 ;Shift since it is a word pointer
-
- mov ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
- mov bx,WORD PTR es:[di+2] ; with the length
-
- cmp bx,0 ;Zero length?
- je fxPT_forebump ;If so, skip
-
- push ax ;Now sound the tone
- push bx
- call fxTone
-
- fxPT_forebump:
-
- inc di ;Bump pointer past this note
- inc di
- inc di
- inc di
-
- fxPT_chkloop:
-
- loop fxPT_loop ;Loop until all notes are played
-
- cmp fxLoopNum,0 ;Are we supposed to loop?
- je fxPT_exit ;If not, exit
-
- cmp fxLoopNum,-1 ;Infinite loop?
- je fxPT_foreloop
-
- dec fxLoopNum ;If so, count this loop
- jz fxPT_exit ; and if zero, exit
-
- fxPT_foreloop:
-
- jmp SHORT fxPT_playfore ;Otherwise, play again
-
- fxPT_playback:
-
- mov fxNotePtr,OFFSET fxNoteBuf ;Store the note buffer pointer
- mov ax,ptcount ; and the count globally
- mov fxCount,ax
- mov fxLoopCnt,ax
-
- mov bx,WORD PTR es:[di] ;Get a tone
- shl bx,1 ;Shift since it is a word pointer
-
- mov ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
-
- push ax ;Now set the tone
- call fxSetFrequency
-
- mov ax,WORD PTR es:[di+2] ;Get the length
- mov fxDelay,ax
-
- mov ax,fxON ; and turn the speaker on
- push ax
- call fxSetSpeaker
-
- mov al,INT_TIMER ;Get the timer vector
- @DOS GETVECT
-
- mov ax,es ;Store the segment
- mov fxClkSeg,ax
-
- mov fxClkOfs,bx ; and offset
-
- mov dx,OFFSET fxPlayInt ;Get the offset and
- @@LoadSeg ds,cs ; and code segment
-
- mov al,INT_TIMER ;Set the timer vector
- @DOS SETVECT
-
- fxPT_exit:
-
- @SetRet ptret,fxSUCCESS ;Set return code
-
- @Exit ptret,ptparm ;Return
-
- fxPlay ENDP
-
- ;**********
-
- ;
- ; This procedure plays the parsed music string in the background.
- ; It recieves control on the timer interrupt.
- ;
- ;
-
-
- fxPlayInt PROC FAR
-
- pushf ;Save everything
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push ds
- push es
-
- sti ;Turn interrupts back on
-
- @@Data ds ;Point to note frequencies
- mov si,OFFSET fxNotes
- @@Data es ; and the note buffer
- mov di,fxNotePtr
-
- sub fxDelay,fxCLICK ;subtract value of one click
-
- cmp fxDelay,0 ;Have we reached zero?
- jle fxPI_count ;If yes, count this note
-
- jmp fxPI_exit ;If not, exit now
-
- fxPI_count:
-
- dec fxCount ;Yes, so count this note
- cmp fxCount,0 ;Have we done them all?
- jle fxPI_stop
-
- inc di ;No, so bump pointer
- inc di
- inc di
- inc di
-
- mov fxNotePtr,di ; and store
-
- mov ax,fxOFF ;Turn the speaker off
- push ax
- call fxSetSpeaker
-
- fxPI_gettone:
-
- mov bx,WORD PTR es:[di] ;Get a tone
- shl bx,1 ;Shift since it is a word pointer
-
- mov ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
- cmp ax,0
- je fxPI_delay
-
- push ax ;Now sound the tone
- call fxSetFrequency
-
- mov ax,fxON ;Turn the speaker on
- push ax
- call fxSetSpeaker
-
- fxPI_delay:
-
- mov ax,WORD PTR es:[di+2] ;Get the delay
- mov fxDelay,ax
-
- jmp SHORT fxPI_exit ; and exit
-
- fxPI_stop:
-
- mov ax,fxOFF ;Turn the speaker off
- push ax
- call fxSetSpeaker
-
- cmp fxLoopNum,0 ;Are we supposed to loop?
- je fxPI_zero
-
- cmp fxLoopNum,-1 ;Infinite Loop?
- je fxPI_initloop
-
- dec fxLoopNum ;Count this loop
- jz fxPI_zero ; and if zero, exit
-
- fxPI_initloop:
-
- mov di,OFFSET fxNoteBuf ;Set up note pointer
- mov fxNotePtr,di
-
- mov ax,fxLoopCnt ;Set up note count
- mov fxCount,ax
-
- jmp SHORT fxPI_gettone
-
- fxPI_zero:
-
- mov fxCount,0 ;Make sure count is zeroed
-
- cli ;Make sure we are not interrupted
-
- @@LoadSeg es,0 ;Point to vector table
- mov di,INT_TIMER*4
-
- mov ax,fxClkOfs ;Restore old vector (bypass DOS,
- mov es:[di],ax
- mov ax,fxClkSeg ; since it is not reentrant)
- mov es:[di+2],ax
-
- fxPI_exit:
-
- pop es ;Restore regs
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- popf
-
- iret
-
- fxPlayInt ENDP
-
- ;**********
-
- ;
- ; This procedure returns the number of notes left in the buffer.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- plparm equ 0
-
- ;Define local variables
- plret equ <[bp- 2]> ;Time Delay
- pllocal equ 2 ;Total local space needed
-
- fxPlayLeft PROC FAR
-
- @Entry pllocal ;Set up frame and save regs
-
- mov ax,fxCount ;Get the notes remaining
- shr ax,1 ; divide by 2 to get actual
-
- @SetRet plret,ax ; and return them
-
- @Exit plret,plparm ;Return
-
- fxPlayLeft ENDP
-
- ;**********
-
- ;
- ; This procedure kills the background music process.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- pkparm equ 0
-
- ;Define local variables
- pkret equ <[bp- 2]> ;Time Delay
- pklocal equ 2 ;Total local space needed
-
- fxPlayKill PROC FAR
-
- @Entry pklocal ;Set up frame and save regs
-
- mov fxLoopNum,0 ;Zero out the loop count
-
- mov fxCount,0 ;Zero out 'Notes Remaining' Count
-
- @SetRet pkret,fxSUCCESS ; and return
-
- @Exit pkret,pkparm ;Return
-
- fxPlayKill ENDP
-
- ;**********
-
- ;
- ; This procedure handles whether the play buffer should loop or not.
- ;
- ;
-
- ;Define variable locations on the stack (pascal model)
- poloopnum equ <[bp+ 6]> ;Loop Flag
- poparm equ 2
-
- ;Define local variables
- poret equ <[bp- 2]> ;Time Delay
- polocal equ 2 ;Total local space needed
-
- fxPlayLoop PROC FAR
-
- @Entry polocal ;Set up frame and save regs
-
- mov ax,poloopnum ;Get the loop flag
-
- mov fxLoopNum,ax ;Store it
-
- @SetRet poret,fxSUCCESS ; and return
-
- @Exit poret,poparm ;Return
-
- fxPlayLoop ENDP
-
- ;**********
-
- ;
- ; This procedure is used to initialize all of the fx music data. It is
- ; called only once by languages that do not permit static data (like
- ; Turbo Pascal).
- ;
- ; Calling: fxInitPData()
- ;
- ;
-
- ;Define variable locations on the stack, depending on model
- idparm equ 0
-
- ;Define local variables
- idret equ <[bp-2]> ;return code
- idlocal equ 2 ;Total local space needed
-
- fxInitPData PROC FAR
-
- @Entry idlocal ;Set up frame and save regs
-
- @SetRet idret,fxSUCCESS ;Assume successful
-
- mov fxOctave,4*OCTAVE ;Default octave
- mov fxNoteLen,45 ;Default note length
- mov fxNoteDel,5 ; and delay
- mov fxTempo,200 ;Default tempo
- mov fxMusic,PLAYNORM ;Play normally
- mov fxMode,PLAYFORE ; and in the foreground
-
- mov fxCount,0 ;Zero out the 'notes left'
-
- mov fxLoopCnt,0 ; and loop counters
- mov fxLoopNum,0
-
- mov si,OFFSET fxNotes
-
- mov WORD PTR ds:[si],0
- inc si
- inc si
-
- IRP x,< 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 262, 277, 294, 311, 330, 349, 370, 392, 416, 440, 466, 494>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6646, 7040, 7459, 7902>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,< 8372, 8870, 9398, 9956,10548,11176,11840,12544,13292,14080,14918,15804>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- IRP x,<16744,17740,18796,19912,21096,22352,23680,25088,26584,28160,29836,31608>
- mov WORD PTR ds:[si],x
- inc si
- inc si
- ENDM
-
- pcxID_exit:
-
- @Exit idret,idparm ;Return
-
- fxInitPData ENDP
-
- @EndCode
-
- END
-
-