home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / bios / csstuff / timer.asm < prev   
Assembly Source File  |  1998-06-08  |  20KB  |  686 lines

  1. ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  2. ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  3. ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  4. ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  5. ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  6. ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  7. ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  8. ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  9. ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  10. ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  11. ;
  12. ; $Source: f:/miner/source/bios/rcs/timer.asm $
  13. ; $Revision: 1.28 $
  14. ; $Author: matt $
  15. ; $Date: 1995/02/15 01:36:56 $
  16. ;
  17. ; Routines for setting and using system timers
  18. ;
  19. ; $Log: timer.asm $
  20. ; Revision 1.28  1995/02/15  01:36:56  matt
  21. ; Cleaned up code to avoid doing out 20,20 more than once
  22. ; Revision 1.27  1995/02/14  11:39:37  john
  23. ; Fixed bug with joystick handler not having enough
  24. ; stack space under Windows.
  25. ; Revision 1.26  1995/02/09  21:51:39  john
  26. ; Made so that DOS timer interrupt gets called before interrupts are
  27. ; enabled in timer interpt because not doing this cause conflicts with
  28. ; ps2 style mice and smartdrv with write caching enabled that hangs the
  29. ; program and trashes the FAT.
  30. ; Revision 1.25  1995/02/04  15:39:33  john
  31. ; More time interrupt changes.
  32. ; Revision 1.24  1995/02/03  23:25:21  john
  33. ; Made so that when interrupts are nested, the time interrupt still
  34. ; calls the DOS one.
  35. ; Revision 1.23  1995/01/29  19:00:42  john
  36. ; Made latching timer value more readable.
  37. ; Revision 1.22  1995/01/17  10:34:53  mike
  38. ; prevent divide overflows.
  39. ; Revision 1.21  1994/12/15  11:10:54  john
  40. ; Added code that should make DOS 18.2 callbacks 
  41. ; a bit more accurate.
  42. ; Revision 1.20  1994/12/10  12:47:34  john
  43. ; Made so that timer_get_fixed seconds and get_approx seconds are always equal.
  44. ; Revision 1.19  1994/12/10  12:27:34  john
  45. ; Added timer_get_approx_seconds.
  46. ; Revision 1.18  1994/12/10  12:07:14  john
  47. ; Added tick counter variable.
  48. ; Revision 1.17  1994/12/04  11:55:16  john
  49. ; Made stick read at whatever rate the clock is at, not
  50. ; at 18.2 times/second.
  51. ; Revision 1.16  1994/11/28  15:24:10  john
  52. ; Cleaned up timer interrupt a bit.
  53. ; Revision 1.15  1994/11/22  17:00:43  john
  54. ; Made the timer handler fill in ES along with DS.
  55. ; The HMI drivers expect this.
  56. ; Revision 1.14  1994/11/15  12:04:38  john
  57. ; Cleaned up timer code a bit... took out unused functions
  58. ; like timer_get_milliseconds, etc.
  59. ; Revision 1.13  1994/10/05  16:17:40  john
  60. ; Made interrupts more stable.
  61. ; Revision 1.12  1994/09/29  18:29:57  john
  62. ; Enabled interrupts whil calling the user_function.
  63. ; Revision 1.11  1994/09/23  16:00:31  john
  64. ; MAde the timer interrupt switch to a 4K stack
  65. ; before calling the timer_function.
  66. ; Revision 1.10  1994/09/22  16:09:21  john
  67. ; Fixed some virtual memory lockdown problems with timer and
  68. ; joystick.
  69. ; Revision 1.9  1994/04/29  12:13:48  john
  70. ; Locked all memory used during interrupts so that program
  71. ; won't hang when using virtual memory.
  72. ; Revision 1.8  1994/04/28  23:50:49  john
  73. ; Changed calling for init_timer.  Made the function that the
  74. ; timer calls be a far function. All of this was done to make
  75. ; our timer system compatible with the HMI sound stuff.
  76. ; Revision 1.7  1994/02/17  15:57:15  john
  77. ; Changed key libary to C.
  78. ; Revision 1.6  1994/01/18  20:19:17  john
  79. ; Fixed minor flaws with pending interrupts,
  80. ; interfaced with joystick code.
  81. ; Revision 1.5  1994/01/18  13:54:18  john
  82. ; Fixed a few miner flaws.
  83. ; Revision 1.4  1994/01/18  10:58:25  john
  84. ; Added timer_get_fixed_seconds
  85. ; Revision 1.3  1993/12/20  15:40:59  john
  86. ; *** empty log message ***
  87. ; Revision 1.2  1993/09/23  18:08:44  john
  88. ; added code so that timer_init can handle multiple calls.
  89. ; added code so that atexit is called.
  90. ; Revision 1.1  1993/07/10  13:10:43  matt
  91. ; Initial revision
  92. ;
  93. ;
  94.  
  95. ;***************************************************************************
  96. ;***************************************************************************
  97. ;*****                                                                 *****
  98. ;*****                     T I M E R . A S M                           *****
  99. ;*****                                                                 *****
  100. ;*****                                                                 *****
  101. ;***** PROCEDURES                                                      *****
  102. ;*****                                                                 *****
  103. ;*****                                                                 *****
  104. ;*****                                                                 *****
  105. ;***** VARIABLES                                                       *****
  106. ;*****                                                                 *****
  107. ;*****                                                                 *****
  108. ;***** CONSTANTS                                                       *****
  109. ;*****                                                                 *****
  110. ;*****                                                                 *****
  111. ;***************************************************************************
  112. ;***************************************************************************
  113.  
  114. .386
  115.  
  116. ;************************************************************************
  117. ;**************** FLAT MODEL DATA SEGMENT STUFF *************************
  118. ;************************************************************************
  119.  
  120. _DATA   SEGMENT BYTE PUBLIC USE32 'DATA'
  121.  
  122. rcsid    db    "$Id: timer.asm 1.28 1995/02/15 01:36:56 matt Exp $"
  123.  
  124. TDATA           EQU     40h
  125. TCOMMAND        EQU     43h
  126. PIC             EQU     020h
  127. STACK_SIZE    EQU    4096    ; A 4K stack
  128.  
  129. TIMER_DATA STRUCT   
  130.     in_timer    db  0
  131.  
  132.     nested_counter    dd    0
  133.  
  134.     _timer_cnt      dd  65536
  135.     dos_timer          dd  0
  136.     sound_timer     dd  0
  137.     joystick_timer  dd  0
  138.  
  139.     joystick_poller    dd  0
  140.  
  141.     user_function   df  0
  142.     
  143.     org_interrupt    df  0    
  144.  
  145.     saved_stack    df  0
  146.  
  147.     new_stack    df  0
  148.  
  149.     tick_count    dd  0
  150.  
  151.     Installed db     0
  152.  
  153.     TimerStack    db  STACK_SIZE dup (0)        
  154. TIMER_DATA ENDS
  155.  
  156.     TimerData    TIMER_DATA <>    
  157.  
  158. _DATA   ENDS
  159.  
  160. DGROUP  GROUP _DATA
  161.  
  162.  
  163. ;************************************************************************
  164. ;**************** FLAT MODEL CODE SEGMENT STUFF *************************
  165. ;************************************************************************
  166.  
  167. _TEXT   SEGMENT BYTE PUBLIC USE32 'CODE'
  168.  
  169.         ASSUME  ds:_DATA
  170.         ASSUME  cs:_TEXT
  171.  
  172. INCLUDE PSMACROS.INC
  173.  
  174. TIMER_LOCKED_CODE_START:
  175.  
  176.         extn atexit_
  177.  
  178. PUBLIC timer_get_stamp64
  179.  
  180. timer_get_stamp64:
  181.         ; Return a 64-bit stamp that is the number of 1.19Mhz pulses
  182.         ; since the time was initialized.  Returns in EDX:EAX.
  183.         ; Also, interrupts must be disabled.
  184.  
  185.         xor     eax, eax            ; Clear all of EAX
  186.         out     TCOMMAND, al        ; Tell timer to latch
  187.  
  188.         mov     al, 0ah             ; Find if interrupt pending
  189.         out     PIC, al
  190.         jmp    @f
  191. @@:        in      al, PIC
  192.         and     eax, 01b
  193.         jz      NoInterrupt
  194.  
  195.         in      al, TDATA           ; Read in lo byte
  196.         mov     dl, al
  197.             in      al, TDATA           ; Read in hi byte
  198.         mov    dh, al
  199.         and    edx, 0ffffh
  200.         mov    eax, TimerData._timer_cnt
  201.         shl    eax, 1        
  202.         sub    eax, edx
  203.             
  204.         push    ebx
  205.         mov    ebx, eax
  206.         mov    eax, TimerData.tick_count
  207.         imul    TimerData._timer_cnt    ; edx:eax = Number of 1.19 MHz ticks elapsed...
  208.         add    eax, ebx
  209.         adc    edx, 0                
  210.         pop    ebx
  211.  
  212.         ret
  213.  
  214. NoInterrupt:
  215.         in      al, TDATA           ; Read in lo byte
  216.         mov     ah, al
  217.         in      al, TDATA           ; Read in hi byte
  218.         xchg    ah, al              ; arrange em correctly
  219.         mov     edx, TimerData._timer_cnt
  220.         sub     dx, ax              ; BX = timer ticks
  221.         mov     ax, dx
  222.  
  223.         push    ebx
  224.         mov    ebx, eax
  225.         mov    eax, TimerData.tick_count
  226.         imul    TimerData._timer_cnt    ; edx:eax = Number of 1.19 MHz ticks elapsed...
  227.         add    eax, ebx
  228.         adc    edx, 0                
  229.         pop    ebx
  230.  
  231.         ret
  232.  
  233.  
  234. PUBLIC  timer_get_fixed_seconds_
  235.  
  236. timer_get_fixed_seconds_:
  237.         push    ebx
  238.         push    edx
  239.  
  240.         cli
  241.         call    timer_get_stamp64
  242.         sti
  243.  
  244.         ; Timing in fixed point (16.16) seconds.
  245.         ; Can be used for up to 1000 hours
  246.         shld    edx, eax, 16            ; Keep 32+11 bits
  247.         shl     eax, 16            
  248.         ; edx:eax = number of 1.19Mhz pulses elapsed.
  249.         mov     ebx, 1193180
  250.  
  251. ; Make sure we won't divide overflow.  Make time wrap at about 9 hours
  252. sub_again:        sub     edx, ebx    ; subtract until negative...
  253.         jns     sub_again    ; ...to prevent divide overflow...
  254.         add     edx, ebx    ; ...then add in to get correct value.
  255.         div     ebx
  256.         ; eax = fixed point seconds elapsed...
  257.  
  258.         pop     edx
  259.         pop     ebx
  260.  
  261.         ret
  262.  
  263. PUBLIC  timer_get_fixed_secondsX_
  264.  
  265. timer_get_fixed_secondsX_:
  266.         push    ebx
  267.         push    edx
  268.  
  269.         call    timer_get_stamp64
  270.  
  271.         ; Timing in fixed point (16.16) seconds.
  272.         ; Can be used for up to 1000 hours
  273.         shld    edx, eax, 16            ; Keep 32+11 bits
  274.         shl     eax, 16            
  275.         ; edx:eax = number of 1.19Mhz pulses elapsed.
  276.         mov     ebx, 1193180
  277.  
  278. xsub_again:        sub     edx, ebx    ; subtract until negative...
  279.         jns     xsub_again    ; ...to prevent divide overflow...
  280.         add     edx, ebx    ; ...then add in to get correct value.
  281.  
  282.         div     ebx
  283.         ; eax = fixed point seconds elapsed...
  284.  
  285.         pop     edx
  286.         pop     ebx
  287.  
  288.         ret
  289.  
  290. PUBLIC timer_get_approx_seconds_
  291. timer_get_approx_seconds_:
  292.     push    ebx
  293.     push    edx
  294.  
  295.     mov    eax, TimerData.tick_count
  296.     imul    TimerData._timer_cnt    ; edx:eax = Number of 1.19 MHz ticks elapsed...
  297.     shld    edx, eax, 16            ; Keep 32+16 bits, for conversion to fixed point
  298.     shl     eax, 16            
  299.     ; edx:eax = number of 1.19Mhz pulses elapsed.
  300.     mov     ebx, 1193180
  301.  
  302. approx_sub_again:    sub     edx, ebx    ; subtract until negative...
  303.     jns     approx_sub_again    ; ...to prevent divide overflow...
  304.     add     edx, ebx    ; ...then add in to get correct value.
  305.  
  306.     div     ebx
  307.     ; eax = fixed point seconds elapsed...
  308.  
  309.     pop    edx
  310.     pop    ebx
  311.     ret
  312.  
  313.  
  314.  
  315. ;extern void timer_set_rate(int count_val);
  316. ;extern void timer_set_function( void _far * function );
  317.  
  318. PUBLIC  timer_set_rate_
  319. timer_set_rate_:
  320.     ; eax = rate
  321.     pushad
  322.  
  323.     ; Make sure eax below or equal to 65535 and above 0
  324.     ; if its not, make it be 65536 which is normal dos
  325.     ; timing.
  326.     cmp    eax, 65535
  327.     jbe    @f
  328.     mov    eax, 65536
  329. @@:    cmp    eax, 0
  330.     jne    @f
  331.     mov    eax, 65536
  332. @@:    ; Set the timer rate to eax
  333.     cli
  334.     mov    TimerData.tick_count, 0
  335.     mov     TimerData._timer_cnt, eax        
  336.     mov     al, 34h        ; count in binary, mode 2, load low byte then hi byte, counter 0:  00 11 010 0
  337.     out     TCOMMAND, al    ; Reset PIT channel 0
  338.     mov     eax, TimerData._timer_cnt
  339.     out     TDATA, al
  340.     mov     al, ah
  341.     out     TDATA, al
  342.     sti
  343.     popad
  344.     ret
  345.  
  346. PUBLIC  timer_set_function_
  347. timer_set_function_:
  348.     ; dx:eax = far pointer to user function
  349.     pushad
  350.     cli
  351.     mov    dword ptr TimerData.user_function[0], eax    ; offset
  352.     mov     word ptr TimerData.user_function[4], dx        ; selector
  353.     sti
  354.     popad
  355.     ret
  356.  
  357. PUBLIC timer_set_joyhandler_
  358. timer_set_joyhandler_:
  359.     cli
  360.     mov    TimerData.joystick_poller, eax
  361.     sti
  362.     ret
  363.  
  364.  
  365. ;************************************************************************
  366. ;************************************************************************
  367. ;*****                                                              *****
  368. ;*****                T I M E R _ H A N D L E R                     *****
  369. ;*****                                                              *****
  370. ;************************************************************************
  371. ;************************************************************************
  372.  
  373. timer_handler:
  374.         push    ds
  375.         push    es
  376.         push    eax
  377.  
  378.         mov     ax, DGROUP       ; Interrupt, so point to our data segment
  379.         mov     ds, ax
  380.         mov     es, ax
  381.  
  382.         ; Increment time counter...
  383.         inc    TimerData.tick_count
  384.                 
  385.         cmp    TimerData._timer_cnt, 9940
  386.         ja    NotEveryOtherTime            
  387.         
  388.         test    TimerData.tick_count, 1
  389.         jz    NotEveryOtherTime
  390.         
  391.         ; every other time, do vsync...
  392.         push    edx
  393.         mov     dx, 3DAh
  394. VS2B:       in      al, dx
  395.         and     al, 08h
  396.         jz      VS2B        ; Loop until in vertical retrace
  397.         pop    edx
  398.  
  399.         mov     al, 34h        ; count in binary, mode 2, load low byte then hi byte, counter 0:  00 11 010 0
  400.         out     TCOMMAND, al    ; Reset PIT channel 0
  401.         mov     eax, TimerData._timer_cnt
  402.         out     TDATA, al
  403.         mov     al, ah
  404.         out     TDATA, al
  405.  
  406. NotEveryOtherTime:
  407.         mov    eax, TimerData._timer_cnt
  408.         add     TimerData.dos_timer, eax        ; Increment DOS timer
  409.         add    TimerData.sound_timer, eax
  410.         add    TimerData.joystick_timer, eax
  411.         cmp    TimerData.dos_timer, 65536
  412.         jb    NoChainToOld            ; See if we need to chain to DOS 18.2
  413.         and    TimerData.dos_timer, 0ffffh
  414.  
  415.         ;
  416.         ; Call the original DOS handler....
  417.         ;
  418.         pushfd
  419.         call    fword ptr [TimerData.org_interrupt]
  420.  
  421.         jmp    NoReset        ;old handler has reset, so we don't
  422.  
  423. NoChainToOld:
  424.         ; Reset controller
  425.         mov     al, 20h         ; Reset interrupt controller
  426.         out     20h, al
  427.  
  428. NoReset:
  429.         cmp    TimerData.in_timer, 0
  430.         jne    ExitInterrupt
  431.  
  432.         mov    TimerData.in_timer, 1        ; Mark that we're in a timer interrupt...
  433.  
  434.         ; Reenable interrupts
  435.         sti            ; Reenable interrupts
  436.  
  437.         cmp     word ptr TimerData.user_function[4], 0        ; Check the selector...
  438.         je      NoUserFunction
  439.  
  440.         cmp    TimerData.sound_timer, 9943
  441.         jb    NoUserFunction            ; See if we need to call the 120 hz sound mixer.
  442.         sub    TimerData.sound_timer, 9943
  443.  
  444.         ; Switch stacks while calling the user-definable function...
  445.         pushad
  446.         push    fs
  447.         push    gs
  448.         mov    dword ptr TimerData.saved_stack[0], esp
  449.         mov    word ptr TimerData.saved_stack[4], ss
  450.         lss    esp, TimerData.new_stack    ; Switch to new stack
  451.         call    fword ptr [TimerData.user_function]    ; Call new function
  452.         lss    esp,  TimerData.saved_stack    ; Switch back to original stack
  453.         pop    gs
  454.         pop    fs
  455.         popad
  456.  
  457. NoUserFunction:    
  458.         cmp    dword ptr TimerData.joystick_poller, 0
  459.         je    NoJoyPolling
  460.  
  461.         
  462.         mov    eax, 39772
  463.         cmp    TimerData.joystick_timer, eax
  464.         jb    NoJoyPolling            ; See if we poll the joystick buttons
  465.         sub    TimerData.joystick_timer, eax
  466.  
  467.         mov    dword ptr TimerData.saved_stack[0], esp
  468.         mov    word ptr TimerData.saved_stack[4], ss
  469.         lss    esp, TimerData.new_stack    ; Switch to new stack
  470.         call    dword ptr TimerData.joystick_poller
  471.         lss    esp,  TimerData.saved_stack    ; Switch back to original stack
  472.  
  473. NoJoyPolling:
  474.         cli
  475.         mov    TimerData.in_timer, 0
  476.  
  477. ExitInterrupt:
  478.         pop    eax
  479.         pop    es
  480.         pop    ds
  481.         iretd                ; Return from timer interrupt
  482.  
  483.  
  484. TIMER_LOCKED_CODE_STOP:
  485.  
  486. ;************************************************************************
  487. ;************************************************************************
  488. ;*****                                                              *****
  489. ;*****                   T I M E R _ I N I T                        *****
  490. ;*****                                                              *****
  491. ;************************************************************************
  492. ;************************************************************************
  493.  
  494.  
  495. PUBLIC  timer_init_
  496.  
  497. timer_init_:
  498.         pushad
  499.         push    ds
  500.         push    es
  501.  
  502.         cmp     TimerData.Installed, 1
  503.         je      AlreadyInstalled
  504.  
  505.         mov     TimerData._timer_cnt, 65536    ; Set to BIOS's normal 18.2 Hz
  506.         mov     TimerData.dos_timer, 0        ; clear DOS Interrupt counter
  507.         mov    TimerData.sound_timer, 0    ; clear 120 hz handler
  508.         mov    TimerData.joystick_timer, 0    ; clear joystick poller
  509.         mov     dword ptr TimerData.user_function[0], 0    ; offset of user function
  510.         mov     word ptr TimerData.user_function[4], 0    ; selector of user function
  511.  
  512.         lea    eax, ds:[TimerData.TimerStack]    ; Use EAX as temp stack pointer
  513.         add    eax, STACK_SIZE            ; Top of stack minus space for saving old ss:esp
  514.         mov    dword ptr TimerData.new_stack[0], eax
  515.         mov    word ptr TimerData.new_stack[4], ds
  516.  
  517.         ;--------------- lock data used in interrupt
  518.         mov    eax, SIZEOF TIMER_DATA
  519.         mov    esi, eax
  520.         shr    esi, 16            
  521.         mov    edi, eax
  522.         and    edi, 0ffffh    ; si:di = length of region to lock in bytes
  523.         lea    ebx, ds:TimerData
  524.         lea    ecx, ds:TimerData
  525.         shr    ebx, 16
  526.         and    ecx, 0ffffh    ; bx:cx = start of linear address to lock
  527.         mov    eax, 0600h    ; DPMI lock address function
  528.         int    31h        ; call dpmi
  529.         jnc    @f
  530.         int    3        ; LOCK FAILED!!
  531. @@:
  532.         ;--------------- lock code used in interrupt
  533.         lea    eax, cs:TIMER_LOCKED_CODE_STOP
  534.         lea    ecx, cs:TIMER_LOCKED_CODE_START
  535.         sub    eax, ecx
  536.         inc    eax        ; EAX = size of timer interrupt handler
  537.         mov    esi, eax
  538.         shr    esi, 16            
  539.         mov    edi, eax
  540.         and    edi, 0ffffh    ; si:di = length of region to lock in bytes
  541.         lea    ebx, cs:TIMER_LOCKED_CODE_START
  542.         lea    ecx, cs:TIMER_LOCKED_CODE_START
  543.         shr    ebx, 16
  544.         and    ecx, 0ffffh    ; bx:cx = start of linear address to lock
  545.         mov    eax, 0600h    ; DPMI lock address function
  546.         int    31h        ; call dpmi
  547.         jnc    @f
  548.         int    3        ; LOCK FAILED!!
  549. @@:
  550.  
  551.         ;**************************************************************
  552.         ;******************* SAVE OLD INT8 HANDLER ********************
  553.         ;**************************************************************
  554.         mov     eax, 03508h             ; DOS Get Vector 08h
  555.         int     21h                     ; Call DOS
  556.  
  557.         mov     dword ptr TimerData.org_interrupt[0], ebx    ; offset of user function
  558.         mov    word ptr TimerData.org_interrupt[4], es        ; selector of user function
  559.  
  560.         ;**************************************************************
  561.         ;***************** INSTALL NEW INT8 HANDLER *******************
  562.         ;**************************************************************
  563.  
  564.         cli
  565.  
  566.         mov     al, 34h        ; count in binary, mode 2, load low byte then hi byte, counter 0:  00 11 010 0
  567.         out     TCOMMAND, al    ; Reset PIT channel 0
  568.         mov     eax, TimerData._timer_cnt
  569.         out     TDATA, al
  570.         mov     al, ah
  571.         out     TDATA, al
  572.  
  573.         mov     TimerData.tick_count, 0
  574.         mov     TimerData.Installed,1
  575.  
  576.         mov     eax, 02508h             ; DOS Set Vector 08h
  577.         mov     edx, offset timer_handler  ; Point DS:EDX to new handler
  578.         mov     bx, cs
  579.         push    ds
  580.         mov     ds, bx
  581.         int     21h
  582.         pop     ds
  583.         sti
  584.         lea     eax, cs:timer_close_
  585.         call    atexit_
  586.  
  587. AlreadyInstalled:
  588.  
  589.         pop     es
  590.         pop     ds
  591.         popad
  592.  
  593.         ret
  594.  
  595.  
  596. ;************************************************************************
  597. ;************************************************************************
  598. ;*****                                                              *****
  599. ;*****                  T I M E R _ C L O S E _                     *****
  600. ;*****                                                              *****
  601. ;************************************************************************
  602. ;************************************************************************
  603.  
  604. PUBLIC  timer_close_
  605.  
  606. timer_close_:
  607.         push    eax
  608.         push    edx
  609.         push    ds
  610.  
  611.  
  612.         cmp     TimerData.Installed, 0
  613.         je      NotInstalled
  614.         mov     TimerData.Installed, 0
  615.  
  616.         ;**************************************************************
  617.         ;***************** RESTORE OLD INT9 HANDLER *******************
  618.         ;**************************************************************
  619.  
  620.         cli
  621.         mov     al, 36h        ; count in binary, mode 3, load low byte then hi byte, counter 0:  00 11 011 0
  622.         out     TCOMMAND, al    ; Reser PIT channel 0
  623.         mov     ax, 0h
  624.         out     TDATA, al
  625.         mov     al, ah
  626.         out     TDATA, al
  627.  
  628.         push    ds
  629.         mov     eax, 02508h         ; DOS Set Vector 08h
  630.         mov     edx, dword ptr TimerData.org_interrupt[0]
  631.         mov     ds, word ptr TimerData.org_interrupt[4]
  632.         int     21h
  633.         pop    ds
  634.  
  635.         sti
  636.         
  637.         cmp    TimerData.nested_counter, 0
  638.         je    NoNestedInterrupts
  639.         mov    eax, TimerData.nested_counter
  640.         ;int     3        ; Get John!!
  641.     
  642. NoNestedInterrupts:
  643.         
  644.  
  645. NotInstalled:
  646.         pop     ds
  647.         pop     edx
  648.         pop     eax
  649.  
  650.         ret
  651.  
  652.  
  653. _TEXT           ENDS
  654.  
  655.  
  656.         END
  657. 
  658.