; ; 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 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’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… ; <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,®ister ; ; This does an LEA that can reach farther than 32K. ; ; 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,®ister @local: lea (&label-@local).L,®ister lea @local(pc,®ister..L),®ister ENDM ; ; MACRO jmpFar &label,®ister ; ; 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,®ister ; ; 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. ; 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 ; ; 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 ; ; Jump into the ROM. MACRO JmpRom &RomOffset ;jmp ([ROMBase],&RomOffset) gbla &RomFixIndex entry RXXX&I2S(&ROMFIXINDEX,-3) jmp (&RomOffset).L ; RXXX&I2S(&ROMFIXINDEX,-3) equ *-4 &RomFixIndex seta &RomFixIndex+1 ENDM ; ; MACRO JsrRom &RomOffset ; ; JSR Into the ROM ; MACRO JsrRom &RomOffset gbla &RomFixIndex entry RXXX&I2S(&ROMFIXINDEX,-3) jsr (&RomOffset).L ; RXXX&I2S(&ROMFIXINDEX,-3) equ *-4 &RomFixIndex seta &RomFixIndex+1 ENDM ; ; MACRO CmpRA &RomOffset, &Effective_Address ; 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 ; ; 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,®ister ; ; LEA into the ROM ; MACRO leaRom &ROMOffset,®ister GBLA &ROMFixIndex ENTRY RXXX&I2S(&ROMFixIndex,-3) IF &SUBSTR(&TYPE(®ister),1,5) = 'REG A' THEN lea &ROMOffset,®ister ELSE move.l #&ROMOffset,®ister 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 ; @xit clr.l ResumeProc ; disable the resume button. MoveQ.L #dsBadPatch, D0 ; _SysError ; @done Rts ; *********************************************************************** ;<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’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 ≥ needed --> done andi.w #$FFFE, d0 ; make sure it’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 ; ; 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