mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-22 19:31:02 +00:00
267 lines
11 KiB
Plaintext
267 lines
11 KiB
Plaintext
;
|
|
; File: TimeMgrPatch.a
|
|
;
|
|
; Contains: code to patch in a new version of the Time Mgr. for various machines
|
|
;
|
|
; Written by: Darin Adler
|
|
;
|
|
; Copyright: © 1990-1992 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <4> 2/12/92 JSM Moved this file to TimeMgr folder, keeping all the old
|
|
; revisions.
|
|
; <3> 9/9/91 JSM Cleanup header.
|
|
; <2> 12/8/90 dba <gbm> turn off Time Mgr. patches for A/UX
|
|
; <1> 9/22/90 dba Created today. Contains a complete patch of TimeMgr for Plus,
|
|
; SE, and II ROMs, and a patch for the Portable and IIci ROMs that
|
|
; adds the _Microseconds trap.
|
|
;
|
|
|
|
load 'StandardEqu.d'
|
|
include 'HardwarePrivateEqu.a'
|
|
include 'LinkedPatchMacros.a'
|
|
|
|
AfterFreezeTimeInRmvTime ROMBind (Portable,$5EC8),(IIci,$AE96)
|
|
MultAndMerge ROMBind (Portable,$5F34),(IIci,$AF02)
|
|
AfterFreezeTimeInPrimeTime ROMBind (Portable,$5F9A),(IIci,$AF3E)
|
|
AfterFreezeTimeInTimer2Int ROMBind (Portable,$6090),(IIci,$B02E)
|
|
|
|
OldTimeMgrGlobalsSize equ 16
|
|
|
|
; globals in system heap (same RECORD in TimeMgr.a; move it to an equate file if you like)
|
|
|
|
TimeMgrPrivate record 0,increment ; time manager private storage
|
|
ActivePtr ds.l 1 ; pointer to soonest active request
|
|
TimerAdjust ds.b 1 ; number of VIA ticks used loading timer
|
|
TimerLowSave ds.b 1 ; low byte of VIA timer from last FreezeTime <4>
|
|
RetryAdjust ds.w 1 ; number of via ticks for underflow retry
|
|
CurrentTime ds.l 1 ; number of virtual ticks since boot
|
|
BackLog ds.l 1 ; number of virtual ticks of ready tasks
|
|
**** NOTE: The ordering of the following 4 fields must not change (FreezeTime Depends on it) <4>
|
|
HighUSecs ds.l 1 ; high 32 bits of microsecond count <4>
|
|
LowUSecs ds.l 1 ; low 32 bits of microsecond count <4>
|
|
FractUSecs ds.w 1 ; 16 bit fractional microsecond count <4>
|
|
CurTimeThresh ds.w 1 ; CurrentTime threshold for updating µsec count <4>
|
|
**** end of order dependent fields <4>
|
|
PrivateSize equ *-TimeMgrPrivate ; size of this record
|
|
endr
|
|
|
|
TITLE 'Time Manager - Equates'
|
|
|
|
TaskActiveBit equ 7 ; high bit of QType word is active flag
|
|
ExtendedTmTaskBit equ 6 ; indicates an extended TmTask record
|
|
T2IntBit equ 5 ; VIER/VIFR bit num for VIA Timer 2
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Representations of time in the Time Manager.
|
|
;
|
|
; Time is represented externally in two ways, both are stored in a longword,
|
|
; if the value is positive, it represents milliseconds, and if it is
|
|
; negative, it represents negated microseconds. This representation is used
|
|
; as the delay time input to PrimeTime, and as the unused remaining time
|
|
; output by RmvTime.
|
|
;
|
|
; The VIA1 Timer2 is the 16 bit hardware timer used by the time manager.
|
|
; On all current machines, it decrements at a rate of 783360 Hz, and
|
|
; generates an interrupt, and keeps counting, when it counts through zero.
|
|
; This provides resolution of 1.276 µsec, and a range of 83.660 msec.
|
|
;
|
|
; Internally the time manager represents time as a virtual unsigned 36 bit
|
|
; VIA timer, which gives a range of about 1 day. However, since we only
|
|
; have 32 bits to store time in, we drop the low 4 bits of the timer,
|
|
; which reduces the resolution by a factor of 16 to 20.425 µsec.
|
|
;
|
|
; Converting between the external and internal forms of time is done by
|
|
; multiplying by the proper fixed point constants, and shifting the binary
|
|
; point of the 64 bit result to get just the integer portion of the result.
|
|
; The computation of the 32 bit conversion constants requires 64 bit
|
|
; intermediate results, and unfortunatly the assembler only provides 32
|
|
; bit expression evaluation, so the proper constants were computed with
|
|
; a 64 bit hex caculator, and hard coded here (yuck!). These are not
|
|
; "Magic Numbers", the formula for computing them is provided, so that
|
|
; they may be re-computed if any of the parameters ever change.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
TicksPerSec equ 783360 ; VIA Timer clock rate
|
|
TickScale equ 4 ; Internal time is VIA ticks >> TickScale
|
|
|
|
MsToIntFractBits equ 26 ; number of fraction bits in 64 bit result
|
|
*MsToInternal equ ((TicksPerSec<<(MsToIntFractBits-TickScale))\
|
|
+999)/1000
|
|
MsToInternal equ $C3D70A3E ; msec to internal time multiplier
|
|
|
|
UsToIntFractBits equ 32 ; number of fraction bits in 64 bit result
|
|
*UsToInternal equ ((TicksPerSec<<(UsToIntFractBits-TickScale))\
|
|
+999999)/1000000
|
|
UsToInternal equ $0C88A47F ; µsec to internal time multiplier
|
|
|
|
IntToMsFractBits equ 32 ; number of fraction bits in 64 bit result
|
|
*InternalToMs equ ((1000<<(IntToMsFractBits+TickScale))\
|
|
+TicksPerSec-1)/TicksPerSec
|
|
InternalToMs equ $053A8FE6 ; internal time to msec multiplier
|
|
|
|
IntToUsFractBits equ 27 ; number of fraction bits in 64 bit result
|
|
*InternalToUs equ ((1000000<<(IntToUsFractBits+TickScale))\
|
|
+TicksPerSec-1)/TicksPerSec
|
|
InternalToUs equ $A36610BC ; internal time to µsec multiplier
|
|
|
|
|
|
macro ; Macro for interfacing with the MultAndMerge routine.
|
|
Convert &Multiplier,&FractionBits
|
|
jsrROM MultAndMerge ; input/output is D0
|
|
dc.l &Multiplier ; conversion multiplier
|
|
if &eval(&FractionBits)=32 then
|
|
dc.l 0 ; merge mask (low 32 bits all fraction)
|
|
else
|
|
dc.l -1<<&FractionBits ; merge mask (some low bits not fraction)
|
|
rol.l #32-&FractionBits,d0 ; position result after merge
|
|
endif
|
|
endm
|
|
|
|
;————————————————————————————————————————————————————————————————————————————————————————————————————
|
|
|
|
GetRidOfPowerMgrInFreezeTime InstallProc (Plus,SE,II,IIci,notAUX)
|
|
|
|
import PoundThreeNOPsHereIfNoPowerMgr
|
|
|
|
lea PoundThreeNOPsHereIfNoPowerMgr,a0
|
|
move.w #$4E71,d0 ; get the NOP opcode
|
|
move.w d0,(a0)+ ; NOP
|
|
move.w d0,(a0)+ ; NOP
|
|
move.w d0,(a0)+ ; NOP
|
|
|
|
rts
|
|
|
|
EndProc
|
|
|
|
InstallTimeMgrPlusSEII InstallProc (Plus,SE,II,notAUX)
|
|
|
|
import InitTimeMgr
|
|
|
|
move.w sr,-(sp) ; save interrupt level
|
|
ori.w #$0700,sr ; no interrupts while swapping Time Mgrs
|
|
|
|
leaResident __InsTime,a0
|
|
moveq #$58,d0 ; _InsTime
|
|
_SetTrapAddress newOS
|
|
|
|
leaResident __RmvTime,a0
|
|
moveq #$59,d0 ; _RmvTime
|
|
_SetTrapAddress newOS
|
|
|
|
leaResident __PrimeTime,a0
|
|
moveq #$5A,d0 ; _PrimeTime
|
|
_SetTrapAddress newOS
|
|
|
|
leaResident __Microseconds,a0
|
|
moveq #$93-$100,d0 ; SetTrapAddress(os) only looks at the low byte
|
|
_SetTrapAddress newOS
|
|
|
|
movea.l TimeVars,a0 ; get pointer to time manager globals
|
|
movea.l MSQueue+qHead(a0),a1 ; save header of queue
|
|
_DisposPtr ; dispose the old globals
|
|
jsr InitTimeMgr ; initialize the new TimeMgr (trashes no registers)
|
|
@loop
|
|
move.l a1,d0 ; test for end of list
|
|
beq.s @done ; exit when queue empty
|
|
move.l a1,a0 ; setup a0 for _PrimeTIme
|
|
move.l qLink(a0),a1 ; remember queue successor
|
|
move.l tmCount(a0),d1 ; save time remaining for _PrimeTime
|
|
_InsTime ; re-install the time manager task
|
|
move.l d1,d0 ; pass time remaining to _PrimeTime
|
|
beq.s @loop ; if not running, don't prime it
|
|
_PrimeTime ; restart the timer with new time mgr
|
|
bra.s @loop ; loop through entire queue
|
|
@done
|
|
move.w (sp)+,sr ; restore interrupt level
|
|
rts
|
|
|
|
EndProc
|
|
|
|
InstallTimeMgrPortableIIci InstallProc (Portable,IIci,notAUX)
|
|
|
|
move.w sr,-(sp) ; save interrupt level
|
|
ori.w #$0700,sr ; no interrupts while swapping Time Mgrs
|
|
|
|
leaResident RmvTimeNewFreezeTime,a0
|
|
moveq #$59,d0 ; _RmvTime
|
|
_SetTrapAddress newOS
|
|
|
|
leaResident PrimeTimeNewFreezeTime,a0
|
|
moveq #$5A,d0 ; _PrimeTime
|
|
_SetTrapAddress newOS
|
|
|
|
leaResident Timer2IntNewFreezeTime,a0
|
|
move.l a0,Lvl1DT+(T2IntBit*4) ; put into interrupt table
|
|
|
|
leaResident __Microseconds,a0
|
|
moveq #$93-$100,d0 ; SetTrapAddress(os) only looks at the low byte
|
|
_SetTrapAddress newOS
|
|
|
|
moveq #TimeMgrPrivate.PrivateSize,d0
|
|
_NewPtr sys,clear ; allocate and clear the structure
|
|
move.l a0,a1 ; keep the pointer for reference
|
|
move.l TimeVars,a0 ; get the old globals
|
|
moveq #OldTimeMgrGlobalsSize,d0
|
|
_BlockMove ; copy over the ones we care about
|
|
_DisposPtr ; get rid of the old globals
|
|
move.l a1,TimeVars ; point to the new globals
|
|
|
|
move.w (sp)+,sr ; restore interrupt level
|
|
rts
|
|
|
|
EndProc
|
|
|
|
;————————————————————————————————————————————————————————————————————————————————————————————————————
|
|
; patch to RmvTime that calls our copy of FreezeTime, and then rejoins the ROM
|
|
|
|
RmvTimeNewFreezeTime proc export
|
|
|
|
import FreezeTime
|
|
|
|
move.l d3,-(sp) ; save d3 also
|
|
jsr FreezeTime ; setup to manipulate time queue
|
|
jmpROM AfterFreezeTimeInRmvTime ; rejoin the ROM
|
|
|
|
endproc
|
|
|
|
;————————————————————————————————————————————————————————————————————————————————————————————————————
|
|
; patch to PrimeTime that calls our copy of FreezeTime, and then rejoins the ROM
|
|
|
|
PrimeTimeNewFreezeTime proc export
|
|
|
|
import FreezeTime
|
|
|
|
move.l d3,-(sp) ; save d3 also
|
|
|
|
tst.l d0 ; see if +msec or -µsec
|
|
bpl.s @msec ; µsec are negated, msec pos
|
|
|
|
@usec neg.l d0 ; get positive number of µsecs
|
|
convert UsToInternal,UsToIntFractBits ; convert µsec to internal
|
|
bra.s @ConvertDone ; join common code
|
|
|
|
@msec convert MsToInternal,MsToIntFractBits ; convert msec to internal
|
|
@ConvertDone
|
|
jsr FreezeTime ; setup to manipulate time queue
|
|
jmpROM AfterFreezeTimeInPrimeTime ; rejoin the ROM
|
|
|
|
endproc
|
|
|
|
;————————————————————————————————————————————————————————————————————————————————————————————————————
|
|
; patch to Timer2Int that calls our copy of Timer2Int, and then rejoins the ROM
|
|
|
|
Timer2IntNewFreezeTime proc export
|
|
|
|
import FreezeTime
|
|
|
|
jsr FreezeTime ; stop the timer, adjust time remaining
|
|
jmpROM AfterFreezeTimeInTimer2Int ; rejoin the ROM
|
|
|
|
;————————————————————————————————————————————————————————————————————————————————————————————————————
|
|
|
|
End
|