home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c011 / 1.ddi / SOURCE / FXTP.ASM < prev    next >
Encoding:
Assembly Source File  |  1989-06-01  |  37.5 KB  |  1,243 lines

  1.   PAGE    60,132
  2.   TITLE   fxTP.ASM -- PCX Effects
  3.   SUBTTL  Copyright (c) Genus Microprogramming, Inc. 1988-89
  4.  
  5. ; fxTP.ASM                                                                   ;
  6. ; Copyright (c) Genus Microprogramming, Inc. 1988-89  All Rights Reserved.   ;
  7.  
  8. ;****************************************************************************;
  9. ;                                                                            ;
  10. ; This file contains procedures for creating tones and playing strings       ;
  11. ; through the computer's sound chip and speaker.                             ;
  12. ;                                                                            ;
  13. ; Procedures: fxSetSpeaker                                                   ;
  14. ;             fxSetFrequency                                                 ;
  15. ;             fxTone                                                         ;
  16. ;             fxPlay                                                         ;
  17. ;             fxPlayLeft                                                     ;
  18. ;             fxPlayKill                                                     ;
  19. ;             fxPlayLoop                                                     ;
  20. ;                                                                            ;
  21. ;                                                                            ;
  22. ; Microsoft ASM 5.x version.              Programmer: Chris Howard  4/15/89  ;
  23. ;                                                                            ;
  24. ;****************************************************************************;
  25.  
  26. ; Include files
  27.   INCLUDE ..\inc\pcxDefs.inc
  28.   INCLUDE ..\inc\pcxMacs.inc
  29.   INCLUDE ..\inc\pcxErrs.inc
  30.  
  31.   INCLUDE ..\inc\fxDefs.inc
  32.   INCLUDE ..\inc\fxMacs.inc
  33.   INCLUDE ..\inc\fxErrs.inc
  34.  
  35.   @SetModel
  36.  
  37.   @BegData
  38.  
  39. ;                   C     C#    D      D#    E     F     F#    G     G#    A     A#    B
  40. fxNotes   dw            0                                                              
  41.           dw           33,   35,   37,   39,   41,   44,   46,   49,   52,   55,   58,   62
  42.           dw           65,   69,   73,   78,   82,   87,   93,   98,  104,  110,  117,  123
  43.           dw          131,  139,  147,  156,  165,  175,  185,  196,  208,  220,  233,  247
  44.           dw          262,  277,  294,  311,  330,  349,  370,  392,  416,  440,  466,  494
  45.           dw          523,  554,  587,  622,  659,  698,  740,  784,  831,  880,  932,  988
  46.           dw         1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976
  47.           dw         2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951
  48.           dw         4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6646, 7040, 7459, 7902
  49.           dw         8372, 8870, 9398, 9956,10548,11176,11840,12544,13292,14080,14918,15804
  50.           dw        16744,17740,18796,19912,21096,22352,23680,25088,26584,28160,29836,31608
  51.  
  52. fxNoteBuf dw        4*128 dup(?)
  53.  
  54. fxOctave  db        4*OCTAVE                ;Current note octave
  55. fxNoteLen dw        45                      ;Current note length
  56. fxNoteDel dw        5                       ;Current note delay 
  57. fxTempo   dw        200                     ;Tempo value (whole note, in ms)
  58. fxMusic   dw        PLAYNORM                ;Music mode (MN, ML, MS)
  59. fxMode    dw        PLAYFORE                ;Play  mode (MF, MB)
  60.  
  61. fxClkOfs  dw        ?                       ;Address of old clock vector
  62. fxClkSeg  dw        ?
  63.  
  64. fxCount   dw        0                       ;Current background note count
  65. fxNotePtr dw        ?                       ;Pointer into note buffer
  66.  
  67. fxLoopCnt dw        0                       ;Original count, if later looping
  68. fxLoopNum dw        0                       ;Current loop number
  69.  
  70. fxDelay   dw        ?                       ;Current delay count
  71.  
  72.   @EndData
  73.  
  74.   @BegCode
  75.  
  76.           EXTRN     fxEffectDelay           : FAR
  77.  
  78.           PUBLIC    fxSetSpeaker
  79.           PUBLIC    fxSetFrequency
  80.           PUBLIC    fxTone
  81.           PUBLIC    fxPlay
  82.           PUBLIC    fxPlayLeft
  83.           PUBLIC    fxPlayKill
  84.           PUBLIC    fxPlayLoop
  85.           PUBLIC    fxInitPData
  86.  
  87. ;**********
  88.  
  89. ;
  90. ; This procedure turns the computer speaker on and off.
  91. ;
  92. ;
  93.  
  94. ;Define variable locations on the stack  (pascal model)
  95. ssflag    equ       <[bp+ 6]>               ;Speaker flag  
  96. ssparm    equ       2
  97.  
  98. ;Define local variables
  99. ssret     equ       <[bp- 2]>               ;Time Delay    
  100. sslocal   equ       2                       ;Total local space needed
  101.  
  102. fxSetSpeaker        PROC FAR
  103.  
  104.           @Entry    sslocal                 ;Set up frame and save regs
  105.  
  106.           mov       ax,ssflag               ;Get the flag
  107.           cmp       ax,fxON                 ;Turn speaker on?
  108.           je        fxSS_on
  109.  
  110.           in        al,PPIPORT              ;No, so read port
  111.           and       al,NOT PPIBITS          ; mask bits
  112.           @Port     PPIPORT,al              ; and send value back
  113.  
  114.           jmp       SHORT fxSS_exit
  115.  
  116. fxSS_on:
  117.  
  118.           in        al,PPIPORT              ;No, so read port
  119.           or        al,PPIBITS              ; mask bits
  120.           @Port     PPIPORT,al              ; and send value back
  121.  
  122. fxSS_exit:
  123.  
  124.           @SetRet   ssret,fxSUCCESS         ;Set return code
  125.  
  126.           @Exit     ssret,ssparm            ;Return
  127.  
  128. fxSetSpeaker        ENDP
  129.  
  130. ;**********
  131.  
  132. ;
  133. ; This procedure sets the frequency on the timer chip. 
  134. ;
  135. ;
  136.  
  137. ;Define variable locations on the stack  (pascal model)
  138. sffreq    equ       <[bp+ 6]>               ;Speaker freq  
  139. sfparm    equ       2
  140.  
  141. ;Define local variables
  142. sfret     equ       <[bp- 2]>               ;Time Delay    
  143. sflocal   equ       2                       ;Total local space needed
  144.  
  145. fxSetFrequency      PROC FAR
  146.  
  147.           @Entry    sflocal                 ;Set up frame and save regs
  148.  
  149.           mov       dx,COUNTHI              ;Get the maximum count
  150.           mov       ax,COUNTLO
  151.  
  152.           mov       bx,sffreq               ;Get the requested frequency
  153.  
  154.           cmp       bx,MINFREQ              ;Make sure above minimum freq
  155.           jae       fxSF_convert
  156.  
  157.           jmp       SHORT fxSF_exit         ;Otherwise, just exit 
  158.  
  159. fxSF_convert:
  160.  
  161.           div       bx                      ;Convert to a count
  162.  
  163.           mov       bx,ax                   ;Move to safe register
  164.  
  165.           @Port     TIMERPORT,COUNTRDY      ;Get timer ready for count
  166.  
  167.           @Port     FREQPORT,bl             ;Output low count
  168.           @Port     FREQPORT,bh             ; then high
  169.  
  170. fxSF_exit:
  171.  
  172.           @SetRet   sfret,fxSUCCESS         ;Set return code
  173.  
  174.           @Exit     sfret,sfparm            ;Return
  175.  
  176. fxSetFrequency      ENDP
  177.  
  178. ;**********
  179.  
  180. ;
  181. ; This procedure sounds a tone for a specified duration.   
  182. ;
  183. ;
  184.  
  185. ;Define variable locations on the stack  (pascal model)
  186. stfreq    equ       <[bp+ 8]>               ;Frequency     
  187. stdur     equ       <[bp+ 6]>               ;Duration      
  188. stparm    equ       4
  189.  
  190. ;Define local variables
  191. stret     equ       <[bp- 2]>               ;Time Delay    
  192. stlocal   equ       2                       ;Total local space needed
  193.  
  194. fxTone              PROC FAR
  195.  
  196.           @Entry    stlocal                 ;Set up frame and save regs
  197.  
  198.           mov       ax,stfreq               ;Get the requested frequency
  199.  
  200.           cmp       ax,0                    ;If zero, just delay
  201.           je        fxST_delay
  202.  
  203.           push      ax                      ;Set the frequency
  204.           call      fxSetFrequency          
  205.  
  206.           mov       ax,fxON                 ;Turn speaker on
  207.           push      ax
  208.           call      fxSetSpeaker
  209.  
  210. fxST_delay:
  211.  
  212.           mov       ax,stdur                ;Get duration
  213.           push      ax
  214.           call      fxEffectDelay           ;Delay
  215.  
  216.           mov       ax,fxOFF                ;Turn speaker off
  217.           push      ax
  218.           call      fxSetSpeaker
  219.  
  220.           @SetRet   stret,fxSUCCESS         ;Set return code
  221.  
  222.           @Exit     stret,stparm            ;Return
  223.  
  224. fxTone              ENDP
  225.  
  226. ;**********
  227.  
  228. ;
  229. ; This is a short internal subprocedure for converting an ASCII number to
  230. ; its numerical equivalent.
  231. ;
  232. ; Entry: es:[di] points to ASCII string
  233. ;  Exit: bx      contains number
  234. ;
  235. ;
  236.  
  237. fxPlayNum           PROC FAR
  238.  
  239.           xor       ax,ax                   ;Clear number to zero
  240.           xor       bx,bx
  241.  
  242. fxPN_loop:
  243.  
  244.           mov       bl,es:[di]              ;Get a digit
  245.  
  246.           cmp       bl,0                    ;If end of string, we are done
  247.           jne       fxPN_chknum
  248.           jmp       SHORT fxPN_exit
  249.  
  250. fxPN_chknum:
  251.  
  252.           cmp       bl,'0'                  ;Check limits
  253.           jb        fxPN_exit
  254.  
  255.           cmp       bl,'9'
  256.           ja        fxPN_exit
  257.  
  258.           inc       di                      ;Bump our pointer
  259.  
  260.           sub       bl,'0'                  ;Convert to a number
  261.  
  262.           mov       dx,10                   ;Multiply existing number by 10
  263.           mul       dx
  264.  
  265.           add       ax,bx                   ; and add this one in
  266.  
  267.           jmp       SHORT fxPN_loop
  268.  
  269. fxPN_exit:
  270.  
  271.           mov       bx,ax                   ;Move into BX for return
  272.  
  273.           ret
  274.  
  275. fxPlayNum           ENDP
  276.  
  277. ;**********
  278.  
  279. ;
  280. ; This procedure parses a string and plays the associated tones.
  281. ;
  282. ;
  283.  
  284. ;Define variable locations on the stack  (pascal model)
  285. ptplayseg equ       <[bp+ 8]>               ;Play string segment
  286. ptplayofs equ       <[bp+ 6]>               ; and offset   
  287. ptparm    equ       4
  288.  
  289. ;Define local variables
  290. ptret     equ       <[bp- 2]>               ;Time Delay    
  291. ptcount   equ       <[bp- 4]>               ;Note count    
  292. ptstr     equ       <pcxstrmax+4>           ;Offset from bp (start at bottom)
  293. ptlocal   equ       <pcxstrmax+4>           ;Total local space needed
  294.  
  295. fxPlay              PROC FAR
  296.  
  297.           @Entry    ptlocal                 ;Set up frame and save regs
  298.  
  299.           @CString  ptplayseg,ptplayofs,ptstr ;Convert to C string format
  300.  
  301. fxPT_playwait:
  302.  
  303.           cmp       fxCount,0               ;Loop until all background notes
  304.           jg        fxPT_playwait           ; are played
  305.  
  306. fxPT_init:
  307.  
  308.           @@LoadSeg es,ptplayseg            ;Point to the string
  309.           mov       di,ptplayofs
  310.  
  311.           @@Data    ds                      ;Point to the note buffer
  312.           mov       si,OFFSET fxNoteBuf
  313.  
  314.           mov       WORD PTR ptcount,0      ;Initialize number of notes
  315.  
  316. fxPT_parse:
  317.  
  318.           mov       bl,es:[di]              ;Get a note
  319.           xor       bh,bh
  320.           inc       di                      ; and bump pointer
  321.  
  322.           cmp       bl,'a'                  ;Check if we need to capitalize
  323.           jb        fxPT_limits
  324.  
  325.           cmp       bl,'z'
  326.           ja        fxPT_limits
  327.  
  328.           and       bl,capmask              ;Lower case, so mask to upper
  329.  
  330. fxPT_limits:
  331.  
  332.           cmp       bl,'A'                  ;Check limits
  333.           jb        fxPT_notnote
  334.  
  335.           cmp       bl,'G'
  336.           ja        fxPT_notnote
  337.  
  338.           cmp       bl,'C'                  ;C note
  339.           jne       fxPT_D
  340.  
  341.           mov       bl,1
  342.           jmp       SHORT fxPT_setnote
  343.  
  344. fxPT_D:
  345.  
  346.           cmp       bl,'D'                  ;D note
  347.           jne       fxPT_E
  348.  
  349.           mov       bl,3
  350.           jmp       SHORT fxPT_setnote
  351.  
  352. fxPT_E:
  353.  
  354.           cmp       bl,'E'                  ;E note
  355.           jne       fxPT_F
  356.  
  357.           mov       bl,5
  358.           jmp       SHORT fxPT_setnote
  359.  
  360. fxPT_F:
  361.  
  362.           cmp       bl,'F'                  ;F note
  363.           jne       fxPT_G
  364.  
  365.           mov       bl,6
  366.           jmp       SHORT fxPT_setnote
  367.  
  368. fxPT_G:
  369.  
  370.           cmp       bl,'G'                  ;G note
  371.           jne       fxPT_A
  372.  
  373.           mov       bl,8
  374.           jmp       SHORT fxPT_setnote
  375.  
  376. fxPT_A:
  377.  
  378.           cmp       bl,'A'                  ;A note
  379.           jne       fxPT_B
  380.  
  381.           mov       bl,10
  382.           jmp       SHORT fxPT_setnote
  383.  
  384. fxPT_B:
  385.  
  386.           mov       bl,12                   ;Default to B note
  387.  
  388. fxPT_setnote:
  389.  
  390.           add       bl,fxOctave             ;Add current octave
  391.  
  392.           mov       ds:[si],bx              ;Store the note number
  393.  
  394.           mov       ax,fxNoteLen            ;Default length
  395.           mov       ds:[si+2],ax  
  396.  
  397.           xor       ax,ax                   ;Add a pause note
  398.           mov       ds:[si+4],ax     
  399.  
  400.           mov       ax,fxNoteDel            ; with the default delay
  401.           mov       ds:[si+6],ax     
  402.  
  403.           add       si,8                    ;Bump
  404.  
  405.           inc       WORD PTR ptcount        ;Count this note
  406.           inc       WORD PTR ptcount
  407.  
  408.           jmp       fxPT_chkparse     
  409.  
  410. fxPT_notnote:
  411.  
  412.           cmp       bl,0                    ;Is this the end of the string?
  413.           jne       fxPT_chksharp           ;If not, check if a sharp
  414.  
  415.           jmp       fxPT_play               ;Otherwise, now play it
  416.  
  417.           cmp       WORD PTR ptcount,0      ;Make sure we have counted a note
  418.           ja        fxPT_chksharp
  419.  
  420.           jmp       SHORT fxPT_chkmusic     ;If not, jump to music check
  421.  
  422. fxPT_chksharp:
  423.  
  424.           cmp       bl,'+'                  ;Is this a sharp?
  425.           je        fxPT_sharp              ;If so, process it     
  426.  
  427.           cmp       bl,'#'                  ;Is this an alternate sharp?
  428.           jne       fxPT_chkflat            ;If not, check for flat
  429.  
  430. fxPT_sharp:
  431.           
  432.           inc       WORD PTR ds:[si-8]      ;Bump previous note up
  433.  
  434.           jmp       fxPT_chkparse
  435.  
  436. fxPT_chkflat:
  437.           
  438.           cmp       bl,'-'                  ;Is this a flat?
  439.           jne       fxPT_chknotelen         ;If not, check for a pause
  440.           
  441.           dec       WORD PTR ds:[si-8]      ;Bump previous note up
  442.  
  443.           jmp       fxPT_chkparse
  444.  
  445. fxPT_chknotelen:
  446.  
  447.           cmp       bl,'0'                  ;Check if in number range
  448.           jb        fxPT_chkmusic           
  449.  
  450.           cmp       bl,'9'
  451.           ja        fxPT_chkmusic
  452.  
  453.           dec       di                      ;Back up 
  454.           call      fxPlayNum               ; and convert to a number
  455.  
  456.           cmp       bx,MINLENGTH
  457.           jae       fxPT_chknotemax
  458.  
  459.           mov       bx,MINLENGTH
  460.           jmp       SHORT fxPT_setnotelen
  461.  
  462. fxPT_chknotemax:
  463.  
  464.           cmp       bx,MAXLENGTH            ; and maximum
  465.           jbe       fxPT_setnotelen
  466.  
  467.           mov       bx,MAXLENGTH
  468.  
  469. fxPT_setnotelen:
  470.  
  471.           mov       ax,fxTempo              ;Get the current tempo
  472.  
  473.           xor       dx,dx                   ;Clear high word
  474.  
  475.           div       bx                      ;Divide whole note by note length
  476.  
  477.           push      ax                      ;Save result
  478.  
  479.           mov       bx,fxMusic              ;Get the music mode
  480.           mul       bx                      ; multiply
  481.           mov       bx,8                    ; and divide (to get mode)
  482.           div       bx
  483.  
  484.           mov       ds:[si-6],ax            ;Store note length
  485.  
  486.           pop       bx                      ;Restore original full value
  487.           sub       bx,ax                   ; and sub note length
  488.  
  489.           mov       ds:[si-2],bx            ;Store the note delay
  490.  
  491.           jmp       fxPT_chkparse
  492.  
  493. fxPT_chkdot:   
  494.  
  495.           cmp       bl,'.'                  ;Dot?
  496.           jne       fxPT_chkmusic
  497.  
  498.           mov       ax,ds:[si-6]            ;Get the current count
  499.           shr       ax,1                    ; divide by half
  500.           add       ds:[si-6],ax            ; and add it back in
  501.           jmp       fxPT_chkparse
  502.  
  503. fxPT_chkmusic:
  504.  
  505.           cmp       bl,'M'                  ;Music command?
  506.           jne       fxPT_chkpause
  507.  
  508.           mov       bl,es:[di]              ;Get the command
  509.           inc       di
  510.  
  511.           cmp       bl,0                    ;If end of string, exit
  512.           jne       fxPT_command
  513.           jmp       fxPT_play
  514.  
  515. fxPT_command:
  516.  
  517.           cmp       bl,'a'                  ;Check if we need to capitalize
  518.           jb        fxPT_chkfore
  519.  
  520.           cmp       bl,'z'
  521.           ja        fxPT_chkfore
  522.  
  523.           and       bl,capmask              ;Lower case, so mask to upper
  524.  
  525. fxPT_chkfore:
  526.  
  527.           cmp       bl,'F'                  ;Music Foreground?
  528.           jne       fxPT_chkback
  529.  
  530.           mov       fxMode,PLAYFORE         ;Yes, so set flag
  531.           jmp       fxPT_chkparse
  532.  
  533. fxPT_chkback:
  534.  
  535.           cmp       bl,'B'                  ;Music Background?
  536.           jne       fxPT_chknorm
  537.  
  538.           mov       fxMode,PLAYBACK         ;Yes, so set flag
  539.           jmp       fxPT_chkparse
  540.  
  541. fxPT_chknorm:
  542.  
  543.           cmp       bl,'N'                  ;Music Normal?
  544.           jne       fxPT_chkleg             
  545.  
  546.           mov       fxMusic,PLAYNORM        ;Yes, so set flag
  547.           jmp       SHORT fxPT_musiclen     ; and recalc defaults
  548.  
  549. fxPT_chkleg:
  550.  
  551.           cmp       bl,'L'                  ;Music Legato?
  552.           jne       fxPT_chkstac            
  553.  
  554.           mov       fxMusic,PLAYLEG         ;Yes, so set flag
  555.           jmp       SHORT fxPT_musiclen     ; and recalc defaults
  556.  
  557. fxPT_chkstac:
  558.  
  559.           cmp       bl,'S'                  ;Music Staccato?
  560.           je        fxPT_staccato           
  561.  
  562.           jmp       fxPT_chkparse           ;No, so ignore
  563.  
  564. fxPT_staccato:
  565.  
  566.           mov       fxMusic,PLAYSTAC        ;Yes, so set flag
  567.  
  568. fxPT_musiclen:
  569.  
  570.           mov       ax,fxNoteLen            ;Get the default length
  571.           add       ax,fxNoteDel            ; and add in the delay, for total
  572.  
  573.           jmp       fxPT_setlen             ;Now recalc under new music
  574.  
  575. fxPT_chkpause:
  576.           
  577.           cmp       bl,'P'                  ;Is this a pause?
  578.           jne       fxPT_chknumber          ;If not, unknown           
  579.           
  580.           mov       WORD PTR ds:[si],0      ;If so, store a 0 for a pause
  581.  
  582.           mov       ax,fxNoteLen            ;Default length
  583.           mov       ds:[si+2],ax
  584.  
  585.           xor       ax,ax                   ;Store a delay of zero
  586.           mov       ds:[si+4],ax
  587.  
  588.           mov       ds:[si+6],ax
  589.  
  590.           add       si,8
  591.  
  592.           inc       WORD PTR ptcount        ;Count this note
  593.           inc       WORD PTR ptcount
  594.           jmp       fxPT_chkparse
  595.  
  596. fxPT_chknumber:
  597.           
  598.           cmp       bl,'N'                  ;Is this a note number?
  599.           jne       fxPT_chkoctave          ;If not, check if octave   
  600.           
  601.           mov       bl,es:[di]              ;Get the number
  602.  
  603.           cmp       bl,0                    ;If end of string, exit
  604.           jne       fxPT_number
  605.           jmp       fxPT_play
  606.  
  607. fxPT_number:
  608.  
  609.           call      fxPlayNum               ;Convert to a number
  610.  
  611.           cmp       bx,MAXNOTE              ;Make sure it is within limits
  612.           jbe       fxPT_setnum
  613.  
  614.           mov       bx,MAXNOTE              ;Set to max if above maximum
  615.  
  616. fxPT_setnum:
  617.  
  618.           mov       ds:[si],bx              ;Store the note number
  619.  
  620.           mov       ax,fxNoteLen            ;Default length
  621.           mov       ds:[si+2],ax  
  622.  
  623.           xor       ax,ax                   ;Add a pause note
  624.           mov       ds:[si+4],ax     
  625.  
  626.           mov       ax,fxNoteDel            ; with the default delay
  627.           mov       ds:[si+6],ax     
  628.  
  629.           add       si,8                    ;Bump
  630.  
  631.           inc       WORD PTR ptcount        ;Count this note
  632.           inc       WORD PTR ptcount
  633.  
  634.           jmp       fxPT_chkparse
  635.  
  636. fxPT_chkoctave:
  637.           
  638.           cmp       bl,'O'                  ;Is this an octave change?
  639.           jne       fxPT_chkupoct           ;If not, check if up octave
  640.           
  641.           mov       bl,es:[di]              ;Get the octave number
  642.           inc       di
  643.  
  644.           cmp       bl,0                    ;If end of string, exit
  645.           jne       fxPT_octave
  646.           jmp       fxPT_play
  647.  
  648. fxPT_octave:
  649.  
  650.           sub       bl,'0'                  ;Convert to a number
  651.  
  652.           cmp       bl,MINOCTAVE            ;Check lower limit
  653.           ja        fxPT_octmax
  654.  
  655.           mov       bl,MINOCTAVE            ;If below min, set to min
  656.  
  657. fxPT_octmax:
  658.           
  659.           cmp       bl,MAXOCTAVE            ;Check upper limit
  660.           jbe       fxPT_octset
  661.  
  662.           mov       bl,MAXOCTAVE            ;If above max, set to max
  663.  
  664. fxPT_octset:
  665.  
  666.           mov       ax,OCTAVE               ;Move number of notes/octave
  667.           mul       bl                      ; and multiply by octave
  668.  
  669.           mov       fxOctave,al             ;Store
  670.           jmp       fxPT_chkparse
  671.  
  672. fxPT_chkupoct:
  673.  
  674.           cmp       bl,'>'                  ;Going up an octave?
  675.           jne       fxPT_chkdownoct         ;If not, check if down octave
  676.  
  677.           mov       al,fxOctave             ;Get the current octave
  678.           xor       ah,ah
  679.  
  680.           mov       bl,OCTAVE               ; and notes/octave
  681.           div       bl                      ; and divide
  682.  
  683.           mov       bl,al                   ;Get the quotient
  684.           inc       bl                      ; and bump it up
  685.  
  686.           cmp       bl,MAXOCTAVE            ;Is the new octave within limits?
  687.           jbe       fxPT_octset             ;If so, set it using above
  688.  
  689.           jmp       fxPT_chkparse
  690.           
  691. fxPT_chkdownoct:
  692.  
  693.           cmp       bl,'<'                  ;Going down an octave?
  694.           jne       fxPT_chklength          ;If not, check if length
  695.  
  696.           mov       al,fxOctave             ;Get the current octave
  697.           xor       ah,ah
  698.  
  699.           mov       bl,OCTAVE               ; and notes/octave
  700.           div       bl                      ; and divide
  701.  
  702.           mov       bl,al                   ;Get the quotient
  703.           dec       bl                      ; and bump it down
  704.  
  705.           cmp       bl,MINOCTAVE            ;Is the new octave within limits?
  706.           jae       fxPT_octset             ;If so, set it using above
  707.  
  708.           jmp       fxPT_chkparse
  709.           
  710. fxPT_chklength:
  711.           
  712.           cmp       bl,'L'                  ;Is this a length default?
  713.           jne       fxPT_chktempo           ;If not, check for tempo
  714.  
  715.           mov       bl,es:[di]              ;Get the number
  716.  
  717.           cmp       bl,0                    ;If end of string, exit
  718.           jne       fxPT_length
  719.           jmp       SHORT fxPT_play
  720.  
  721. fxPT_length:
  722.  
  723.           call      fxPlayNum               ;Convert to a number
  724.  
  725.           cmp       bx,MINLENGTH            ;Check minimum
  726.           jae       fxPT_chklenmax
  727.  
  728.           mov       bx,MINLENGTH
  729.           jmp       SHORT fxPT_calclen
  730.  
  731. fxPT_chklenmax:
  732.  
  733.           cmp       bx,MAXLENGTH            ; and maximum
  734.           jbe       fxPT_calclen
  735.  
  736.           mov       bx,MAXLENGTH
  737.  
  738. fxPT_calclen:
  739.  
  740.           mov       ax,fxTempo              ;Get the current tempo
  741.           xor       dx,dx                   ;Clear high word
  742.  
  743.           div       bx                      ;Divide whole note by note length
  744.  
  745. fxPT_setlen:
  746.  
  747.           push      ax                      ;Save result
  748.  
  749.           mov       bx,fxMusic              ;Get the music mode
  750.           mul       bx                      ; multiply
  751.           mov       bx,8                    ; and divide (to get mode)
  752.           div       bx
  753.  
  754.           mov       fxNoteLen,ax            ;Store note length
  755.  
  756.           pop       bx                      ;Restore original full value
  757.           sub       bx,ax                   ; and sub note length
  758.  
  759.           mov       fxNoteDel,bx            ;Store the note delay
  760.  
  761.           jmp       SHORT fxPT_chkparse
  762.  
  763. fxPT_chktempo:
  764.  
  765.           cmp       bl,'T'                  ;Is this a length default?
  766.           jne       fxPT_chkparse           ;If not, check for tempo
  767.  
  768.           mov       bl,es:[di]              ;Get the number
  769.  
  770.           cmp       bl,0                    ;If end of string, exit
  771.           jne       fxPT_tempo 
  772.           jmp       SHORT fxPT_play
  773.  
  774. fxPT_tempo: 
  775.  
  776.           call      fxPlayNum               ;Convert to a number
  777.  
  778.           cmp       bx,MINTEMPO             ;Check minimum
  779.           jae       fxPT_chktempomax
  780.  
  781.           mov       bx,MINTEMPO
  782.           jmp       SHORT fxPT_settempo
  783.  
  784. fxPT_chktempomax:
  785.  
  786.           cmp       bx,MAXTEMPO             ; and maximum
  787.           jbe       fxPT_settempo
  788.  
  789.           mov       bx,MAXTEMPO 
  790.  
  791. fxPT_settempo:
  792.  
  793.           mov       ax,60*100               ;Number of milliseconds/second
  794.           xor       dx,dx
  795.  
  796.           div       bx                      ;Divide by quarternotes/second
  797.  
  798.           shl       ax,1                    ;Get a whole note value, in ms
  799.           shl       ax,1
  800.  
  801.           mov       fxTempo,ax              ;Store the new tempo
  802.  
  803.           mov       ax,fxNoteLen            ;Get the default length
  804.           add       ax,fxNoteDel            ; and add in the delay, for total
  805.  
  806.           jmp       fxPT_setlen             ;Now recalc under new tempo
  807.  
  808. fxPT_chkparse:
  809.  
  810.           jmp       fxPT_parse              ;Continue parsing
  811.  
  812. fxPT_play:
  813.  
  814.           mov       ax,ptcount              ;Get number of notes
  815.           cmp       ax,0                    ;If not zero,
  816.           jg        fxPT_getptrs            ; continue
  817.  
  818.           jmp       fxPT_exit               ; otherwise exit
  819.  
  820. fxPT_getptrs:
  821.  
  822.           @@Data    es
  823.           mov       si,OFFSET fxNotes       ;Point to tone frequencies
  824.           mov       di,OFFSET fxNoteBuf
  825.  
  826.           cmp       fxMode,PLAYBACK         ;Play in background?
  827.           jne       fxPT_playfore
  828.           jmp       SHORT fxPT_playback     ;If yes, do it
  829.  
  830. fxPT_playfore:
  831.  
  832.           mov       cx,ptcount              ;Get number of notes
  833.  
  834. fxPT_loop:
  835.  
  836.           mov       bx,WORD PTR es:[di]     ;Get a tone
  837.           shl       bx,1                    ;Shift since it is a word pointer
  838.  
  839.           mov       ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
  840.           mov       bx,WORD PTR es:[di+2]   ; with the length
  841.  
  842.           cmp       bx,0                    ;Zero length?
  843.           je        fxPT_forebump           ;If so, skip
  844.  
  845.           push      ax                      ;Now sound the tone
  846.           push      bx
  847.           call      fxTone
  848.  
  849. fxPT_forebump:
  850.  
  851.           inc       di                      ;Bump pointer past this note
  852.           inc       di
  853.           inc       di
  854.           inc       di
  855.  
  856. fxPT_chkloop:
  857.  
  858.           loop      fxPT_loop               ;Loop until all notes are played
  859.  
  860.           cmp       fxLoopNum,0             ;Are we supposed to loop?
  861.           je        fxPT_exit               ;If not, exit
  862.  
  863.           cmp       fxLoopNum,-1            ;Infinite loop?
  864.           je        fxPT_foreloop
  865.  
  866.           dec       fxLoopNum               ;If so, count this loop
  867.           jz        fxPT_exit               ; and if zero, exit
  868.  
  869. fxPT_foreloop:
  870.  
  871.           jmp       SHORT fxPT_playfore     ;Otherwise, play again
  872.  
  873. fxPT_playback:
  874.  
  875.           mov       fxNotePtr,OFFSET fxNoteBuf ;Store the note buffer pointer
  876.           mov       ax,ptcount                 ; and the count globally
  877.           mov       fxCount,ax                 
  878.           mov       fxLoopCnt,ax                 
  879.  
  880.           mov       bx,WORD PTR es:[di]     ;Get a tone
  881.           shl       bx,1                    ;Shift since it is a word pointer
  882.  
  883.           mov       ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
  884.  
  885.           push      ax                      ;Now set the tone
  886.           call      fxSetFrequency
  887.  
  888.           mov       ax,WORD PTR es:[di+2]   ;Get the length
  889.           mov       fxDelay,ax
  890.  
  891.           mov       ax,fxON                 ; and turn the speaker on
  892.           push      ax
  893.           call      fxSetSpeaker
  894.  
  895.           mov       al,INT_TIMER            ;Get the timer vector
  896.           @DOS      GETVECT                 
  897.  
  898.           mov       ax,es                   ;Store the segment
  899.           mov       fxClkSeg,ax
  900.  
  901.           mov       fxClkOfs,bx             ; and offset
  902.  
  903.           mov       dx,OFFSET fxPlayInt     ;Get the offset and
  904.           @@LoadSeg ds,cs                   ; and code segment
  905.  
  906.           mov       al,INT_TIMER            ;Set the timer vector
  907.           @DOS      SETVECT
  908.  
  909. fxPT_exit:
  910.  
  911.           @SetRet   ptret,fxSUCCESS         ;Set return code
  912.  
  913.           @Exit     ptret,ptparm            ;Return
  914.  
  915. fxPlay              ENDP
  916.  
  917. ;**********
  918.  
  919. ;
  920. ; This procedure plays the parsed music string in the background.
  921. ; It recieves control on the timer interrupt.
  922. ;
  923. ;
  924.  
  925.  
  926. fxPlayInt           PROC FAR
  927.  
  928.           pushf                             ;Save everything
  929.           push      ax
  930.           push      bx
  931.           push      cx
  932.           push      dx
  933.           push      si
  934.           push      di
  935.           push      ds
  936.           push      es
  937.  
  938.           sti                               ;Turn interrupts back on
  939.  
  940.           @@Data    ds                      ;Point to note frequencies
  941.           mov       si,OFFSET fxNotes      
  942.           @@Data    es                      ; and the note buffer
  943.           mov       di,fxNotePtr           
  944.  
  945.           sub       fxDelay,fxCLICK         ;subtract value of one click
  946.  
  947.           cmp       fxDelay,0               ;Have we reached zero?
  948.           jle       fxPI_count              ;If yes, count this note
  949.  
  950.           jmp       fxPI_exit               ;If not, exit now
  951.  
  952. fxPI_count:
  953.  
  954.           dec       fxCount                 ;Yes, so count this note
  955.           cmp       fxCount,0               ;Have we done them all?
  956.           jle       fxPI_stop
  957.  
  958.           inc       di                      ;No, so bump pointer
  959.           inc       di
  960.           inc       di
  961.           inc       di
  962.  
  963.           mov       fxNotePtr,di            ; and store
  964.  
  965.           mov       ax,fxOFF                ;Turn the speaker off
  966.           push      ax
  967.           call      fxSetSpeaker
  968.  
  969. fxPI_gettone:
  970.  
  971.           mov       bx,WORD PTR es:[di]     ;Get a tone
  972.           shl       bx,1                    ;Shift since it is a word pointer
  973.  
  974.           mov       ax,WORD PTR ds:[si][bx] ;Get the corresponding freq
  975.           cmp       ax,0
  976.           je        fxPI_delay
  977.  
  978.           push      ax                      ;Now sound the tone
  979.           call      fxSetFrequency
  980.  
  981.           mov       ax,fxON                 ;Turn the speaker on
  982.           push      ax
  983.           call      fxSetSpeaker
  984.  
  985. fxPI_delay:
  986.  
  987.           mov       ax,WORD PTR es:[di+2]   ;Get the delay
  988.           mov       fxDelay,ax
  989.  
  990.           jmp       SHORT fxPI_exit         ; and exit
  991.  
  992. fxPI_stop:
  993.  
  994.           mov       ax,fxOFF                ;Turn the speaker off
  995.           push      ax
  996.           call      fxSetSpeaker
  997.  
  998.           cmp       fxLoopNum,0             ;Are we supposed to loop?
  999.           je        fxPI_zero
  1000.  
  1001.           cmp       fxLoopNum,-1            ;Infinite Loop?
  1002.           je        fxPI_initloop
  1003.  
  1004.           dec       fxLoopNum               ;Count this loop
  1005.           jz        fxPI_zero               ; and if zero, exit
  1006.  
  1007. fxPI_initloop:
  1008.  
  1009.           mov       di,OFFSET fxNoteBuf     ;Set up note pointer
  1010.           mov       fxNotePtr,di
  1011.  
  1012.           mov       ax,fxLoopCnt            ;Set up note count
  1013.           mov       fxCount,ax
  1014.  
  1015.           jmp       SHORT fxPI_gettone
  1016.  
  1017. fxPI_zero:
  1018.  
  1019.           mov       fxCount,0               ;Make sure count is zeroed
  1020.  
  1021.           cli                               ;Make sure we are not interrupted
  1022.  
  1023.           @@LoadSeg es,0                    ;Point to vector table
  1024.           mov       di,INT_TIMER*4
  1025.  
  1026.           mov       ax,fxClkOfs             ;Restore old vector (bypass DOS,
  1027.           mov       es:[di],ax              
  1028.           mov       ax,fxClkSeg             ; since it is not reentrant)
  1029.           mov       es:[di+2],ax            
  1030.  
  1031. fxPI_exit:
  1032.  
  1033.           pop       es                      ;Restore regs
  1034.           pop       ds
  1035.           pop       di
  1036.           pop       si
  1037.           pop       dx
  1038.           pop       cx
  1039.           pop       bx
  1040.           pop       ax
  1041.           popf
  1042.  
  1043.           iret
  1044.  
  1045. fxPlayInt           ENDP
  1046.  
  1047. ;**********
  1048.  
  1049. ;
  1050. ; This procedure returns the number of notes left in the buffer.
  1051. ;
  1052. ;
  1053.  
  1054. ;Define variable locations on the stack  (pascal model)
  1055. plparm    equ       0
  1056.  
  1057. ;Define local variables
  1058. plret     equ       <[bp- 2]>               ;Time Delay    
  1059. pllocal   equ       2                       ;Total local space needed
  1060.  
  1061. fxPlayLeft          PROC FAR
  1062.  
  1063.           @Entry    pllocal                 ;Set up frame and save regs
  1064.  
  1065.           mov       ax,fxCount              ;Get the notes remaining
  1066.           shr       ax,1                    ; divide by 2 to get actual
  1067.  
  1068.           @SetRet   plret,ax                ; and return them
  1069.  
  1070.           @Exit     plret,plparm            ;Return
  1071.  
  1072. fxPlayLeft          ENDP
  1073.  
  1074. ;**********
  1075.  
  1076. ;
  1077. ; This procedure kills the background music process.
  1078. ;
  1079. ;
  1080.  
  1081. ;Define variable locations on the stack  (pascal model)
  1082. pkparm    equ       0
  1083.  
  1084. ;Define local variables
  1085. pkret     equ       <[bp- 2]>               ;Time Delay    
  1086. pklocal   equ       2                       ;Total local space needed
  1087.  
  1088. fxPlayKill          PROC FAR
  1089.  
  1090.           @Entry    pklocal                 ;Set up frame and save regs
  1091.  
  1092.           mov       fxLoopNum,0             ;Zero out the loop count
  1093.  
  1094.           mov       fxCount,0               ;Zero out 'Notes Remaining' Count
  1095.  
  1096.           @SetRet   pkret,fxSUCCESS         ; and return
  1097.  
  1098.           @Exit     pkret,pkparm            ;Return
  1099.  
  1100. fxPlayKill          ENDP
  1101.  
  1102. ;**********
  1103.  
  1104. ;
  1105. ; This procedure handles whether the play buffer should loop or not.
  1106. ;
  1107. ;
  1108.  
  1109. ;Define variable locations on the stack  (pascal model)
  1110. poloopnum equ       <[bp+ 6]>               ;Loop Flag     
  1111. poparm    equ       2
  1112.  
  1113. ;Define local variables
  1114. poret     equ       <[bp- 2]>               ;Time Delay    
  1115. polocal   equ       2                       ;Total local space needed
  1116.  
  1117. fxPlayLoop          PROC FAR
  1118.  
  1119.           @Entry    polocal                 ;Set up frame and save regs
  1120.  
  1121.           mov       ax,poloopnum            ;Get the loop flag
  1122.  
  1123.           mov       fxLoopNum,ax            ;Store it
  1124.  
  1125.           @SetRet   poret,fxSUCCESS         ; and return
  1126.  
  1127.           @Exit     poret,poparm            ;Return
  1128.  
  1129. fxPlayLoop          ENDP
  1130.  
  1131. ;**********
  1132.  
  1133. ;
  1134. ; This procedure is used to initialize all of the fx music data.  It is
  1135. ; called only once by languages that do not permit static data (like
  1136. ; Turbo Pascal).
  1137. ;
  1138. ; Calling: fxInitPData()
  1139. ;
  1140. ;
  1141.  
  1142. ;Define variable locations on the stack, depending on model
  1143. idparm    equ       0
  1144.  
  1145. ;Define local variables
  1146. idret     equ       <[bp-2]>                ;return code
  1147. idlocal   equ       2                       ;Total local space needed
  1148.  
  1149. fxInitPData         PROC FAR
  1150.  
  1151.           @Entry    idlocal                 ;Set up frame and save regs
  1152.  
  1153.           @SetRet   idret,fxSUCCESS         ;Assume successful
  1154.  
  1155.           mov       fxOctave,4*OCTAVE       ;Default octave
  1156.           mov       fxNoteLen,45            ;Default note length
  1157.           mov       fxNoteDel,5             ; and delay
  1158.           mov       fxTempo,200             ;Default tempo
  1159.           mov       fxMusic,PLAYNORM        ;Play normally
  1160.           mov       fxMode,PLAYFORE         ; and in the foreground
  1161.  
  1162.           mov       fxCount,0               ;Zero out the 'notes left'
  1163.  
  1164.           mov       fxLoopCnt,0             ; and loop counters
  1165.           mov       fxLoopNum,0
  1166.  
  1167.           mov       si,OFFSET fxNotes 
  1168.  
  1169.           mov       WORD PTR ds:[si],0
  1170.           inc       si
  1171.           inc       si
  1172.  
  1173.           IRP       x,<   33,   35,   37,   39,   41,   44,   46,   49,   52,   55,   58,   62>
  1174.           mov       WORD PTR ds:[si],x
  1175.           inc       si
  1176.           inc       si
  1177.           ENDM
  1178.  
  1179.           IRP       x,<   65,   69,   73,   78,   82,   87,   93,   98,  104,  110,  117,  123>
  1180.           mov       WORD PTR ds:[si],x
  1181.           inc       si
  1182.           inc       si
  1183.           ENDM
  1184.  
  1185.           IRP       x,<  131,  139,  147,  156,  165,  175,  185,  196,  208,  220,  233,  247>
  1186.           mov       WORD PTR ds:[si],x
  1187.           inc       si
  1188.           inc       si
  1189.           ENDM
  1190.  
  1191.           IRP       x,<  262,  277,  294,  311,  330,  349,  370,  392,  416,  440,  466,  494>
  1192.           mov       WORD PTR ds:[si],x
  1193.           inc       si
  1194.           inc       si
  1195.           ENDM
  1196.  
  1197.           IRP       x,<  523,  554,  587,  622,  659,  698,  740,  784,  831,  880,  932,  988>
  1198.           mov       WORD PTR ds:[si],x
  1199.           inc       si
  1200.           inc       si
  1201.           ENDM
  1202.  
  1203.           IRP       x,< 1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976>
  1204.           mov       WORD PTR ds:[si],x
  1205.           inc       si
  1206.           inc       si
  1207.           ENDM
  1208.  
  1209.           IRP       x,< 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951>
  1210.           mov       WORD PTR ds:[si],x
  1211.           inc       si
  1212.           inc       si
  1213.           ENDM
  1214.  
  1215.           IRP       x,< 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6646, 7040, 7459, 7902>
  1216.           mov       WORD PTR ds:[si],x
  1217.           inc       si
  1218.           inc       si
  1219.           ENDM
  1220.  
  1221.           IRP       x,< 8372, 8870, 9398, 9956,10548,11176,11840,12544,13292,14080,14918,15804>
  1222.           mov       WORD PTR ds:[si],x
  1223.           inc       si
  1224.           inc       si
  1225.           ENDM
  1226.  
  1227.           IRP       x,<16744,17740,18796,19912,21096,22352,23680,25088,26584,28160,29836,31608>
  1228.           mov       WORD PTR ds:[si],x
  1229.           inc       si
  1230.           inc       si
  1231.           ENDM
  1232.  
  1233. pcxID_exit:
  1234.  
  1235.           @Exit     idret,idparm            ;Return
  1236.  
  1237. fxInitPData         ENDP
  1238.  
  1239.   @EndCode
  1240.  
  1241.           END
  1242.  
  1243.