TIMEREAL.ASM 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ;***************************************************************************
  19. ;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
  20. ;***************************************************************************
  21. ;* *
  22. ;* Project Name : Timer interrupt for RM *
  23. ;* *
  24. ;* File Name : TIMEREAL.ASM *
  25. ;* *
  26. ;* Programmer : Scott K. Bowen *
  27. ;* *
  28. ;* Start Date : July 8, 1994 *
  29. ;* *
  30. ;* Last Update : July 8, 1994 [SKB] *
  31. ;* *
  32. ;*-------------------------------------------------------------------------*
  33. ;* Functions: *
  34. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  35. IDEAL
  36. MODEL TINY
  37. P386N
  38. LOCALS ??
  39. ;//////////////////////////////////////////////////////////////////////////////////////
  40. ;///////////////////////////////////// Equates ////////////////////////////////////////
  41. INTCHIP0 EQU 20h ; 8259 interrupt chip controller 0
  42. CLEARISR EQU 20h ; Value to write to 8259 to reenable interrupts.
  43. CODESEG
  44. ;//////////////////////////////////////////////////////////////////////////////////////
  45. ;///////////////////////////////////// Data ////////////////////////////////////////
  46. ; This information may not change unless the protected mode version is
  47. ; also changed.
  48. ; For speed, PM uses a DD while RM used DW
  49. TrueRate DW 0 ; True rate of clock. (only use word)
  50. TrueRateNA DW 0 ; used for speed in prot mode.
  51. ; For speed, SysRate and SysError are DD in PM and are DW in real mode.
  52. SysTicks DD 0 ; Tick count of timer.
  53. SysRate DD 0 ; Desired rate of timer.
  54. SysError DD 0 ; Amount of error in clock rate for desired frequency.
  55. SysCurRate DW 0 ; Keeps track of when to increment timer.
  56. SysCurError DW 0 ; Keeps track of amount of error in timer.
  57. UserTicks DD 0 ; Tick count of timer.
  58. UserRate DD 0 ; Desired rate of timer.
  59. UserError DD 0 ; Amount of error in clock rate for desired frequency.
  60. UserCurRate DW 0 ; Keeps track of when to increment timer.
  61. UserCurError DW 0 ; Keeps track of amount of error in timer.
  62. DosAdder DW 0 ; amount to add to DosFraction each interrupt.
  63. DosFraction DW 0 ; Call dos when overflowed.
  64. OldRMI DD 0 ; The origianl RM interrupt seg:off.
  65. OldPMIOffset DD 0 ; The origianl PM interrupt offset
  66. OldPMISelector DD 0 ; The original PM interrupt segment.
  67. CodeOffset DW RM_Timer_Interrupt_Handler ; Offset of the code in the RM stuff.
  68. CallRMIntOffset DW Call_Interrupt_Chain ; Offset of function to call DOS timer interrupt.
  69. CallRMIntAddr DD 0 ; PM address of CallRealIntOffset for speed.
  70. PMIssuedInt DD 0 ; PM signals RM to just call Int chain.
  71. ; These are just used for information on testing. When all is done, they can
  72. ; be removed, but why? The don't add too much proccessing time and can
  73. ; be useful.
  74. NumPMInts DD 0 ; Number of PM interrupts
  75. NumRMInts DD 0 ; Number of RM interrupts.
  76. ;//////////////////////////////////////////////////////////////////////////////////////
  77. ;///////////////////////////////////// Code ////////////////////////////////////////
  78. ; This is here for easy comparison with the PM version.
  79. MACRO INCREMENT_TIMERS
  80. inc [NumRMInts] ; For testing.
  81. ; At this point, increment the system and user timers.
  82. mov ax,[TrueRate] ; Get the rate of the PC clock.
  83. sub [SysCurRate],ax ; Sub from our rate counter.
  84. ja ??end_sys ; If !below zero, do not inc.
  85. mov bx,[WORD PTR SysRate] ; Get rate of timer.
  86. mov dx,[WORD PTR SysError] ; Get amount of error.
  87. add [SysCurRate],bx ; Add rate to the current.
  88. sub [SysCurError],dx ; Subtract err from error count.
  89. jb ??error_adj_sys ; If !below 0, increment counter.
  90. inc [SysTicks] ; increment the timer.
  91. jmp short ??end_sys ; don't modify SysCurError.
  92. ??error_adj_sys:
  93. add [SysCurError],bx ; reajust the error by timer rate.
  94. ??end_sys:
  95. sub [UserCurRate],ax ; Sub from our rate counter.
  96. ja ??end_user ; If !below zero, do not inc.
  97. mov bx,[WORD PTR UserRate] ; Get rate of timer.
  98. mov dx,[WORD PTR UserError] ; Get amount of error.
  99. add [UserCurRate],bx ; Add rate to the current.
  100. sub [UserCurError],dx ; Subtract err from error count.
  101. jb ??error_adj_user ; If !below 0, increment counter.
  102. inc [UserTicks] ; increment the timer.
  103. jmp short ??end_user ; don't modify UserCurError.
  104. ??error_adj_user:
  105. add [UserCurError],bx ; reajust the error by timer rate.
  106. ??end_user:
  107. ENDM
  108. ;**************************************************************************
  109. ;* RM_INTERRUPT_HANDLER -- Called when processor interrupted in real mode. *
  110. ;* *
  111. ;* *
  112. ;* INPUT: *
  113. ;* *
  114. ;* OUTPUT: *
  115. ;* *
  116. ;* WARNINGS: *
  117. ;* *
  118. ;* HISTORY: *
  119. ;* 07/08/1994 SKB : Created. *
  120. ;*=========================================================================*
  121. label RM_Timer_Interrupt_Handler
  122. start_RM_Timer_Interrupt_Handler:
  123. push ax
  124. push bx
  125. push dx
  126. push ds
  127. mov ax,cs ; Set data segment to code segment
  128. mov ds,ax ; since data is in code seg.
  129. cmp [WORD PTR PMIssuedInt],0; Check to see if PM made Int call.
  130. mov [WORD PTR PMIssuedInt],0; Make it false.
  131. jne ??call_int_chain ; if so, just call Int Chain.
  132. INCREMENT_TIMERS
  133. ; Now check to see if we should call the old timer handler.
  134. mov ax,[DosAdder] ; Get amount to add each tick.
  135. add [DosFraction],ax ; add it to the fraction.
  136. jnc ??no_int_chain ; Skip call if no overflow.
  137. ??call_int_chain:
  138. pushf ; Push flags for interrupt call.
  139. call [OldRMI] ; chain the call.
  140. ??no_int_chain:
  141. sti
  142. mov al,CLEARISR ; value to clear In Service Register
  143. mov dx,INTCHIP0
  144. out dx,al ; 8259 interrupt chip controller 0
  145. exit1:
  146. pop ds
  147. pop dx
  148. pop bx
  149. pop ax
  150. iret
  151. ;**************************************************************************
  152. ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*
  153. ;* *
  154. ;* *
  155. ;* INPUT: *
  156. ;* *
  157. ;* OUTPUT: *
  158. ;* *
  159. ;* WARNINGS: *
  160. ;* *
  161. ;* HISTORY: *
  162. ;* 07/08/1994 SKB : Created. *
  163. ;*=========================================================================*
  164. Call_Interrupt_Chain:
  165. pushf
  166. call [OldRMI] ;
  167. retf
  168. STACK ; Don't really need this
  169. END
  170. IF 0
  171. ; mono print stuff.
  172. pushf
  173. push ax
  174. push di
  175. push es
  176. mov ax,0B000h ; ES:DI = Mono RAM address.
  177. mov es,ax
  178. mov al,'A'
  179. mov ah,2
  180. and di,63
  181. stosw
  182. pop es
  183. pop di
  184. pop ax
  185. popf
  186. ENDIF