home *** CD-ROM | disk | FTP | other *** search
/ Dr. CD ROM (Annual Premium Edition) / premium.zip / premium / MUSICLAB / DIGVOIVE.ZIP / VRMOD.ASM < prev    next >
Assembly Source File  |  1989-06-24  |  17KB  |  731 lines

  1. page 58,132
  2. .286c
  3. .MODEL LARGE
  4.  
  5. ;**********************************************************************
  6. ;*                                                                    *
  7. ;*                             Equates                                *
  8. ;*                                                                    *
  9. ;**********************************************************************
  10.  
  11. tccount        equ    72    ;reload count to produce 16572 Hz
  12. countmax_18hz    equ    910    ;ratio of new timer rate to old rate
  13.  
  14. tcaddrc        equ    43h    ;timer/counter control register address
  15. tcaddrd        equ    40h    ;timer/counter data register zero
  16.  
  17. tcmode        equ    34h    ;mode control byte for timer/counter
  18.  
  19. ppiaddr        equ    61h    ;programmable peripheral interface address
  20.  
  21. ;**********************************************************************
  22. ;*                                                                    *
  23. ;*                             Macros                                 *
  24. ;*                                                                    *
  25. ;**********************************************************************
  26.  
  27. ljz    macro    dest
  28.     local    skip
  29.     jnz    skip
  30.     jmp    dest
  31. skip:
  32.     endm
  33.  
  34. ;**********************************************************************
  35. ;*                                                                    *
  36. ;*                         Global variables                           *
  37. ;*                                                                    *
  38. ;**********************************************************************
  39.  
  40. .DATA
  41.         even        ;don't put these on an odd boundary
  42.  
  43. blockaddr    dd    0    ;beginning of memory block
  44. blocksize    dd    0    ;size of memory block
  45. blockend    dd    0    ;last address of memory block + 1
  46. currentaddr    dd    0    ;pointer to current record position in memory
  47. datacount    dd    0    ;number of data bytes already recorded
  48. fwrtaddr    dd    0    ;address of next byte to be written to disk
  49. fwrtcount    dd    0    ;number of bytes already written to disk
  50.  
  51. goflag        dw    0    ;indicates whether recording is in progress
  52. fileflag    dw    0    ;indicates whether data is written to a file
  53. filehandle    dw    0    ;handle of file to receive voice data
  54. hookedflag    dw    0    ;indicates whether the interrupt is hooked
  55. countfor_18hz    dw    0    ;counter to determine when to call BIOS
  56. comaddr        dw    0    ;the address of the COM port
  57.  
  58. comlist        dw    3FEh    ;needed addresses of all COM ports
  59.         dw    2FEh
  60.         dw    3EEh
  61.         dw    2EEh
  62.  
  63. shiftcount    db    0    ;current bit position within byte
  64.  
  65. ;**********************************************************************
  66. ;*                                                                    *
  67. ;*                               Code                                 *
  68. ;*                                                                    *
  69. ;**********************************************************************
  70.  
  71. .CODE
  72.  
  73. bios_timer_routine    dd    0    ;we keep this in the code segment
  74.                     ; for access through the CS register
  75.                     ; since the other segment registers
  76.                     ; will contain unknown values when
  77.                     ; this is needed
  78.  
  79.     assume    ds:DGROUP
  80.  
  81. ;**********************************************************************
  82. ;*             Speed up the timer tick and set "goflag"               *
  83. ;**********************************************************************
  84.  
  85. startvoice    proc    near
  86.  
  87.     pushf
  88.     cli
  89.     mov    al,tcmode
  90.     out    tcaddrc,al
  91.     mov    ax,tccount
  92.     out    tcaddrd,al
  93.     mov    al,ah
  94.     out    tcaddrd,al
  95.     mov    shiftcount,0
  96.     mov    countfor_18hz,countmax_18hz
  97.     mov    goflag,1
  98.     popf
  99.     ret
  100.  
  101. startvoice    endp
  102.  
  103. ;**********************************************************************
  104. ;*         Slow the timer tick to normal and clear "goflag"           *
  105. ;**********************************************************************
  106.  
  107. stopvoice    proc    near
  108.  
  109.     pushf
  110.     cli
  111.     mov    al,tcmode
  112.     out    tcaddrc,al
  113.     mov    al,0
  114.     out    tcaddrd,al
  115.     out    tcaddrd,al
  116.     mov    goflag,0
  117.     popf
  118.     ret
  119.  
  120. stopvoice    endp
  121.  
  122. ;**********************************************************************
  123. ;*                   Interrupt service routine                        *
  124. ;**********************************************************************
  125.  
  126. timer_tick    proc    far
  127.  
  128.     push    ds
  129.     push    bx
  130.     push    es
  131.     push    ax
  132.     push    cx
  133.     push    dx
  134.  
  135.     mov    ax,DGROUP
  136.     mov    ds,ax
  137.  
  138.     cmp    goflag,0
  139.     je    chain_exit
  140.  
  141.     les    bx,currentaddr
  142.     mov    ah,es:[bx]
  143.     mov    dx,comaddr
  144.     in    al,dx
  145.     rcl    al,4
  146.     rcl    ah,1
  147.     mov    es:[bx],ah
  148.  
  149.     inc    shiftcount
  150.     and    shiftcount,07h
  151.     jnz    exit_decide
  152.  
  153.     mov    ax,es
  154.     inc    bx
  155.     jnz    check_wrap
  156.     add    ax,1000h
  157. check_wrap:
  158.     cmp    bx,word ptr blockend
  159.     jne    save_cur_addr
  160.     cmp    ax,word ptr blockend+2
  161.     jne    save_cur_addr
  162.     mov    bx,word ptr blockaddr
  163.     mov    ax,word ptr blockaddr+2
  164. save_cur_addr:
  165.     mov    word ptr currentaddr,bx
  166.     mov    word ptr currentaddr+2,ax
  167.     add    word ptr datacount,1
  168.     adc    word ptr datacount+2,0
  169.  
  170. exit_decide:
  171.     dec    countfor_18hz
  172.     jnz    nochain_exit
  173.     mov    countfor_18hz,countmax_18hz
  174.  
  175. chain_exit:
  176.     pop    dx
  177.     pop    cx
  178.     pop    ax
  179.     pop    es
  180.     pop    bx
  181.     pop    ds
  182.     jmp    cs:bios_timer_routine
  183.  
  184. nochain_exit:
  185.     mov    al,20h
  186.     out    20h,al
  187.     pop    dx
  188.     pop    cx
  189.     pop    ax
  190.     pop    es
  191.     pop    bx
  192.     pop    ds
  193.     iret
  194.  
  195. timer_tick    endp
  196.  
  197. ;**********************************************************************
  198. ;*                   Initialization procedure                         *
  199. ;**********************************************************************
  200.  
  201. ;This routine should be called exactly one time before any of the other
  202. ; routines in this package are called. It takes no parameters, but returns
  203. ; a value indicating success or failure as follows:
  204.  
  205. ;Return value        Meaning
  206. ;------------        -------
  207. ;     0              success
  208. ;     1              voice package already initialized
  209. ;     2              wrong CPU, won't run on 8088 or 8086
  210.  
  211.     public    RVOICE_INIT
  212.  
  213. RVOICE_INIT    proc    far
  214.  
  215.     push    sp
  216.     pop    ax
  217.     cmp    ax,sp
  218.     je    vi_test
  219.     mov    ax,2
  220.     ret
  221.  
  222. vi_test:
  223.     cmp    hookedflag,0
  224.     je    vi_hook
  225.     mov    ax,1
  226.     ret
  227.  
  228. vi_hook:
  229.     enter    0,0
  230.     push    si
  231.     push    di
  232.  
  233.     push    ds
  234.     lea    dx,RVOICE_CBREAK
  235.     mov    ax,seg RVOICE_CBREAK
  236.     mov    ds,ax
  237.     mov    ax,2523h
  238.     int    21h
  239.     pop    ds
  240.  
  241.     push    ds
  242.     mov    ax,3508h
  243.     int    21h
  244.     mov    word ptr cs:bios_timer_routine,bx
  245.     mov    word ptr cs:bios_timer_routine+2,es
  246.     lea    dx,timer_tick
  247.     mov    ax,seg timer_tick
  248.     mov    ds,ax
  249.     mov    ax,2508h
  250.     int    21h
  251.     pop    ds
  252.  
  253.     pop    di
  254.     pop    si
  255.     mov    hookedflag,1
  256.     sub    ax,ax
  257.     leave
  258.     ret
  259.  
  260. RVOICE_INIT    endp
  261.  
  262. ;**********************************************************************
  263. ;*                      Cleanup procedure                             *
  264. ;**********************************************************************
  265.  
  266. ;This will restore the interrupt 8 vector to its original state. This
  267. ; routine MUST be called before the main program exits to DOS, unless:
  268. ; (a) the program has never called RVOICE_INIT, or (b) the program is
  269. ; becoming memory-resident.
  270.  
  271. ;There are no parameters. The return values are 0 for success or 1 if
  272. ; the interrupt vector was not in fact hooked.
  273.  
  274.     public    RVOICE_CLEANUP
  275.  
  276. RVOICE_CLEANUP    proc    far
  277.  
  278.     cmp    hookedflag,1
  279.     je    vc_unhook
  280.     mov    ax,1
  281.     ret
  282.  
  283. vc_unhook:
  284.     enter    0,0
  285.     push    si
  286.     push    di
  287.     call    stopvoice
  288.     push    ds
  289.     lds    dx,cs:bios_timer_routine
  290.     mov    ax,2508h
  291.     int    21h
  292.     pop    ds
  293.     pop    di
  294.     pop    si
  295.     mov    hookedflag,0
  296.     sub    ax,ax
  297.     leave
  298.     ret
  299.  
  300. RVOICE_CLEANUP    endp
  301.  
  302. ;**********************************************************************
  303. ;*                Vector restore for Control-Break                    *
  304. ;**********************************************************************
  305.  
  306.     public    RVOICE_CBREAK
  307.  
  308. RVOICE_CBREAK    proc    far
  309.  
  310.     pusha
  311.     push    ds
  312.     push    es
  313.  
  314.     mov    ax,DGROUP
  315.     mov    ds,ax
  316.     call    stopvoice
  317.     call    RVOICE_CLEANUP
  318.  
  319.     pop    es
  320.     pop    ds
  321.     popa
  322.     stc
  323.     ret
  324.  
  325. RVOICE_CBREAK    endp
  326.  
  327. ;**********************************************************************
  328. ;*                "File write catch-up" procedure                     *
  329. ;**********************************************************************
  330.  
  331. ;This must be called frequently from the main program if file writing is
  332. ; being used and the length of the data to be recorded is longer than the
  333. ; length of the memory block. The routine checks the progress of the
  334. ; address pointer in use by the interrupt service routine and writes
  335. ; new data to the file as it becomes available.
  336.  
  337. ;There are no parameters. The return values are 0 for success 1 if there
  338. ; was no new data to write, or 2 if an error occurred while writing the file.
  339.  
  340. vcat_temp1l        equ    [bp-4]    ;current address from ISR
  341. vcat_temp1h        equ    [bp-2]
  342. vcat_temp2l        equ    [bp-8]    ;<unused>
  343. vcat_temp2h        equ    [bp-6]
  344.  
  345. ;the three stopping points:
  346.  
  347. vcat_temp3l        equ    [bp-12]    ;current address - fill address
  348. vcat_temp3h        equ    [bp-10]
  349. vcat_temp4l        equ    [bp-16]    ;block end - fill address
  350. vcat_temp4h        equ    [bp-14]
  351. vcat_temp5l        equ    [bp-20]    ;(boundary) - fill address
  352. vcat_temp5h        equ    [bp-18]
  353.  
  354. vcat_templength        equ    20
  355.  
  356.     public    RVOICE_CATCHUP
  357.  
  358. RVOICE_CATCHUP    proc    far
  359.  
  360.     enter    vcat_templength,0
  361.  
  362. ;should we even be doing this?
  363.  
  364.     cmp    fileflag,0
  365.     ljz    vcat_exit0
  366.  
  367. ;grab a stable value from currentaddr
  368. ; since it is changing all the time
  369.  
  370.     cli
  371.     mov    ax,word ptr currentaddr
  372.     mov    vcat_temp1l,ax
  373.     mov    ax,word ptr currentaddr+2
  374.     mov    vcat_temp1h,ax
  375.     sti
  376.  
  377. ;calculate the forward distance to each of the
  378. ; three possible stopping points
  379.  
  380. vcat_getgap:
  381.     mov    ax,vcat_temp1l
  382.     sub    ax,word ptr fwrtaddr
  383.     mov    vcat_temp3l,ax
  384.     pushf
  385.     mov    ax,vcat_temp1h
  386.     sub    ax,word ptr fwrtaddr+2
  387.     sar    ax,12
  388.     popf
  389.     sbb    ax,0
  390.     mov    vcat_temp3h,ax
  391.  
  392. vcat_getclearance:
  393.     mov    ax,word ptr blockend
  394.     sub    ax,word ptr fwrtaddr
  395.     mov    vcat_temp4l,ax
  396.     pushf
  397.     mov    ax,word ptr blockend+2
  398.     sub    ax,word ptr fwrtaddr+2
  399.     sar    ax,12
  400.     popf
  401.     sbb    ax,0
  402.     mov    vcat_temp4h,ax
  403.  
  404.     mov    ax,word ptr fwrtaddr
  405.     neg    ax
  406.     mov    vcat_temp5l,ax
  407.     mov    word ptr vcat_temp5h,0
  408.     jnz    vcat_cmp2
  409.     inc    word ptr vcat_temp5h
  410.  
  411. ;select the stopping point which will be
  412. ; encountered soonest
  413.  
  414. ;Since we are not interested in the negative
  415. ; values, doing unsigned compares in a search
  416. ; for the smallest number will give the
  417. ; desired result.
  418.  
  419. vcat_cmp2:
  420.     mov    ax,vcat_temp3h
  421.     mov    cx,vcat_temp3l
  422.  
  423.  
  424. vcat_cmp3:
  425.     cmp    ax,vcat_temp4h
  426.     jb    vcat_cmp5
  427.     ja    vcat_cmp4
  428.     cmp    cx,vcat_temp4l
  429.     jb    vcat_cmp5
  430.  
  431. vcat_cmp4:
  432.     mov    ax,vcat_temp4h
  433.     mov    cx,vcat_temp4l
  434.  
  435.  
  436. vcat_cmp5:
  437.     cmp    ax,vcat_temp5h
  438.     jb    vcat_cmp7
  439.     ja    vcat_cmp6
  440.     cmp    cx,vcat_temp5l
  441.     jb    vcat_cmp7
  442.  
  443. vcat_cmp6:
  444.     mov    ax,vcat_temp5h
  445.     mov    cx,vcat_temp5l
  446.  
  447.  
  448. vcat_cmp7:
  449.  
  450. ;Now the smallest number is in AX:CX.
  451. ; However, AX:CX may be 65536 or 0FFFFh
  452. ; (illegal), so we must test for these
  453. ; possibilities.
  454.  
  455.     cmp    ax,1
  456.     je    vcat_fixcx
  457.     cmp    cx,0FFFFh
  458.     jne    vcat_writefile
  459.  
  460. vcat_fixcx:
  461.     mov    cx,0FE00h
  462.  
  463. vcat_writefile:
  464.     or    cx,cx
  465.     jz    vcat_exit1
  466.     mov    bx,filehandle
  467.     push    ds
  468.     lds    dx,fwrtaddr
  469.     mov    ah,40h
  470.     int    21h
  471.     pop    ds
  472.     jc    vcat_error2
  473.     cmp    ax,cx
  474.     jne    vcat_error2
  475.  
  476. ;update global varibles to show the current
  477. ; situation
  478.  
  479.     add    word ptr fwrtcount,cx
  480.     adc    word ptr fwrtcount+2,0
  481.  
  482.     add    word ptr fwrtaddr,cx
  483.     jnc    vcat_fillwrap
  484.     add    word ptr fwrtaddr+2,1000h
  485.  
  486. vcat_fillwrap:
  487.     mov    bx,word ptr blockend
  488.     cmp    bx,word ptr fwrtaddr
  489.     jne    vcat_exit0
  490.     mov    ax,word ptr blockend+2
  491.     cmp    ax,word ptr fwrtaddr+2
  492.     jne    vcat_exit0
  493.     mov    bx,word ptr blockaddr
  494.     mov    ax,word ptr blockaddr+2
  495.     mov    word ptr fwrtaddr,bx
  496.     mov    word ptr fwrtaddr+2,ax
  497.  
  498.     jmp    short vcat_exit0
  499.  
  500. ;return code exit points
  501.  
  502. vcat_error2:
  503.     mov    ax,2
  504.     jmp    short vcat_exit
  505.  
  506. vcat_exit1:
  507.     mov    ax,1
  508.     jmp    short vcat_exit
  509.  
  510. ;normal exit point
  511.  
  512. vcat_exit0:
  513.  
  514.     ;don't leave until at least one bit has been played
  515.     ; if goflag is not zero
  516.  
  517.     mov    ax,word ptr currentaddr
  518.     cmp    vcat_temp1l,ax
  519.     jne    vcat_exitloop
  520.     cmp    goflag,0
  521.     jne    vcat_exit0
  522. vcat_exitloop:
  523.     sub    ax,ax
  524. vcat_exit:
  525.     leave
  526.     ret
  527.  
  528. RVOICE_CATCHUP    endp
  529.  
  530. ;**********************************************************************
  531. ;*                   "Start recording" procedure                      *
  532. ;**********************************************************************
  533.  
  534. ;Accepts the following parameters with PASCAL parameter-passing convention:
  535.  
  536. ;Position   Size   Description
  537. ;--------   ----   -----------
  538. ;   1         4    A far pointer to the memory block used for voice data.
  539. ;   2         4    A dword indicating the length of the memory block.
  540. ;   3         2    A flag word. If this is 1, then data will be written to
  541. ;                   a file. If it is 0, no file operations will be performed.
  542. ;   4         2    An open file handle. This is ignored if the flag word
  543. ;                   is 0.
  544. ;   5         2    A word containing the number of the COM port to be used
  545. ;                   for input (1 thru 4).
  546. ;   6         4    A dword indicating the offset within the memory block
  547. ;                   where recording is to begin.
  548.  
  549. ;Return value        Meaning
  550. ;------------        -------
  551. ;     0              success
  552. ;     1              block size is too small (blocklen < 8192 and 
  553. ;                     file write = yes)
  554. ;     2              voice recording is already in progress
  555. ;     3              a COM port number not within the range of 1 thru 4
  556. ;                     was specified
  557. ;     4              starting position is not less than block length
  558.  
  559. min_blocksize        equ    8192
  560.  
  561. vs_parm1        equ    [bp+20]    ;length = 4
  562. vs_parm2        equ    [bp+16]    ;length = 4
  563. vs_parm3        equ    [bp+14]    ;length = 2
  564. vs_parm4        equ    [bp+12]    ;length = 2
  565. vs_parm5        equ    [bp+10]    ;length = 2
  566. vs_parm6        equ    [bp+6]    ;length = 4
  567.  
  568. vs_parmlength    equ    18
  569.  
  570.     public    RVOICE_START
  571.  
  572. RVOICE_START    proc    far
  573.  
  574.     cmp    goflag,0
  575.     je    vs_begin
  576.     mov    ax,2
  577.     ret    vs_parmlength
  578.  
  579. vs_begin:
  580.     enter    0,0
  581.     mov    word ptr datacount,0
  582.     mov    word ptr datacount+2,0
  583.     mov    word ptr fwrtcount,0
  584.     mov    word ptr fwrtcount+2,0
  585.  
  586.     les    bx,dword ptr vs_parm1
  587.     mov    word ptr blockaddr,bx
  588.     mov    word ptr blockaddr+2,es
  589.     les    bx,dword ptr vs_parm6
  590.     mov    ax,es
  591.     add    bx,word ptr blockaddr
  592.     adc    ax,0
  593.     shl    ax,12
  594.     add    ax,word ptr blockaddr+2
  595.     mov    word ptr currentaddr,bx
  596.     mov    word ptr currentaddr+2,ax
  597.     mov    word ptr fwrtaddr,bx
  598.     mov    word ptr fwrtaddr+2,ax
  599.     les    bx,dword ptr vs_parm2
  600.     mov    word ptr blocksize,bx
  601.     mov    word ptr blocksize+2,es
  602.     mov    ax,es
  603.     add    bx,word ptr blockaddr
  604.     adc    ax,0
  605.     shl    ax,12
  606.     add    ax,word ptr blockaddr+2
  607.     mov    word ptr blockend,bx
  608.     mov    word ptr blockend+2,ax
  609.     cmp    ax,word ptr currentaddr+2
  610.     jb    vs_error4
  611.     ja    vs_gethandle
  612.     cmp    bx,word ptr currentaddr
  613.     jbe    vs_error4
  614.  
  615. vs_gethandle:
  616.     mov    ax,vs_parm4
  617.     mov    filehandle,ax
  618.  
  619.     mov    bx,vs_parm5
  620.     cmp    bx,1
  621.     jb    vs_error3
  622.     cmp    bx,4
  623.     ja    vs_error3
  624.     dec    bx
  625.     shl    bx,1
  626.     lea    ax,comlist
  627.     add    bx,ax
  628.     mov    ax,[bx]
  629.     mov    comaddr,ax
  630.  
  631.     mov    ax,vs_parm3
  632.     mov    fileflag,ax
  633.  
  634.     or    ax,ax
  635.     jz    vs_exit0
  636.  
  637.     mov    ax,word ptr blocksize
  638.     sub    ax,min_blocksize
  639.     mov    ax,word ptr blocksize+2
  640.     sbb    ax,0
  641.     jnc    vs_exit0
  642.     mov    ax,1
  643.     jmp    short vs_exit
  644.  
  645. vs_error3:
  646.     mov    ax,3
  647.     jmp    short vs_exit
  648.  
  649. vs_error4:
  650.     mov    ax,4
  651.     jmp    short vs_exit
  652.  
  653. vs_exit0:
  654.     call    startvoice
  655.     sub    ax,ax
  656. vs_exit:
  657.     leave
  658.     ret    vs_parmlength
  659.  
  660. RVOICE_START    endp
  661.  
  662. ;**********************************************************************
  663. ;*                   "Stop recording" procedure                       *
  664. ;**********************************************************************
  665.  
  666. ;Call this to stop the voice recording operation.
  667.  
  668. ;This routine accepts no parameters and has no return information.
  669.  
  670.     public    RVOICE_STOP
  671.  
  672. RVOICE_STOP    proc    far
  673.  
  674.     call    stopvoice
  675.     sub    ax,ax
  676.     ret
  677.  
  678. RVOICE_STOP    endp
  679.  
  680. ;**********************************************************************
  681. ;*                     "Get status" procedure                         *
  682. ;**********************************************************************
  683.  
  684. ;This will report the status of voice operations.
  685.  
  686. ;The first parameter is a far pointer to a dword which will receive the
  687. ; number of bytes which have already been recorded.
  688. ;The second parameter is a far pointer to a dword which will receive a
  689. ; value indicating the offset within the memory block of the next byte
  690. ; to be filled by the recording operation.
  691.  
  692. ;There is no return value.
  693.  
  694. vst_parm1    equ    [bp+10]    ;length = 4
  695. vst_parm2    equ    [bp+6]    ;length = 4
  696.  
  697. vst_parmlength    equ    8
  698.  
  699.     public    RVOICE_STATUS
  700.  
  701. RVOICE_STATUS    proc    far
  702.  
  703.     enter    0,0
  704.  
  705.     les    bx,vst_parm1
  706.     cli
  707.     mov    ax,word ptr datacount
  708.     mov    dx,word ptr datacount+2
  709.     mov    es:[bx],ax
  710.     mov    es:[bx+2],dx
  711.     les    bx,vst_parm2
  712.     mov    ax,word ptr currentaddr
  713.     mov    dx,word ptr currentaddr+2
  714.     sti
  715.     shr    dx,12    ;we can cheat here because we
  716.             ; know it's incremented by 1000h units
  717.     mov    cx,word ptr blockaddr+2
  718.     shr    cx,12
  719.     sub    ax,word ptr blockaddr
  720.     sbb    dx,cx
  721.     mov    es:[bx],ax
  722.     mov    es:[bx+2],dx
  723.  
  724.     sub    ax,ax
  725.     leave
  726.     ret    vst_parmlength
  727.  
  728. RVOICE_STATUS    endp
  729.  
  730.     end
  731.