sys7.1-doc-wip/Internal/Asm/PatchMacros.a
2019-07-27 22:37:48 +08:00

1131 lines
32 KiB
Plaintext
Raw 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: PatchMacros.a
;
; Contains: macros for patching
;
; Written by: Ed KeyCaps
;
; Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <15> 4/10/92 SAH Fixed the leaFar macro for non 68000 machines by having it do
; the same thing for all machines.
; <14> 10/28/91 SAM/KSM Clean up header.
; <12> 1/30/91 gbm sab, #38: Change the already including this file variable to
; all uppercase (for security reasons)
; <11> 1/25/91 stb JDR: remove betaStage and finalStage
; <10> 11/9/90 dba <JSM> add macros for protected come-from patches
; <9> 7/11/90 gbm stop using temp as a weapon
; <8> 5/2/90 BBM change default freespace for 6.0 compatibility.
; <6> 4/11/90 dba change so MakeSysFree is no longer used under 7.0
; <5> 2/26/90 EMT Added LeaTrap.
; <4> 1/31/90 csd Added the required $ to the hex constant. (What do you expect
; for 5:11 am?)
; <3> 1/31/90 csd In MakeSysFree, mask off the low bit of the amount of space
; requested so that the MacPlus wont address error in SetAppBase.
; <2> 12/20/89 dba use betaStage and finalStage instead of Beta and Final
; <3.1> 11/27/89 dvb Fixed DcBind, and added DcROM
; <3.0> 8/29/89 EMT Added ACTR in FixRomAddresses to allow for more looping. Removed
; references to SPLINE_FONT per Sampo and Charlton.
; <2.9> 8/29/89 dba added OSTrapReturnAddressDepth equate
; <2.8> 8/15/89 dba NEEDED FOR 6.0.4: added leaFar, jmpFar, jsrFar, setTrapA0,
; getTrapA0, setTrap, setTrapFar, getTrap, getTrapFar,
; stuffOldTrap, and stuffOldTrapFar macros and made InstToolTp,
; InstOSTp, PatchOSJump, and PatchToolJump macros use them;
; changed leaROM so that destination can be non-address register
; <2.7> 8/7/89 EMT Per PKE, force SEEK_ALLOWED to be false on all final builds FOR
; 6.0.4.
; <2.6> 8/3/89 EMT Roll in some of the more urgent code review changes FOR 6.0.4:
; Added USE_MAKESYSFREE conditional in the same vein as
; SEEK_ALLOWED Fixed PtchInstall to correctly fail with SysError.
; Removed meaningless comments.
; <2.5> 8/2/89 CEL When building a beta system the seek function can not be used
; due to a conditional. The conditional warns a user - which is
; good. But a ROM may not be final which makes it impossible to
; build a system that works on those machines. The SEEK_ALLOWED
; variable was added that allows one to use the seek option if
; this flag is set. So the naive persons will be warned and the
; daring still can make systems that work on moving targets!!!
; <2.4> 6/28/89 EMT Only use MakeSysFree stuff for spline fonts. Otherwise, use 1.0
; version with 32-bit clean fixes (1.9, 2.2)
; <2.3> 6/12/89 EMT Cleaned up source code including 2.2 fixes.
; <2.2> 6/12/89 BAL Fixed bugs in 1.9 which caused the system heap to be huge and
; init31 to fail.
; <2.1> 6/10/89 CEL Took out old Macro labels…
; <2.0> 6/2/89 CEL ifdefed the old labels out of patchmacs
; <1.9> 6/1/89 EMT StripAddress before executing 'ptch's.
; <1.8> 5/31/89 EMT Added DcBind macro for Dave and Earsh.
; <1.7> 5/24/89 EMT Fixed "robust" Bind macros. Thanks Carl.
; <1.6> 5/23/89 CCH Backed out BIND macros that refused to be robust. This version
; same as 1.4.
; <1.5> 5/23/89 EMT Rewrote Bind macros to be more robust.
; <1.4> 5/12/89 EMT Shortened names for Bind macros. Old ones still work. Removed
; MaxSymbols, MaxReferences, and SysDifferent.
; <•1.3> 5/3/89 CEL Added seek capability in addition to hard offset binding, and
; merged macros from each PTCH file into here, so there is only
; one source for all the macros.
; <1.2> 4/12/89 EMT 'HardwareEqu.a' doesn't work due to scope, removed ROMStart
; reference.
; <1.1> 4/12/89 EMT Included 'HardwareEqu.a' for ROMStart equate.
; <1.0> 4/7/89 EMT New today.
;
IF &TYPE('__INCLUDINGPATCHMACROS__') = 'UNDEFINED' THEN
__INCLUDINGPATCHMACROS__ SET 1
IF &TYPE('__INCLUDINGFSEQU__') = 'UNDEFINED' THEN
INCLUDE 'FSEqu.a'
ENDIF
; conditionals for this file
IF (&TYPE('SEEK_ALLOWED') = 'UNDEFINED') OR (StageInt = finalStage) THEN
SEEK_ALLOWED: EQU (StageInt < betaStage)
ENDIF
IF (&TYPE('USE_MAKESYSFREE') = 'UNDEFINED') THEN
USE_MAKESYSFREE: EQU 0
ENDIF
; ROM versions
MacPlus EQU $0075
MacSE EQU $0276
MacII EQU $0178
Esprit EQU $037A
Aurora EQU $067C
; useful equates for patching
OSTrapReturnAddressDepth equ $1C
;
; MACRO leaFar &label,&register
;
; This does an LEA that can reach farther than 32K.
;
; <SAH> Removed check for Machine other than 68000 as the macro generated
; a normal pc relative with 16 bit offset lea for these machines. All
; machines now use the 68000 version which does a real leaFar.
MACRO
leaFar &label,&register
@local: lea (&label-@local).L,&register
lea @local(pc,&register..L),&register
ENDM
;
; MACRO jmpFar &label,&register
;
; This does an JMP that can reach farther than 32K.
;
MACRO
jmpFar &label,&scratch
IF &SETTING('MACHINE') = 'MC68000' THEN
@local: lea (&label-@local).L,&scratch
jmp @local(pc,&scratch..L)
ELSE
bra.L &label
ENDIF
ENDM
;
; MACRO jsrFar &label,&register
;
; This does an JSR that can reach farther than 32K.
;
MACRO
jsrFar &label,&scratch
IF &SETTING('MACHINE') = 'MC68000' THEN
@local: lea (&label-@local).L,&scratch
jsr @local(pc,&scratch..L)
ELSE
bsr.L &label
ENDIF
ENDM
;
; MACRO BackToTrap &JumpLabel
;
; Insert an absolute JMP instruction, initially to the ROM reset vector, to be
; patched at installation time to the previous address from the trap table.
; the &JumpLabel provided refers to the 4-byte address to be backpatched.
;
MACRO
BackToTrap &JumpLabel
EXPORT &JumpLabel
JMP (0).L
&JumpLabel EQU *-4
ENDM
;
; MACRO JsrTrap &JumpLabel
;
; Insert an absolute JSR instruction, initially to the ROM reset vector, to be
; patched at installation time to the previous address from the trap table.
; the &JumpLabel provided refers to the 4-byte address to be backpatched.
;
MACRO
JsrTrap &JumpLabel
EXPORT &JumpLabel
JSR (0).L
&JumpLabel EQU *-4
ENDM
;
; MACRO LeaTrap &JumpLabel
;
; Insert an absolute LEA instruction, initially to the ROM reset vector, to be
; patched at installation time to the previous address from the trap table.
; the &JumpLabel provided refers to the 4-byte address to be backpatched.
;
MACRO
LeaTrap &JumpLabel, &Reg
EXPORT &JumpLabel
LEA (0).L, &Reg
&JumpLabel EQU *-4
ENDM
;
; MACRO setTrapA0 &trapNumber
;
; Install the patch pointed to by A0 as trap &trapNumber.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
;
MACRO
setTrapA0 &trapNumber
LCLA &realTrapNumber
&realTrapNumber: SETA &EVAL(&trapNumber)
IF (&realTrapNumber AND $800) = 0 THEN ; it is an OS trap
&realTrapNumber: SETA &realTrapNumber AND $FF
IF &realTrapNumber < 128 THEN
moveq #&realTrapNumber,d0 ; move trap number (sometimes sign extended)
ELSE
moveq #&realTrapNumber-$100,d0 ; move trap number (sometimes sign extended)
ENDIF
_SetTrapAddress newOS
ELSE
&realTrapNumber: SETA &realTrapNumber AND $3FF
IF &realTrapNumber < 128 THEN
moveq #&realTrapNumber,d0 ; move trap number
ELSE
move.w #&realTrapNumber,d0 ; move trap number
ENDIF
_SetTrapAddress newTool
ENDIF
ENDM
;
; MACRO getTrapA0 &trapNumber
;
; Get the current address of trap &trapNumber into A0.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
;
MACRO
getTrapA0 &trapNumber
LCLA &realTrapNumber
&realTrapNumber: SETA &EVAL(&trapNumber)
IF (&realTrapNumber AND $800) = 0 THEN ; it is an OS trap
&realTrapNumber: SETA &realTrapNumber AND $FF
IF &realTrapNumber < 128 THEN
moveq #&realTrapNumber,d0 ; move trap number (sometimes sign extended)
ELSE
moveq #&realTrapNumber-$100,d0 ; move trap number (sometimes sign extended)
ENDIF
_GetTrapAddress newOS
ELSE
&realTrapNumber: SETA &realTrapNumber AND $3FF
IF &realTrapNumber < 128 THEN
moveq #&realTrapNumber,d0 ; move trap number
ELSE
move.w #&realTrapNumber,d0 ; move trap number
ENDIF
_GetTrapAddress newTool
ENDIF
ENDM
;
; MACRO setTrap &patchLabel,&trapNumber
;
; Install the patch at &patchLabel as trap &trapNumber.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
; As a special case, bypass IMPORTing absolute addresses written in hex with a leading '$'.
;
MACRO
setTrap &patchLabel,&trapNumber
IF &patchLabel[1] <> '$' THEN
IMPORT &patchLabel
ENDIF
lea &patchLabel,a0
setTrapA0 &trapNumber
ENDM
;
; MACRO setTrapFar &patchLabel,&trapNumber
;
; Install the patch at &patchLabel (which can be far away) as trap &trapNumber.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
; As a special case, bypass IMPORTing absolute addresses written in hex with a leading '$'.
;
MACRO
setTrapFar &patchLabel,&trapNumber
IF &patchLabel[1] <> '$' THEN
IMPORT &patchLabel
ENDIF
leaFar &patchLabel,a0
setTrapA0 &trapNumber
ENDM
;
; MACRO stuffOldTrap &jumpLabel,&trapNumber
;
; Stuff the current address of trap &trapNumber at &jumpLabel,
; usually the effective address of a JMP instruction terminating a patch.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
;
MACRO
stuffOldTrap &jumpLabel,&trapNumber
getTrapA0 &trapNumber
IMPORT &jumpLabel
lea &jumpLabel,a1
move.l a0,(a1)
ENDM
;
; MACRO stuffOldTrapFar &jumpLabel,&trapNumber
;
; Stuff the current address of trap &trapNumber at &jumpLabel (which can be far away),
; usually the effective address of a JMP instruction terminating a patch.
; This handles OS traps and Toolbox traps by checking the toolbox bit.
;
MACRO
stuffOldTrapFar &jumpLabel,&trapNumber
getTrapA0 &trapNumber
IMPORT &jumpLabel
leaFar &jumpLabel,a1
move.l a0,(a1)
ENDM
;
; MACRO InstOSTp &PatchLabel, &TrapNumber
;
; Install the patch at &PatchLabel as OS trap &TrapNumber. As a special case,
; bypass the IMPORTing of absolute addresses (presumably written in hex with a
; leading $) passed as &PatchLabel.
;
MACRO
InstOSTp &PatchLabel,&TrapNumber
setTrap &patchLabel,(&trapNumber AND $FF)
ENDM
;
; MACRO InstToolTp &PatchLabel, &TrapNumber
;
; Install the patch at &PatchLabel as Toolbox trap &TrapNumber. As a special case,
; bypass the IMPORTing of absolute addresses (presumably written in hex with a
; leading $) passed as &PatchLabel.
;
MACRO
InstToolTp &PatchLabel,&TrapNumber
setTrap &patchLabel,($800 OR (&trapNumber AND $3FF))
ENDM
;
; This is a macro that sets up the arguments for a vanilla Toolbox trap patch
; rom76Fix had a setfractenable with a number and not a routine
; The normal InstToolTp does not work
;
MACRO
InstToolTpNum
LCLC &trapid
&trapid SETC &Syslst[1]
IF (&trapid[1] <> '$') THEN
IMPORT &Syslst[1]
ENDIF
LEA &Syslst[1],A0
MOVE.w #&Syslst[2],D0
DC.W ($A647)
ENDM
;
; MACRO PatchOSJump &JumpLabel,&TrapNumber
;
; Stuff the current trap address of OS trap &TrapNumber into the longword at
; &JumpLabel, presumably a JMP instruction terminating a patch.
;
MACRO
PatchOSJump &JumpLabel,&TrapNumber
stuffOldTrap &jumpLabel,(&trapNumber AND $FF)
ENDM
;
; MACRO PatchToolJump &JumpLabel,&TrapNumber
;
; Stuff the current trap address of Tool trap &TrapNumber into the longword at
; &JumpLabel, presumably a JMP instruction terminating a patch.
;
MACRO
PatchToolJump &JumpLabel,&TrapNumber
stuffOldTrap &jumpLabel,($800 OR (&trapNumber AND $3FF))
ENDM
;_________________________________________________________________________________
; DcRom, JmpRom, JsrRom, PeaRom, LeaRom, CmpRA
;
; These macros are used to build a run-time symbol table for patching multiple
; ROMs.
;_________________________________________________________________________________
; A/UX Patching macros - JmpROM, JsrROM, CmpRA. <PB302>
; The ROM addresses in the instructions produced by these macros are offset by
; the actual ROM address (determined from ROMBase) at patch install time.
; Each location to be offset gets a label of the form RXXXnnn, with nnn
; being 000, 001, 002, 003, ...
; &RomFixIndex is a count of the number of locations to be fixed (and the next
; value of nnn to be used).
; The RXXXnnn labels are used to build a table of fixup locations; see FixupTbl at
; the end of this file.
;
gbla &RomFixIndex
&RomFixIndex seta 0
;
; MACRO DcRom &RomOffset <dvb>
;
; Define a longword which is a ROM address.
MACRO
DcRom &RomOffset
gbla &RomFixIndex
entry RXXX&I2S(&ROMFIXINDEX,-3)
DC.L (&RomOffset)
RXXX&I2S(&ROMFIXINDEX,-3) equ *-4
&RomFixIndex seta &RomFixIndex+1
ENDM
;
; MACRO JmpRom &RomOffset <PB302>
;
; Jump into the ROM.
MACRO
JmpRom &RomOffset
;jmp ([ROMBase],&RomOffset)
gbla &RomFixIndex
entry RXXX&I2S(&ROMFIXINDEX,-3)
jmp (&RomOffset).L ; <PB330>
RXXX&I2S(&ROMFIXINDEX,-3) equ *-4
&RomFixIndex seta &RomFixIndex+1
ENDM
;
; MACRO JsrRom &RomOffset <PB302>
;
; JSR Into the ROM
;
MACRO
JsrRom &RomOffset
gbla &RomFixIndex
entry RXXX&I2S(&ROMFIXINDEX,-3)
jsr (&RomOffset).L ; <PB330>
RXXX&I2S(&ROMFIXINDEX,-3) equ *-4
&RomFixIndex seta &RomFixIndex+1
ENDM
;
; MACRO CmpRA &RomOffset, &Effective_Address <PB302>
;
MACRO
CmpRA &RomOffset, &EffAddr
gbla &RomFixIndex
entry RXXX&I2S(&ROMFIXINDEX,-3)
RXXX&I2S(&ROMFIXINDEX,-3) equ *+2
cmp.l #&RomOffset, &EffAddr
&RomFixIndex seta &RomFixIndex+1
ENDM
;
; MACRO PeaRom &RomOffset <PB319>
;
; Pea ROM address
;
MACRO
PeaRom &RomOffset
gbla &RomFixIndex
entry RXXX&I2S(&ROMFIXINDEX,-3)
pea &RomOffset
RXXX&I2S(&ROMFIXINDEX,-3) equ *-4
&RomFixIndex seta &RomFixIndex+1
ENDM
;
; MACRO leaROM &ROMOffset,&register
;
; LEA into the ROM
;
MACRO
leaRom &ROMOffset,&register
GBLA &ROMFixIndex
ENTRY RXXX&I2S(&ROMFixIndex,-3)
IF &SUBSTR(&TYPE(&register),1,5) = 'REG A' THEN
lea &ROMOffset,&register
ELSE
move.l #&ROMOffset,&register
ENDIF
RXXX&I2S(&ROMFixIndex,-3): equ *-4
&ROMFixIndex: seta &ROMFixIndex+1
ENDM
;_________________________________________________________________________________
; RomVersions, Bind, JmpBind, JsrBind, PeaBind, LeaBind, CmpBind, DcBind, FixRomAddresses
;
; These macros are used to build a run-time symbol table for patching multiple
; ROMs.
;_________________________________________________________________________________
;
; MACRO RomVersions &RomVersion1, RomVersion2, …
;
; Identify the ROM version numbers a paticular patch file calls.
; Allocates the symbol lists.
;
MACRO
RomVersions
GBLA &NumSymbols
&NumSymbols SETA 0
GBLA &NumReferences
&NumReferences SETA 0
GBLA &NumVersions
&NumVersions SETA &NBR(&SYSLIST)
GBLC &RomVersion[&NumVersions]
LCLA &i
&i SETA 1
WHILE &i <= &NumVersions DO
&RomVersion[&i] SETC &SYSLIST[&i]
&i SETA &i + 1
ENDWHILE
ENDM
;
; MACRO &Symbol Bind (&RomVersion1, &RomOffset1), (&RomVersion2, SEEK, &TrapNum, &Pattern1, &Pattern2, …), …
;
; Binds offsets to symbols based upon their RomVersion. &RomOffset is an offset from ROMBase,
; however, if it has memory manager bits set, an absolute must be used. These are not first class
; symbols; they only have meaning when used in these macros.
;
MACRO
&Symbol Bind
GBLA &NumSymbols
&NumSymbols SETA &NumSymbols + 1
Bind_&Symbol EQU &NumSymbols
LCLA &i, &j
&i SETA 1
WHILE &i <= &NBR(&SYSLIST) DO
IF &SYSLIST[&i,2] = 'SEEK' THEN ;test for SEEK
IF SEEK_ALLOWED THEN
RomSymTab_&SYSLIST[&i,1]_&NumSymbols EQU 0
Trap_&SYSLIST[&i,1]_&NumSymbols EQU &SYSLIST[&i,3]
NumPats_&SYSLIST[&i,1]_&NumSymbols EQU &NBR(&SYSLIST[&i]) - 3
&j SETA 1
WHILE &j <= (&NBR(&SYSLIST[&i]) - 3) DO
PatTab_&SYSLIST[&i,1]_&NumSymbols._&j EQU &SYSLIST[&i,&j+3]
&j SETA &j + 1
ENDWHILE
ELSE
! Seek not permitted on beta and final software!
ENDIF ;SEEK_ALLOWED
ELSE ;Not a SEEK
RomSymTab_&SYSLIST[&i,1]_&NumSymbols EQU &SYSLIST[&i,2]
ENDIF
&i SETA &i + 1
ENDWHILE
ENDM
;
; MACRO JmpBind &Symbol
;
; JMP through a Bind symbol.
;
MACRO
JmpBind &Symbol
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences EQU *+2
JMP (Bind_&Symbol).L
ENDM
;
; MACRO JsrBind &Symbol
;
; JSR through a Bind symbol.
;
MACRO
JsrBind &Symbol
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences EQU *+2
JSR (Bind_&Symbol).L
ENDM
;
; MACRO PeaBind &Symbol
;
; PEA a Bind symbol.
;
MACRO
PeaBind &Symbol
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences EQU *+2
PEA (Bind_&Symbol).L
ENDM
;
; MACRO LeaBind &Symbol, &Reg
;
; LEA a Bind symbol into a register.
;
MACRO
LeaBind &Symbol, &Reg
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences EQU *+2
LEA (Bind_&Symbol).L, &Reg
ENDM
;
; MACRO CmpBind &Symbol, &EA
;
; CMP a Bind symbol to an effective address.
;
MACRO
CmpBind &Symbol, &EA
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences EQU *+2
CMP.L #Bind_&Symbol, &EA
ENDM
;
; MACRO DcBind &Symbol
;
; Make a constant based upon a Bind symbol
;
MACRO
DcBind &Symbol
GBLA &NumReferences
&NumReferences SETA &NumReferences + 1
ENTRY RomRefTab_&NumReferences
RomRefTab_&NumReferences
DC.L Bind_&Symbol
ENDM
;
; MACRO FixRomAddresses
;
; Fixes the references in the patch file. Should be first thing executed by
; the patch and should live in the cut-back portion of the code. Also includes
; the assembler instructions to build the tables.
;
; This macro destroys A0-A4/D0-D3.
;
; The format of the tables are as follows:
; # of Symbols (word)
; # of Rom Versions (word)
; Rom Version Table
; Rom ID (word)
; Offset to Symbol Table (word)
; 1 per Rom Version
; Symbol Table
; Offset from ROMBase (long), 0 if a SEEK (to be replaced at runtime)
; Seek Table
; Reference ID (long)
; Trap # (word)
; # of longs to search (word)
; search pattern (n longs)
; 0.L at the end of each seek table
; Reference Table
; Offset to reference (long)
; 0.L
;
; After retreiving the correct address, it may be altered as follows to ensure it
; works correctly under A/UX.
; Addressing High Byte in Instruction Action
; 24 bit NZ Do not alter the address in the instruction.
; Used with CMPRA to a ROM Resource.
; 32 bit NZ Mask out 12 high bits from the address
; in the instruction, leaving a ROM offset
; Then add in ROMBase.
; either Zero Normal Case. Add ROMBase to the address
; in the instruction.
;
MACRO
FixRomAddresses
ACTR 10000 ; Allow for lots 'o looping <3.0>
; First, find the correct symbol and seek tables for the machine.
LEA RomTableStart, A2 ; Beginning of tables in A2
MOVE.L A2, A1 ; Copy to A1
MOVE.W (A1)+, D0 ; Number of symbols in D0
ASL.W #2, D0 ; * 4 for number of bytes
MOVE.W (A1)+, D1 ; Number of versions in D1
MOVE.L ROMBase, A0 ; ROMBase in A0
MOVE.W 8(A0), D2 ; Rom version number in D2
BRA.S @VersDBRA
@NextVersion
CMP.W (A1)+, D2 ; Is this it?
BEQ.S @FoundVersion ; Yes!
ADDQ.L #2, A1 ; Nope, go to next one.
@VersDBRA DBRA D1, @NextVersion
; Damn! Didn't find it.
CLR.L ResumeProc ; disable the resume button.
MOVEQ.L #dsBadPatch, D0
_SysError
@FoundVersion
MOVE.L A0, D3 ; ROMBase in D3
MOVE.W (A1)+, D1 ; Get the symbol table offset
LEA (A2, D1.W), A1 ; Symbol table starts at A1
IF SEEK_ALLOWED THEN
LEA (A1, D0.W), A2 ; Seek table starts at A2
@NextSeek
; Use seek table to patch symbol table.
MOVE.L (A2)+, D2 ; Symbol ID in D2
ASL.L #2, D2 ; * 4 for number of bytes
BEQ.S @DoneSeek ; If 0, we're done.
MOVE.W (A2)+, D0 ; Get trap number
CMP.W #$A800, D0 ; OS or TB trap?
BLO.S @OSTrap ; < $A800 is OS - use GetTrapWordAddress when available
_GetTrapAddress newTool
BRA.S @GotTrap
@OSTrap _GetTrapAddress newOS
@GotTrap
CMP.L A0, D3 ; Make sure we're looking at ROM.
BLO.S @InROM ; If ROMBase < the address, we're cool.
_Debugger
@InROM
MOVE.W (A2)+, D4 ; Get # of longs in D4
BEQ.S @GotMatch ; If 0, we got it already!
@NextMatch
MOVE.L (A2), D0 ; Get first pattern
@FirstMatch
; Try to match the first 4 byte pattern. Assume that the pattern is word aligned,
; since SEEK is used for matching instruction sequences.
ADDQ.L #2, A0 ; Next word, please.
CMP.L (A0), D0 ; Does first pattern match?
BNE.S @FirstMatch ; Nope, look for next one.
MOVE.W D4, D0 ; Get # of longs
SUBQ.W #1, D0 ; Subtract 1 because we've found first pattern
LEA 4(A0), A3 ; A3 is ROM without first long
LEA 4(A2), A4 ; A4 is search pattern without first long
BRA.S @LongDBRA
@NextLong
CMP.L (A3)+, (A4)+ ; Same?
BNE.S @NextMatch ; No, gotta start fresh.
@LongDBRA DBRA D0, @NextLong ; Seen enough?
@GotMatch
SUB.L D3, A0 ; Turn A0 into a ROMBase offset
MOVE.L A0, -4(A1, D2.L) ; Put it in the symbol table
ASL.W #2, D4 ; Convert # of longs to bytes
LEA (A2, D4.W), A2 ; Go to next entry in seek table
BRA.S @NextSeek
@DoneSeek
ENDIF ;SEEK_ALLOWED
MOVEQ.L #-1, D0
_StripAddress ; D0 is negative with 32 bit memory manager.
LEA RefTableStart, A0 ; Reference table in A0
@NextReference
MOVE.L (A0)+, D2 ; Offset in D2
BEQ RomTableEnd ; All done.
LEA RomTableStart(PC, D2.L), A2 ; Address of code to patch in A2
MOVE.L (A2), D1 ; Symbol ID in D1
ASL.L #2, D1 ; * 4 for number of bytes
MOVE.L -4(A1, D1.L), D1 ; Offset from ROMBase in D1
CMP.L #$00FFFFFF, D1 ; High bits set?
BLS.S @AddIt ; No, normal case
TST.L D0 ; 32 bit mode?
BPL.S @CopyReference ; No, don't touch!
AND.L #$000FFFFF, D1 ; Yes, clear high 12 bits.
@AddIt
ADD.L D3, D1 ; Add in ROMBase
@CopyReference
MOVE.L D1, (A2) ; Put it in the code.
BRA.S @NextReference
; Build the table.
ALIGN 4
RomTableStart
GBLA &NumSymbols
NumSymbols DC.W &NumSymbols
GBLA &NumVersions
NumVersions DC.W &NumVersions
GBLC &RomVersion[*]
LCLA &i, &j, &k
VersTableStart
&i SETA 1
WHILE &i <= &NumVersions DO
DC.W &RomVersion[&i]
DC.W SymTableStart_&i - RomTableStart
&i SETA &i + 1
ENDWHILE
&i SETA 1
WHILE &i <= &NumVersions DO
SymTableStart_&i
&j SETA 1
WHILE &j <= &NumSymbols DO
DC.L RomSymTab_&RomVersion[&i]_&j
&j SETA &j + 1
ENDWHILE
IF SEEK_ALLOWED THEN
SeekTableStart_&i
&j SETA 1
WHILE &j <= &NumSymbols DO
PatchMacros$temp SET RomSymTab_&RomVersion[&i]_&j ; Stupid assembler!
IF PatchMacros$temp = 0 THEN
DC.L &j
DC.W Trap_&RomVersion[&i]_&j
DC.W NumPats_&RomVersion[&i]_&j
&k SETA 1
PatchMacros$temp SET NumPats_&RomVersion[&i]_&j ; Stupid assembler!
WHILE &k <= PatchMacros$temp DO
DC.L PatTab_&RomVersion[&i]_&j._&k
&k SETA &k + 1
ENDWHILE
ENDIF
&j SETA &j + 1
ENDWHILE
DC.L 0
ENDIF ;SEEK_ALLOWED
&i SETA &i + 1
ENDWHILE
RefTableStart
GBLA &NumReferences
&i SETA 1
WHILE &i <= &NumReferences DO
DC.L RomRefTab_&i - RomTableStart
&i SETA &i + 1
ENDWHILE
DC.L 0
RomTableEnd
ENDM
;_________________________________________________________________________________
; EntryTable, PtchInst
;
; These macros are used in conjunction with 'ptch' resources.
;_________________________________________________________________________________
;
; MACRO EntryTable &entryPt, &trapID
;
; Placed at the end of a 'ptch' file, this macro specifies a patch to be
; applied by the macro which reads and executed the 'ptch'.
;
Macro
EntryTable &entryPt, &trapID
If (&entryPt <> '0') Then
Import &entryPt
Import Start
DC.L &entryPt-Start
DC.W &trapID
Else
DC.L 0
EndIf
EndM
;
; MACRO PtchInst &selector
;
; Placed at the appropriate point, this macro calls the ptchInstall routine,
; which loads and executes the given 'ptch' resource.
;
Macro ; PMAB308 24Nov87 RWW
PtchInst &selector
MoveQ #&Eval(&selector),D0
Import ptchInstall
Bsr ptchInstall
EndM
;
; MACRO UsesPtchInst
;
; Placed in the cutback section of a patch, this macro includes the code
; required by the PtchInst macro.
;
Macro
UsesPtchInst
IF USE_MAKESYSFREE THEN
ptchInstall Proc Export
MinSysExtra EQU 16*1024 ; Add in Extra space for system <2.3-4april89-CEL>
SubQ #4,SP ; room for result <2.3-4april89-CEL>
Move.L #'ptch',-(SP) ; signature of loadable patch resource <2.3-4april89-CEL>
Move.W D0,-(SP) ; pass along given ID <2.3-4april89-CEL>
SF -(SP) ; just get a handle before sizing... <2.3-4april89-CEL>
_SetResLoad ; <2.3-4april89-CEL>
_GetResource ; get the resource handle <2.3-4april89-CEL>
MOVE.L (SP)+,D4 ; save the resource handle <2.3-4april89-CEL>
BEQ.S @xit ; we didn't get it, so just go on <2.3-4april89-CEL>
CLR.L -(SP) ; slot for resource size <2.3-4april89-CEL>
MOVE.L D4,-(SP) ; saved handle <2.3-4april89-CEL>
_SizeRsrc ; (SP) := patch res size <2.3-4april89-CEL>
MOVE.L (SP)+,D3 ; prime input to heap sizer <2.3-4april89-CEL>
ADD.L #MinSysExtra,D3 ; handy value <2.3-4april89-CEL>
BSR MakeSysFree ; get D3 contiguous bytes in sys heap <2.3-4april89-CEL>
ST -(SP) ; just get a handle before sizing... <2.3-4april89-CEL>
_SetResLoad ; <2.3-4april89-CEL>
MOVE.L D4,-(SP) ; saved handle <2.3-4april89-CEL>
_LoadResource ; get it in this time <2.3-4april89-CEL>
MOVE.L D4,-(SP) ; saved handle <2.3-4april89-CEL>
Move.L D4,-(SP) ; make a copy of the handle <2.3>
_DetachResource
; Uh, should we lock it down too, in case somebody goofs up?
Move.L (SP),A0 ; fetch handle (and keep copy on stack)
Move.L (A0),D0 ; point at head of resource <1.9>
_StripAddress ; strip it <1.9>
Move.L D0,-(SP) ; save it on the stack <2.3>
Move.L D0,A0 ; put it into A0 <1.9>
Jsr (A0) ; go execute init code
; on return, A0 should hold cutback address
Move.L A0,D1 ; save cutback address
Move.L A0,A1 ; and make an index copy
Move.L (SP)+,D2 ; get previously stripped pointer <2.3>
@3 Move.L (A1)+,D0 ; get address
Beq.S @1 ; if it's zero, we be done
Add.L D2,D0 ; add base to get real address
Move.L D0,A0 ; move to A0 for SetTrapAddress
Move.W (A1)+,D0 ; get trap number
Cmp.W #$A800,D0 ; OS or TB trap?
Bcs.S @2 ; < $A800 is OS
_SetTrapAddress newTool
Bra.S @3
@2 _SetTrapAddress newOS
Bra.S @3
@1 Move.L D1,D0 ; cutback address
Sub.L D2,D0 ; cutback - resource start = new size
Move.L (SP)+,A0 ; fetch handle, for the last time
_SetHandleSize
Bra.S @done ; <PMAB335>
@xit clr.l ResumeProc ; disable the resume button. <PMAB442>
MoveQ.L #dsBadPatch, D0 ; <PMAB335>
_SysError ; <PMAB335>
@done Rts ; <PMAB335>
*********************************************************************** ;<2.3-4april89-CEL>
* PROCEDURE MakeSysFree
* Guarantee a contiguous block of free space in the sys heap.
* To avoid purging everything, we use a loop based on _CompactMem.
* Growing the zone depends on whether there is a distinct appl zone,
* as is the case with Plus and SE and in which case we use the
* traditional _SetApplBase, or whether sys and appl are coincident,
* as is the case with II and in which case we just allocate a handle
* and immediately release it. In the worst case, the loop should be
* executed twice. At this early stage, we dont init the appl zone,
* just set its base. The initializations of InitApplZone are for later.
* Input:
* d3 = requested space
* Trashes:
* d0-d2/a0-a1
*********************************************************************** ;<2.3-4april89-CEL>
MakeSysFree ; new routine
move.l d3,d0 ; amount needed
_CompactMem SYS ; look for it in sys zone
sub.l d3,d0 ; gotten - needed
bge.s @loopEnd ; gotten ≥ needed --> done
andi.w #$FFFE, d0 ; make sure its even for MacPlus ;<3><4> csd
movea.l SysZone,a0 ; start of sys zone
cmpa.l ApplZone,a0 ; are they coincident?
beq.s @loopEnd ; same go to the end
movea.l SysZone,a0 ; start of sys zone
movea.l bkLim(a0),a0 ; end of sys zone
suba.l d0,a0 ; end of sys zone + (needed-gotten)
adda.w #128,a0 ; with slop
_SetApplBase ; free up more sys space
_InitApplZone ; init the Toolbox world, too
bra.s MakeSysFree ; be sure we have enough
@loopEnd
rts ; end of MakeSysFree
EndProc
ELSE ; USE_MAKESYSFREE
; ***************************************************************************
; ptchInstall - subroutine
; <PMAB308/RWW112187>
; Loads 'ptch' resource, initializes it, and installs its traps.
; 'ptch' resource is assumed to have SysHeap and Locked bits set!
;
; Entry: D0.W = rsrc ID of 'ptch' resource to load
;
; Uses: D0-D2, A0-A1
;
; ***************************************************************************
ptchInstall Proc Export
SubQ #4,SP ; room for result
Move.L #'ptch',-(SP) ; signature of loadable patch resource
Move.W D0,-(SP) ; pass along given ID
_GetResource ; just in case we want to ROM it later on
Tst.L (SP) ; handle returned?
Bnz.S @4 ; Yep, okay to continue
AddQ #4,SP ; Yank garbage off the stack
Bra.S @xit ; and depart
@4
Move.L (SP),-(SP) ; make a copy of the handle
_DetachResource
; Uh, should we lock it down too, in case somebody goofs up?
Move.L (SP),A0 ; fetch handle (and keep copy on stack)
Move.L (A0),D0 ; point at head of resource <1.9>
_StripAddress ; strip it <1.9>
Move.L D0,-(SP) ; save it on the stack <2.3>
Move.L D0,A0 ; put it into A0 <1.9>
Jsr (A0) ; go execute init code
; on return, A0 should hold cutback address
Move.L A0,D1 ; save cutback address
Move.L A0,A1 ; and make an index copy
Move.L (SP)+,D2 ; get previously stripped pointer <2.3>
@3 Move.L (A1)+,D0 ; get offset
Beq.S @1 ; if it's zero, we be done
Add.L D2,D0 ; add base to get real address
Move.L D0,A0 ; move to A0 for SetTrapAddress
Move.W (A1)+,D0 ; get trap number
Cmp.W #$A800,D0 ; OS or TB trap?
Bcs.S @2 ; < $A800 is OS
_SetTrapAddress NewTool
Bra.S @3
@2 _SetTrapAddress NewOS
Bra.S @3
@1 Move.L D1,D0 ; cutback address
Sub.L D2,D0 ; cutback - resource start = new size
Move.L (SP)+,A0 ; fetch handle, for the last time
_SetHandleSize
Bra.S @done
@xit clr.l ResumeProc ; disable the resume button.
MoveQ.L #dsBadPatch, D0
_SysError
@done Rts
EndProc
ENDIF ; USE_MAKESYSFREE
EndM
;
; MACRO protectedJmp &label,&toWhere
;
; This puts the special protection header on for the patch protector.
; See PatchProtector.a for details.
;
macro
protectedJmp &label,&toWhere
bra.s @skip
@jmp:
jmp (&toWhere).L
@skip:
&label: equ @jmp
endm
;
; MACRO protectedJmpBind &label,&toWhere
;
; This puts the special protection header on for the patch protector.
; See PatchProtector.a for details.
;
macro
protectedJmpBind &label,&toWhere
bra.s @skip
@jmp:
jmpBind &toWhere
@skip:
&label: equ @jmp
endm
;
; MACRO protectedJmpROM &label,&toWhere
;
; This puts the special protection header on for the patch protector.
; See PatchProtector.a for details.
;
macro
protectedJmpROM &label,&toWhere
bra.s @skip
@jmp:
jmpROM &toWhere
@skip:
&label: equ @jmp
endm
ENDIF ; ...already included