| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- ;
- ; Command & Conquer Red Alert(tm)
- ; Copyright 2025 Electronic Arts Inc.
- ;
- ; This program is free software: you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, either version 3 of the License, or
- ; (at your option) any later version.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program. If not, see <http://www.gnu.org/licenses/>.
- ;
- ;***************************************************************************
- ;** 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 **
- ;***************************************************************************
- ;* *
- ;* Project Name : Timer interrupt for RM *
- ;* *
- ;* File Name : TIMEREAL.ASM *
- ;* *
- ;* Programmer : Scott K. Bowen *
- ;* *
- ;* Start Date : July 8, 1994 *
- ;* *
- ;* Last Update : July 8, 1994 [SKB] *
- ;* *
- ;*-------------------------------------------------------------------------*
- ;* Functions: *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- IDEAL
- MODEL TINY
- P386N
- LOCALS ??
- ;//////////////////////////////////////////////////////////////////////////////////////
- ;///////////////////////////////////// Equates ////////////////////////////////////////
- INTCHIP0 EQU 20h ; 8259 interrupt chip controller 0
- CLEARISR EQU 20h ; Value to write to 8259 to reenable interrupts.
- CODESEG
- ;//////////////////////////////////////////////////////////////////////////////////////
- ;///////////////////////////////////// Data ////////////////////////////////////////
- ; This information may not change unless the protected mode version is
- ; also changed.
- ; For speed, PM uses a DD while RM used DW
- TrueRate DW 0 ; True rate of clock. (only use word)
- TrueRateNA DW 0 ; used for speed in prot mode.
- ; For speed, SysRate and SysError are DD in PM and are DW in real mode.
- SysTicks DD 0 ; Tick count of timer.
- SysRate DD 0 ; Desired rate of timer.
- SysError DD 0 ; Amount of error in clock rate for desired frequency.
- SysCurRate DW 0 ; Keeps track of when to increment timer.
- SysCurError DW 0 ; Keeps track of amount of error in timer.
- UserTicks DD 0 ; Tick count of timer.
- UserRate DD 0 ; Desired rate of timer.
- UserError DD 0 ; Amount of error in clock rate for desired frequency.
- UserCurRate DW 0 ; Keeps track of when to increment timer.
- UserCurError DW 0 ; Keeps track of amount of error in timer.
- DosAdder DW 0 ; amount to add to DosFraction each interrupt.
- DosFraction DW 0 ; Call dos when overflowed.
- OldRMI DD 0 ; The origianl RM interrupt seg:off.
- OldPMIOffset DD 0 ; The origianl PM interrupt offset
- OldPMISelector DD 0 ; The original PM interrupt segment.
- CodeOffset DW RM_Timer_Interrupt_Handler ; Offset of the code in the RM stuff.
- CallRMIntOffset DW Call_Interrupt_Chain ; Offset of function to call DOS timer interrupt.
- CallRMIntAddr DD 0 ; PM address of CallRealIntOffset for speed.
- PMIssuedInt DD 0 ; PM signals RM to just call Int chain.
- ; These are just used for information on testing. When all is done, they can
- ; be removed, but why? The don't add too much proccessing time and can
- ; be useful.
- NumPMInts DD 0 ; Number of PM interrupts
- NumRMInts DD 0 ; Number of RM interrupts.
- ;//////////////////////////////////////////////////////////////////////////////////////
- ;///////////////////////////////////// Code ////////////////////////////////////////
- ; This is here for easy comparison with the PM version.
- MACRO INCREMENT_TIMERS
- inc [NumRMInts] ; For testing.
- ; At this point, increment the system and user timers.
- mov ax,[TrueRate] ; Get the rate of the PC clock.
- sub [SysCurRate],ax ; Sub from our rate counter.
- ja ??end_sys ; If !below zero, do not inc.
- mov bx,[WORD PTR SysRate] ; Get rate of timer.
- mov dx,[WORD PTR SysError] ; Get amount of error.
- add [SysCurRate],bx ; Add rate to the current.
- sub [SysCurError],dx ; Subtract err from error count.
- jb ??error_adj_sys ; If !below 0, increment counter.
- inc [SysTicks] ; increment the timer.
- jmp short ??end_sys ; don't modify SysCurError.
- ??error_adj_sys:
- add [SysCurError],bx ; reajust the error by timer rate.
- ??end_sys:
- sub [UserCurRate],ax ; Sub from our rate counter.
- ja ??end_user ; If !below zero, do not inc.
- mov bx,[WORD PTR UserRate] ; Get rate of timer.
- mov dx,[WORD PTR UserError] ; Get amount of error.
- add [UserCurRate],bx ; Add rate to the current.
- sub [UserCurError],dx ; Subtract err from error count.
- jb ??error_adj_user ; If !below 0, increment counter.
- inc [UserTicks] ; increment the timer.
- jmp short ??end_user ; don't modify UserCurError.
- ??error_adj_user:
- add [UserCurError],bx ; reajust the error by timer rate.
- ??end_user:
- ENDM
- ;**************************************************************************
- ;* RM_INTERRUPT_HANDLER -- Called when processor interrupted in real mode. *
- ;* *
- ;* *
- ;* INPUT: *
- ;* *
- ;* OUTPUT: *
- ;* *
- ;* WARNINGS: *
- ;* *
- ;* HISTORY: *
- ;* 07/08/1994 SKB : Created. *
- ;*=========================================================================*
- label RM_Timer_Interrupt_Handler
- start_RM_Timer_Interrupt_Handler:
- push ax
- push bx
- push dx
- push ds
- mov ax,cs ; Set data segment to code segment
- mov ds,ax ; since data is in code seg.
- cmp [WORD PTR PMIssuedInt],0; Check to see if PM made Int call.
- mov [WORD PTR PMIssuedInt],0; Make it false.
- jne ??call_int_chain ; if so, just call Int Chain.
- INCREMENT_TIMERS
- ; Now check to see if we should call the old timer handler.
- mov ax,[DosAdder] ; Get amount to add each tick.
- add [DosFraction],ax ; add it to the fraction.
- jnc ??no_int_chain ; Skip call if no overflow.
- ??call_int_chain:
- pushf ; Push flags for interrupt call.
- call [OldRMI] ; chain the call.
- ??no_int_chain:
- sti
- mov al,CLEARISR ; value to clear In Service Register
- mov dx,INTCHIP0
- out dx,al ; 8259 interrupt chip controller 0
- exit1:
- pop ds
- pop dx
- pop bx
- pop ax
- iret
- ;**************************************************************************
- ;* CALL_INTERRUPT_CHAIN -- Function PM calls to call the RM interrupt chain*
- ;* *
- ;* *
- ;* INPUT: *
- ;* *
- ;* OUTPUT: *
- ;* *
- ;* WARNINGS: *
- ;* *
- ;* HISTORY: *
- ;* 07/08/1994 SKB : Created. *
- ;*=========================================================================*
- Call_Interrupt_Chain:
- pushf
- call [OldRMI] ;
- retf
- STACK ; Don't really need this
- END
- IF 0
- ; mono print stuff.
- pushf
- push ax
- push di
- push es
- mov ax,0B000h ; ES:DI = Mono RAM address.
- mov es,ax
-
- mov al,'A'
- mov ah,2
- and di,63
- stosw
- pop es
- pop di
- pop ax
- popf
- ENDIF
|