mac-rom/Internal/Asm/PatchMacros.a

1131 lines
32 KiB
Plaintext
Raw Permalink Normal View History

;
; File: PatchMacros.a
;
; Contains: macros for patching
;
; Written by: Ed KeyCaps
;
; Copyright: <09> 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 <20>already including this file<6C> 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 won<6F>t 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<6C>
; <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.
; <<3C>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, <20>
;
; 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, <20>), <20>
;
; 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 don<6F>t 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 <20> needed --> done
andi.w #$FFFE, d0 ; make sure it<69>s 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