supermario/base/SuperMarioProj.1994-02-09/LinkedPatches/PatchProtector.a
2019-06-29 23:17:50 +08:00

192 lines
6.9 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; File: PatchProtector.a
;
; Contains: a patch to SetTrapAddress and GetTrapAddress that “protects” come-from patches
;
; Written by: Darin Adler
;
; Copyright: © 1990-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <11> 8/28/91 JSM Cleanup header.
; <10> 4/5/91 gbm dba: Exit via jCacheFlush when setting the trap address. This
; makes it possible to use copy-back mode on '040's
; <9> 4/3/91 dba kill the fun
; <8> 3/25/91 dba VL: get rid of that stupid StripAddress
; <7> 3/4/91 dba gbm: do a StripAddress for all the 24-bit slobs out there
; <6> 12/18/90 gbm (dba) Use the noPatchProtector conditional to prevent two patch
; protectors from getting upset at each other.
; <5> 12/5/90 dba <gbm> disallow come-from patch headers except from people who
; use the $CXXX form of SetTrapAddress; also check the address
; passed to SetTrapAddress for validity, by reading the first long
; word and looking for the come-from header
; <4> 8/2/90 dba get rid of the MemTop and odd checks
; <3> 5/30/90 dba add validation for the old address in GetTrapAddress
; <2> 5/1/90 dba do nothing to this file, just touch it so that people will get
; the LinkedPatchLib rebuilt
; <1> 3/21/90 dba fixed some more bugs and checked in for general use
; 2/1/90 dba fixed the bug that Ed found
; 1/30/90 dba revamped, added [GS]etTrapWordAddress
; 1/25/90 dba added a header
;
; To Do:
; take into account the number of toolbox traps on each machine in [GS]etTrapWordAddress
;
; This is a patch to Get/SetTrapAddress that respects come-from patches with a special format.
;
; bra.s *+6
; jmp OldTrapAddress
;
; Get and SetTrapAddress will notice patches that begin with this sequence and treat them as
; “come-from” patches. Instead of changing the address of the trap in the trap table, instead
; they will change the “old” address in the last come-from patch in the chain.
;
; This patch needs to be installed before any come-from patches are installed. This can be done
; by linking it first in the first 'lpch' to be loaded.
;
; This patch also implements a new variant of [GS]etTrapAddress called [GS]etTrapWordAddress.
; It takes a whole trap word, and does the right thing, removing the need for N[GS]etTrapAddress.
;
print push,off
load 'StandardEqu.d'
include 'LinkedPatchMacros.a'
print pop
; opcodes
kBranchOverJMPLOpcode equ $6006
kJMPLOpcode equ $4EF9
kComeFromHeader equ (kBranchOverJMPLOpcode << 16) + kJMPLOpcode
; bits in trap numbers and Set/GetTrapAddress opcodes
TrapNumber record 0
toolboxBit equ 11
endr
TrapAddressOpcode record 0
newBit equ 9
toolboxBit equ 10
endr
; The following patch has to use $A046 as the trap number instead of _GetTrapAddress.
; This is because it is installed before these patches modify the behavior of [GS]etTrapAddress
; to work properly for full trap words. The trap number is thus used as an “old-style” trap number.
; $A046 is GetTrapAddress, but $A146 (the value of _GetTrapAddress) is interpreted as $A946.
ProtectGetTrap patchproc $A046,(Plus,SE,II,Portable,IIci,noPatchProtector)
import TrapAddressBits
export OldGetTrapAddress
jsr TrapAddressBits ; set bits in the trap word
move sr,-(sp) ; would do a MOVE CCR, but it is not available on 68000
bsr.s OldGetTrapAddress ; call the old GetTrapAddress
move (sp)+,ccr ; get condition codes back
bcs.s @done ; come-from patches bypass our trickery
@next
cmp.l #kComeFromHeader,(a0) ; does this have the come-from header?
bne.s @done ; no we are done
move.l 4(a0),a0 ; go on to the next
bra.s @next
@done
moveq #0,d0 ; must zero the result code again
rts
OldGetTrapAddress
jmpOld
endproc
; Since SetTrapAddress looks at the first long word of the previous value of the traps address,
; it can be dangerous to call SetTrapAddress on some random value. Later, a correct SetTrapAddress
; might encounter a bus error or address error or some other problem. To avoid this, SetTrapAddress
; looks at the first long word of the new trap address *before* setting the address in the trap table
; or come-from chain. This ensures that the bus error will happen right away.
ProtectSetTrap patchproc _SetTrapAddress,(Plus,SE,II,Portable,IIci,noPatchProtector)
import TrapAddressBits
import OldGetTrapAddress
move.l (a0),d2 ; get header of trap, and check for bus errors <5>
jsr TrapAddressBits ; set bits in the trap word
bcs.s OldSetTrapAddress ; come-from patches bypass our trickery
cmp.l #kComeFromHeader,d2 ; headers can only be used on come-from patches <5>
beq.s @illegalHeader ; saw a header, so I must system error <5>
movem.l d0-d1/a0,-(sp) ; save trap address, number, and bits
jsr OldGetTrapAddress ; call the old GetTrapAddress
move.l #0,a1 ; no come-froms found yet
@next
cmp.l #kComeFromHeader,(a0)+ ; does this have the come-from header?
bne.s @done ; no we are done
move.l a0,a1 ; remember this address
move.l (a0),a0 ; go on to the next
bra.s @next
@done
movem.l (sp)+,d0-d1/a0 ; restore trap address, number, and bits
cmp.l #0,a1 ; any come-froms found?
beq.s OldSetTrapAddress ; no, go do the real SetTrapAddress
move.l a0,(a1) ; set the trap address
move.l jCacheFlush,-(sp) ; get the cache flush vector <9>
rts ; call it, and then return to the trap dispatcher <9>
@illegalHeader
move.w #dsBadPatchHeader,d0 ; get error code <5>
_SysError ; report it to the unsuspecting user <5>
OldSetTrapAddress
jsrOld ; call so we can flush the cache when we return <9>
move.l jCacheFlush,-(sp) ; get the cache flush vector <9>
rts ; call it, and then return to the trap dispatcher <9>
endproc
TrapAddressBits proc
; TrapAddressBits
;
; In:
; d0.w trap number
; d1.w [GS]etTrapAddress trap word
;
; Out:
; d1.w (modified) [GS]etTrapAddress trap word
; ccr CC if it is not a come-from, CS if it is a come-from
btst #TrapAddressOpcode.newBit,d1 ; is this N[GS]etTrapAddress?
bnz.s @notFullWord ; yes, dont handle it
btst #TrapAddressOpcode.toolboxBit,d1 ; is this normal [GS]etTrapAddress?
bz.s @notFullWord ; yes, dont handle it
@fullWord
; adjust the trap bits
bset #TrapAddressOpcode.newBit,d1 ; is this NGetTrapAddress?
btst #TrapNumber.toolboxBit,d0 ; is the trap a Toolbox trap?
bnz.s @toolbox ; yes, leave the bit set
bclr #TrapAddressOpcode.toolboxBit,d1 ; clear bit for OS
@toolbox
cmp.w #$C000,d0 ; is this a come-from trap word?
blo.s @notComeFrom ; no, it is not
cmp.w #$D000,d0 ; is it a come-from trap word?
bhs.s @notComeFrom ; no, it is not
@comeFrom
; oooh... carry is set for us, we can return
rts
@notFullWord
@notComeFrom
and #$FE,ccr ; clear the carry bit
rts
endproc
end