; ; File: CheckDevicesINIT.a ; ; Contains: 7 patches for Color QuickDraw (mostly video driver related) ; ; Written by: Dave Fung/Mike Puckett ; ; Copyright: © 1989-1993 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 09-23-93 jmp Quit doing below when the Display Manager is around. ; 9/1/93 SKH Fixed a bug with fixed CLUT devices (ie: DBLite). SetEntries can not be called for ; direct or fixed devices ; 04-07-93 jmp Cleaned up the invalid 'scrn' resource code so that it actually ; removes the invalid 'scrn' resource. This makes family modes ; work better. However, this is really only a stop-gap measure ; for now. ; 11-05-92 jmp Changed the TPD, FPD, and HR video driver patch mechanism so ; that it now runs correctly from ROM (it was originally written ; to work in RAM). ; 10/28/92 SWC Changed SlotEqu.a->Slots.a and VideoEqu.a->Video.a. ; 10/28/92 PN # 1045532 Call QDSecondaryInit from the BootCode3.a to set up ; the color and gdevice environment also fix up the code to run ; from ROM and check for SuperMario ROM ID. Mike Puckett will come ; back to this file and clean it up (he promised !) Also, take out ; the system INIT stuff and the 950 patch. ; 10/27/92 CSS Changed a short branch to a word branch. ; 7/16/92 CSS Update from Reality: ; <27> 7/13/92 DTY #1035553 : The Quadra950VideoPatch assumes that the driver ; is RAM based, thus it treats the dCtlDriver field as a handle. ; Under A/UX, the video driver is a ROM based driver, and is a ; pointer. Add a check to see whether the driver is RAM based or ; ROM based before doing an extra dereference. ; <26> 05-20-92 jmp Moved the ÒPatchQuadra950DriverÓ code from VideoPatch.a to this ; file so that the patch would work both when the Quadra 950 ; built-in video is the main device and when it is secondary. ; <2> 2/13/92 PN Add forRom conditionals. ; <1> ¥ Pre-SuperMario comments follow ¥ ; <25> 8/23/91 JSM Remove benign redefinition of TRUE, which is now defined by the ; build script. ; <24> 3/7/91 DC dba, #83785: attach the VBL to the main screen after moving ; cursor there ; <23> 11/7/90 jmp Fixed a bug that I introduced iton SixPack where 'gama' tables ; pointed to by the 'scrn' resource were not being loaded. ; <22> 7/11/90 gbm define true (this was the only file that used it when it was in ; StandardEqu.d) ; <21> 7/10/90 jmp Added another item to the ÒTo DoÓ list below. NO CODE CHANGES ; WERE MADE. ; <20> 7/10/90 DDG NEEDED FOR SIXPACK: Fixed bug in setting gamma entries ; (SetDevGamma) where the csParam was being setup as if it was a ; word instead of what it really is: a long. Also fixed duplicate ; comment for change 19. ; <19> 7/4/90 jmp Cleaned up and corrected MY previous inequities (and itÕs about ; time, too). ¥¥¥ NEEDED FOR SIXPACK ¥¥¥ ; <18> 7/2/90 jmp Move of the same -- rolling out my changes to fix the build. ; <17> 7/2/90 jmp Put things back to the way they were because I was breaking ; everybody (IÕll hang my head in shame). ; <16> 7/2/90 jmp Took out <15> changes due to breaking build -- will put back in ; later. ; <15> 7/2/90 jmp Moved the NoScrn routine to CheckDeviceINIT.c in preparation for ; $067C machine fix. ; <14> 6/29/90 jmp Various small fixes, plus added some (badly needed) comments. ; <13> 6/28/90 DTY Removed extra dereference on A2 when no 'scrn' resource is ; around, which caused Bus Error on startup. (OopsÉ I [jmp] left some ; bad parts of an attempted optimization in.) ; <12> 6/27/90 jmp Fixed a problem where systems that do not have a 'scrn' resource ; start out dark and then become light on the first SetGamma ; and/or SetEntries call. ¥¥¥ NEEDED FOR SIXPACK ¥¥¥ ; <11> 5/1/90 DDG Changed a comment that indicated some permanent code was ; temporary. (no code change) ; <10> 4/24/90 dba make the cursor be on the main device, not the boot device ; <9> 4/19/90 csd corrected a typa for Darin who is completely without blame in ; this matter ; <8> 4/19/90 dba change so this can be used by StartSystemPatches.a in 7.0 ; <7> 4/10/90 DF Fix the interrupt handler patching code here to ; correct illegal memory access when the driver is in ROM on ; Erickson ; <6> 3/2/90 DDG Early in the boot process an _InitGraf was performed (for the ; Welcome to Mac box). It's not correct if the main screen moved ; away from the boot screen, so let's call InitGraf on these early ; globals to correct the problem. This will fix a problem with the ; LMgr "init" which didn't do an InitGraf while setting up the ; environment for an alert dialog. (this comment stolen from Brian ; McGhie) ; <5> 2/5/90 DAF The INIT resource executing code at boot time requires that the ; INIT resources not trash registers (particularily D6). This fix ; crudely saves and restores all register across calls. It's ; crude because this file is really about 3 independent inits ; strung together ; <4> 2/3/90 DAF Added additional init functionality to file. This code ; fixes a bug in the interrupt-level manipulation code in ; several Apple drivers. ; <3> 1/31/90 DAF Added an AllocCursor before the ShowCursor at the end of the ; init to make sure all data structures are properly setup ; <2> 1/30/90 DAF Added secondary function which sets a GDFlag bit to identify ; 32-bit addressed frame buffers. ; <1.0> 9/21/89 DAF FOR 6.0.4 Build - Color QuickDraw CheckDevices System Init ; <1.1> 8/17/89 DAF Commented a test out (;!!!) to force the gamma and gray state to ; be flushed out to the CLUT hardware with a SetEntries. ; ; To Do: ; To eliminate flashing, it would be nice to keep some sort of tally about which ; gDevices have already had SetEntries/SetGamma calls made to them. The cases ; where this would occur are rare, but it should be looked into. ; ; This code contains lots of jumping around, and it would be nice to eliminate it. ; ; In the ¥¥¥ 3rd INIT ¥¥¥ there a several ÒMove.l DeviceList,AxÓ. It might be ; nice to use something like A5 (since itÕs free and all the registers are ; being saved) to just cache the DeviceList. ; ; If the above is implemented, the SetDevEntries and SetDevGamma utilites could ; be tightened up to some degree (i.e, saving of input register(s)). ; ; SetDevEntries and SetDevGamma should return _Control errors. (This would be handy ; in the 4th INIT when SetDevGamma fails -- e.g., the card doesnÕt support it -- so ; that the subsequent SetDevEntries call is NOT made.) ; ; This system file INIT basically contains the CheckDevices routine from within Color QuickDraw ; (this excerpt from gdevice.a). This INIT runs only on CQD machines. ; ; This routine normally performs validations on the 'scrn' resource and sets up the color ; and gDevice environment. It fixes two bugs. The first is related to gamma tables ; specified by ID in the 'scrn' resource. Previously, if a gamma table was specified, but a ; color table ID was NOT specified, the gamma setting would not take place until the next ; change of the device's color table. The second is an improvement of the 'scrn' validation code. ; If a mode (screen depth) is recorded in the 'scrn' resource, but that mode becomes unavailable ; (through removal of frame buffer memory), then an invalid mode may be selected. This INIT ; corrects that problem by validating the mode field. ; ; Since this routine is fairly large, and only executes once, I'm executing this code as a System ; INIT before the first _InitGraf. The code in ROM will see that the allInit flag is set, and will ; just skip over the faulty code in ROM. There's no attempt to modify the ROM version. ; ; IÕve left this code as close to CheckDevices as possible. Live code that has been left out of ; this init version is marked with ';+++'. ; ; UPDATE FOR 6.0.5: I've added another INIT function to the tail end of the main Init. This ; code tests each frame buffer in the system, and sets a bit in GDFlags of it's gDevice if ; the frame buffer is to be addressed in 32-bit addressing mode. Addressing mode is independent ; of pixelsize. Only 32-bit QD equipped machines can use these frame buffers, but the ; design of the video card architecture protects non-QD 32 machines. ; ; UPDATE FOR SixPack: I (jmp) have essentially added three more INIT functions. Two of these end ; up jumping to the same piece of code, and the third (although it uses some of the code from ; the first two) is totally different. The addeded functionality in the first two INIT functions ; is to correct the problem where there is no and/or no valid 'scrn' resource in the System. To do ; this we just call SetEntries on the boot deviceÕs pmTable. The other problem is a little more ; subtle and only happens on $067C machines. The problem is that InitDefGamma (in StartInit) ; doesnÕt set up non-TFB, non-gamma dir cards at all. So, the INIT here is does a SetEntries ; and SetGamma on $067C machines on all non-TFB cards that contain no gamma directories. ; MACHINE MC68020 LOAD 'StandardEqu.d' INCLUDE 'Slots.a' INCLUDE 'ROMEqu.a' INCLUDE 'Video.a' INCLUDE 'GestaltEqu.a' ;---------------------------------------------------------------------------------------------------- ; This code is only an INIT under older systems that use the old boot sequence ; for 7.0 systems it is called by StartSystemPatches instead. if &type('asINIT')='UNDEFINED' then asINIT: equ 0 endif ;---------------------------------------------------------------------------------------------------- if asINIT then ThreeVideoThings MAIN else DavesRandomVideoStuff PROC EXPORT endif WITH VDPageInfo ;---------------------------------------------------------- ; ; PROCEDURE CheckDevices; ; ; Look at the device list to see if it needs to be initialized. If so, read ; in the resource of type 'scrn'. If it is found, configure the devices as ; described in that resource. The format of the 'scrn' resource is: ; ; [count] ; [word] number of devices in resource ; FOR I := 1 TO COUNT DO ; [sResource Type] ; [word] spDrvrH of device n ; [slot] ; [word] slot number of device n ; [dCtlDevBase] ; [long] the dCtlDevBase of device n ; [mode] ; [word] the sRsrcID for the desired mode ; [flagMask] ; [word] masks off all bits used in flags ; [flags] ; [word] indicates the state of the device ; ; bit 0 = 0 if monochrome; 1 if color ; ; bit 11 = 1 if this device is main screen ; ; bit 15 = 1 if the screen is active ; [colorTable] ; [word] resource id of desired color table (-1=none) ; [gammaTable] ; [word] resource id of gamma table (-1=none) ; [global Rect] ; [rect] global rectangle for this device ; [CtlCount] ; [word] number of control calls following ; FOR J := 1 TO CtlCount DO ; [csCode] ; [word] control code for this call ; [length] ; [word] number of bytes in the param blk ; [param blk] ; [length] data to be passed in control call ; END; ; END; ; ; CheckDevices is called by InitGraf. ;PARAMSIZE EQU 0 ; <19> What is this for? DoesnÕt appear to be used. IOPBlk EQU -IOVQElSize ; [64] parameter blk for I/O calls SlotParms EQU IOPBlk-spBlock.SPBlockSize ; parameter block for slot manager calls VidParms EQU SlotParms-12 ; [12] size of mode params StartList EQU VidParms-4 ; [long] pointer to start of resource VARSIZE EQU StartList-4 ; size of local vars for CheckDevices UTILVARS EQU VidParms-$30 ; size of local vars for utility routines ; ¥¥¥ Start of Code ¥¥¥ ; if asINIT then CMP.W #$3FFF,ROM85 ; is this a MacII-class machine? BEQ CheckDevices ; yup, so continue RTS ; if not, then exit else Bra CheckDevices ; <19>: Jump abound utility routines. Should we make a ; real INIT out of this (i.e., using a Òstandard headerÓ)? endif ; Utilities ------------------------------------------------------------------------------------------------ ; ; SetDevEntries: This routine expects A0 to contain the Handle to the gDevice (GDHandle) being set. ; If A1 contains a -1, SetDevEntries will use the pmTable, otherwise it treats A1 ; as a Handle to a colorTable. ; ; If the gDevice is a directType/fixedType, SetEntries will not be called. ; ; A0 and A1 will NOT necessarily be preseverd on exit. ; SetDevEntries Link A6,#UTILVARS ; Allocate room for local vars. Move.l A2,-(Sp) ; Storage for remembering gDevice. Move.l (A0),A2 ; gDevice Handle to gDevice Ptr. Cmp.w #clutType,gdType(A2) ; If the gDevice is direct or fixed (SKH), Bne.s @sdeExit ; then do nothing. Cmp.l #-1,A1 ; If A1 == -1, then use the Beq.s @usePMap ; gDeviceÕs PixMap. Move.l A1,A0 ; Otherwise copy the colorTable Handle Bra.s @continue ; and continue on. @usePMap Move.l gdPMap(A2),A0 ; Get the gDeviceÕs pixMapÕs Move.l (A0),A0 ; colorTable. Move.l pmTable(A0),A0 ; @continue _HLock ; Lock down the colorTable. Move.l A0,-(Sp) ; And save it for _HUnlock. Move.l (A0),A0 ; Turn it into a Ptr. Lea VidParms(A6),A1 ; Set up for SetEntries: Clr.w csStart(A1) ; csStart = 0 Move.w ctSize(A0),csCount(A1) ; csCount = pmTable.ctSize Lea ctTable(A0),A0 ; Move.l A0,csTable(A1) ; csTable = &pmTable.ctTable[0] Lea IOPBlk(A6),A0 ; Set up for Control call: Move.w gdRefNum(A2),ioRefNum(A0) ; ioRefNum = gDevice.gdRefNum Move.w #cscSetEntries,csCode(A0) ; csCode = cscSetEntries Move.l A1,csParam(A0) ; csParam = &VidParams _Control ,Immed ; Call SetEntries. Move.l (Sp)+,A0 ; Unlock color table Handle. _HUnlock @sdeExit Move.l (Sp)+,A2 ; Restore A2. Unlk A6 Rts ; SetDevGamma: This routine expects A0 to contain the Handle to the gDevice (GDHandle) being set, and ; A1 to contain a Ptr to a gammaTable. ; ; A0 and A1 will NOT necessarily be preserved on exit. ; SetDevGamma Link A6,#UTILVARS ; Allocate room for local vars. Movem.l A2-A3, -(Sp) ; Storage for gDevice/gammaTable. Move.l (A0),A2 ; gDevice Handle to gDevice Ptr. Move.l A1,A3 ; save gammaTable Ptr. Lea VidParms(A6),A1 ; Set up for SetGamma call: Move.l A3,csGTable(A1) ; csGTable = gammaTable Ptr Lea IOPBlk(A6),A0 ; Set up for Control call: Move.w gdRefNum(A2),ioRefNum(A0) ; ioRefNum = gDevice.gdRefNum Move.w #cscSetGamma,csCode(A0) ; csCode = cscSetGamma Move.l A1,csParam(A0) ; csParam = &VidParams <20> Changed Move.w to Move.l (oops). _Control ,Immed ; Call SetGamma. Movem.l (Sp)+,A2-A3 ; Restore A2-A3. Unlk A6 Rts ; ; ---------------------------------------------------------------------------------------------------------- NewFunc Link A6,#-$B4 Move.l A2,-(SP) Move.l (A0),A2 Lea.l -$94(A6),A1 Move.l #-2,(A1) Lea.l -$B4(A6),A0 Move.l A0,$C(A1) Lea.l -$40(A6),A0 Move (A2),$18(A0) Move #$14,$1A(A0) Move.l A1,$1C(A0) dc.w $A205 ; _PBStatusImmed Move.l (SP)+,A2 Unlk A6 Rts CheckDevices ; <19>: Moved label from within if-endif to embed utility ; routines. It would be nice to be able to the the LINK ; stuff AFTER the GotScrn entrypoint. LINK A6,#VARSIZE ; allocate local stack frame MOVEM.L A0-A4/D0-D7,-(SP) ; so we donÕt screw up the boot process Move.l DeviceList,A0 ; A0 contains gDevice. Move.l #-1,A1 ; Use gDeviceÕs PixMap for colorTable. Bsr.s SetDevEntries ; Bra NoGammaFix ; ¥¥¥ 4th INIT ¥¥¥ ; ; As explained above in the SixPack update notes, the NoGammaFix is for $067C-class ; machines only. The function of this code is to seek out non-TFB video cards that ; do not have gamma directories. When such cards are found, they are issued a ; SetDevGamma call with the ROMÕs default gamma table. ; ; [This should just be fixed in the SuperMario CQD sources directly.] ; NoGammaFix WITH spBlock,vpBlock ; Get the default gamma table from ROM (so we donÕt have to get it every time ; we find a card that needs it -- if we donÕt find any cards that need ; to be fixed, no harm done). ; Clr.l -(Sp) ; Make an RGetResource('gama',0) call. Move.l #'gama',-(Sp) ; resType = 'gama' Clr.w -(Sp) ; resID = 0 _RGetResource ; (RGetResource exists on $067C machines.) ; Since this is a ROM resource, I assume that the _RGetResource will NOT fail. Is ; this a bad assumption? (IÕve seen several places in various other OS files that ; make the same assumption, but I wonÕt name any names.) Move.l (Sp),-(Sp) ; Transform the 'gama' resource into _DetachResource ; a Handle, and prevent it from Move.l (Sp)+,A0 ; being purged. _HNoPurge Move.l A0,A2 ; Keep a copy of the gammaTable Handle ; in A2 for future reference. ; Walk thru the gDevice list looking for non-TFB video cards that do not have ; gamma directories. (Note: Dave F. suggested that I do this via the Slot ; Manager but I thought that since gDevices have already been set up and ; since they are easier to walk thru, I would just use them instead.) Move.l DeviceList,A3 ; Use A3 to keep the gDevice Handle, and @nextGD Move.l A3,A4 ; A4 to keep the gDevice Ptr. Move.l (A4),A4 ; Move.w gdRefNum(A4),D0 ; Get the gDeviceÕs slotID by looking Not.w D0 ; it up in the UnitTable. Move.l UTableBase,A0 ; Move.l (A0,D0*4),A0 ; DCE Handle. Move.l (A0),A0 ; DCE Ptr. Move.b dCtlSlot(A0),D0 ; Save slot number. Cmp.b #15,D0 Bcs.b @dont Move.l A3,A0 Bsr.w NewFunc Bne.s @reallyDont Bra.s @skipGD @dont Lea SlotParms(A6),A0 ; Fill out SpBlock: Move.b D0,spSlot(A0) ; spSlot = slot number Clr.w spID(A0) ; spID = 0 Clr.w spExtDev(A0) ; spExtDev = 0 Move.b #drvrHWMask,spTBMask(A0) ; spTBMask = drvrHWMask Move.w #catDisplay,spCategory(A0) ; spCategory = catDisplay Move.w #typVideo,spCType(A0) ; spCType = typVideo Move.w #drSwApple,spDrvrSW(A0) ; spDrvrSW = drSwApple Clr.w spHwDev(A0) ; spHwDev = 0; _SNextTypeSRsrc ; Was there an Apple SW compatible video card here? Bne.s @skipGD ; Apparently not, so skip this device. Cmp.w #drHwTFB,spDrvrHW(A0) ; If there is a card here, is it a TFB? Beq.s @skipGD ; Yep, so skip it. Move.b #sGammaDir,spID(A0) ; Not a TFB, so does it have a gamma _SFindStruct ; directory associated with? Beq.s @skipGD ; Yep, so skip it. ; We found a non-TFB card that contains no gamma table directory. So, we need to ; employ our fix, which is to make a SetGamma and then a SetEntries call. @reallyDont Move.l A2,A0 ; Lock down the gammaTable Handle. _Hlock Move.l (A0),A1 ; gammaTable Ptr into A1. Move.l A3,A0 ; gDevice Handle into A0. Bsr SetDevGamma Move.l A2,A0 ; Unlock gammaTable Handle. _HUnlock Move.l A3,A0 ; gDevice Handle into A0. Move.l #-1,A1 ; Use gDeviceÕs PixMap for colorTable. Bsr SetDevEntries @skipGD Move.l gdNextGD(A4),D0 ; Get the next gDevice. And if Move.l D0,A3 ; weÕre not at the end of the Bne.s @nextGD ; list, go around again. Move.l A2,A0 ; Dispose of the storage used for the _DisposHandle ; gammaTable Handle. ; ¥¥¥ 5th INIT ¥¥¥ ; ;---------------------------------------------------------------- ; ; Here's the other init in the file. It scans the device list frame buffers ; and sets a flag in the gDevice if the frame buffer is addressed in 32-bit ; mode. It's kind of slobby looking to hook this onto the end of the other ; init instead of integrating, but it's small, and the CheckDevices code ; goes to great lengths to exit early when it can, which this cannot do. ; ;---------------------------------------------------------------- ; ; Yet a another function co-exists with the others in this file. If we recognize ; an Apple Video card who's interrupt handler needs to be fixed, we will do it here. ; Here's the problem: In an attempt to simplify the driver code while correcting some ; of my VBL polling code, I raised the interrupt level to level-7 while waiting for ; the leading edge of VBL. Unfortunately, this can lead to a (eternally long) wait ; of up to one active screen for the next leading edge. In earlier versions, I ; forced the SR to $2200 which got level-2 interrupts (good) and forced the interrupt ; stack pointer (bad). When the interrupt level is raised to level-7, the SCC and ; everything else is blocked out which can cause loss of data on the serial ports. ; This new replacement code will raise the level to level-2 if it isn't higher already ; but won't change it if it is 3 or higher. This code is quite a bit larger than the ; original code, but fortunately, the drivers are all in RAM, so it's easy to patch ; them all out. ; ; We modify four different types of drivers. All drivers share the same faulty code, ; so we fix them all by installing a single copy of the updated interrupt code in the ; system heap, identifying which drivers are subject to patch, then pointing them at the ; new interrupt code. We identify the drivers via a few bytes of code that have significant ; values such as the name strings. We don't need to do a full compare, or check version ; numbers since we will verify the object code in the driver as well. If the faulty code ; isn't there, then we don't have to replace it! The drivers are always locked, so this ; is pretty safe (they must be locked since the interrupt handler is included within the ; driver proper). ; ; Here are the video cards modified: ; 1) Mac IIci Built-In Video Driver (.Display_Video_Apple_RBV1) [Only when this code is built as a patch.] ; 2) Mac II High-Resolution Video Card (.Display_Video_Apple_HRVC) ; 3) Mac II Two-Page Video Card (.DrWVC) [ROM Version WVC1.2, P/N 341-0727] ; 4) Mac II Portrait Video Card (.DrPVC) [ROM Version PVC1.1, P/N 341-0732] ; BRA DoDrvrPatches ; Stupid extra branch because I calculate the size of the ; resident interrupt handler from labels, and they can't ; be forward references. <15>: Changed name from Start to ; DoDrvrPatches for <17>. ;----- Memory/ROM-Resident Interrupt Handler Patch ------ ; ; Here is the improved interrupt level setting code. It's a little weird looking since I ; had to patch the MOVE.W SR,-(SP) to have room for the JSR, but I couldn't save any ; registers on the stack, and couldn't trash any regs either. ; ; All registers preserved (except SR!). This routine returns with the SR pushed on the top of ; stack. ; PtchStart SUBA.W #2,SP ; make room for the stack manipulations MOVE.L 2(SP),(SP) ; move the retaddr to top, leaving room for SR MOVE.W SR,4(SP) ; save the status reg MOVE.L D0,-(SP) ; save this reg MOVEQ #7,D0 ; get mask in D0 AND.B 8(SP),D0 ; get the interrupt level SUBQ.B #2,D0 ; BGE.S @OK ; if ³, then don't change ORI.W #$0200,SR ; raise above level-2 ANDI.W #$FAFF,SR ; make it level-2 @OK MOVE.L (SP)+,D0 ; restore saved register RTS ; return to caller PtchEnd ;---------------------------------------------------- ; ; This compares the object code at (A1,D0.W) with the target string in D6 and D7, then, if it ; matches, replaces this object with a JSR absolute. It saves a little code in the patch ; since this is a very common sequence. ; CmpReplTarget1 CMP.W (A1,D0.W),D6 ; is this the target string BNE.S ExitBad ; no, so quit CMP.L 2(A1,D0.W),D7 ; check the other half BNE.S ExitBad ; no, so quit ; Replace the faulty code ; MOVE.W (A6),(A1,D0.W) ; copy the JSR instruction If ForROM Then Lea PtchStart,A5 ; Get a pointer to the start of the replacement code. Move.l A5,2(A1,D0.W) ; And copy it down. Else MOVE.L 2(A6),2(A1,D0.W) ; copy the patch address Endif ExitGood RTS ; return ExitBad ADDA #4,SP ; kill return address BRA NxtSlot ; and go to next card ; ; This compares the HRVC's odd case object code at (A1,D0.W) with TargetObj2, then, if it ; matches, replaces this object with a JSR absolute. ; CmpReplTarget2 MOVE.L A0,-(SP) ; save some regs LEA TargetObj2,A0 ; point to the target object MOVE.L (A0)+,D1 ; get the first long CMP.L $9BA(A1),D1 ; is this the target string BNE.S ExitBad2 ; no, so quit MOVE.L (A0)+,D1 ; get the second long CMP.L $9BA+4(A1),D1 ; check the other half BNE.S ExitBad2 ; no, so quit MOVE.W (A0)+,D1 ; get the final word CMP.W $9BA+8(A1),D1 ; check the other half BNE.S ExitBad2 ; no, so quit ; Replace the faulty code ; MOVE.W (A6),$9BA(A1) ; copy the extended patch over If ForROM Then Lea PtchStart,A5 ; Get a pointer to the start of the replacement code. Move.l A5,$9BA+2(A1) ; And copy it down. Else MOVE.L 2(A6),$9BA+2(A1) ; copy the patch address Endif MOVE.L 6(A6),$9BA+6(A1) ; copy some NOPs for fill out the gap MOVE.L (SP)+,A0 ; restore A0 ExitGood2 RTS ; return ExitBad2 MOVE.L (SP)+,A0 ; restore A0 ADDA #4,SP ; kill return address BRA NxtSlot ; and go to next card ; Here is the faulty code section. We will replace it with a JSR to the improved code. Since ; the first line is a stack-based operation, the patch code needs to swap things around a ; bit. ; TargetObj1 MOVE.W SR,-(SP) ; word to test OR.W #$0700,SR ; longword to test TargetObj2 MOVE.W SR,D0 ; longword to test MOVE.W D0,-(SP) OR.W #$0700,D0 ; longword to test MOVE.W D0,SR ; word to test ; ; Here is the image of the code to replace the faulty sections. ; ReplObj JSR $7FFFFFFF ; the destination will be patched NOP ; target2 needs some additional NOPs NOP ; WITH spBlock,vpBlock DoDrvrPatches ; ; Save all registers to prevent problems with the ROM INIT running code. ; MOVEM.L A5-A6,-(SP) ; so we donÕt screw up the boot process ; ; Point to UnitTable in A2. ; MOVE.L UTableBase,A2 ; point to base of unit table ; ; Allocate a spBlock (slot parameter block) on the stack. ; SUB.W #spBlockSize,SP ; create an spBlock on the stack ; ; Set up stuff for the interrupt patch. ; LEA TargetObj1,A0 ; point to the start of the target sequence MOVE.W (A0),D6 ; get the first word of the target sequence MOVE.L 2(A0),D7 ; get the remaining long of the target seq MOVEQ #0,D5 ; if D5>0 at end, at least one card got patched ; ; It's easier to allocate the patch's memory and release it if it's not used than to allocate on ; demand. This is only a small piece of memory anyway. ; If Not ForROM Then MOVE.L #PtchEnd-PtchStart,D0 ; get the size of the interrupt fixer _NewPtr ,Sys ; allocate some memory for it in sysheap BNE Out ; if you can't get memory, exit LEA PtchStart,A1 ; point at the code EXG A1,A0 ; get source in A0, dest in A1 MOVE.L #PtchEnd-PtchStart,D0 ; get the size of the interrupt fixer _BlockMove ; copy it down Endif LEA ReplObj,A6 ; point to the substitution object If Not ForROM Then MOVE.L A1,2(A6) ; patch the JSR address with the sysHeap dest Endif ; ; Get a pointer to the first gDevice in A3. Since we won't upset memory, we don't need to lock it. ; MOVE.L DeviceList,A3 ; get handle MOVE.L (A3),A3 ; get pointer ; ; Point to DCE of next gDevice ; NxtSlotLoop MOVE.W gdRefNum(A3),D0 ; get driver refnum NOT.W D0 ; convert to offset MOVE.L (A2,D0*4),A1 ; get DCE handle MOVE.L (A1),A1 ; get DCE pointer MOVE.L (A1),A4 MOVE dCtlFlags(A1),D0 BTST.L #6,D0 BEQ.S @dont MOVE.L (A4),A4 @dont ; ; Point to spBlock. ; MOVE.L SP,A0 ; save pointer to block ; ; Set up for an sRsrcInfo call. ; MOVE.B dCtlSlot(A1),spSlot(A0) ; get slot number MOVE.B dCtlSlotID(A1),spID(A0) ; get ID MOVE.B dCtlExtDev(A1),spExtDev(A0) ; external device ID _sRsrcInfo ; there should never be a miss here If Not ForROM Then Bne Out1 ; But if there is, exit gracefully. Else Bne Out ; Ditto. Endif ; ; Now that we have the right sRsrcList in spsPointer, get the sRsrcFlags word ; from the video sRsrc. ; MOVE.B #sRsrcFlags,spID(A0) ; look for sRsrcFlags _sReadWord ; spsPointer is still set up from before BNE.S @IntPtch ; if not present, then it's 24-bit addressed MOVE.L spResult(A0),D0 ; get the result in a reg ; ; Test the flag word for 32-bit devices ; BTST #f32BitMode,D0 ; test it BEQ.S @IntPtch ; if not a 32-bit device, don't do init BSET #ext32Device,gdFlags(A3) ; set the 32-bit access flag in the gDevice ; ; Take the DCE pointer in A4 (from above), and test to see if we want to patch this driver. ; @IntPtch MOVE.L A4,A1 ; get pointer to driver MOVE.L drvrName+2(A1),D0 ; get a unique long from the name CMP.L #'DrWV',D0 ; is it the 2-Page card? BEQ.S @isTwo ; CMP.L #'DrPV',D0 ; is it the Portrait card? BEQ.S @isPort ; CMP.L #'Disp',D0 ; could it be one of the others? BNE NxtSlot ; no, so don't do anything with this card MOVE.L drvrName+20(A1),D0 ; pick up the next significant long CMP.L #'e_HR',D0 ; is it the Hi-Res Video card? BEQ.S @isHR ; If Not ForROM Then CMP.L #'e_RB',D0 ; is it the Mac II ci? BNE.S NxtSlot ; no, so go to the next card Else Bra.s NxtSlot Endif ; Here are the patch offsets for the Mac IIci Built-In Video v1.0 driver. If Not ForROM Then MOVE.W #$1A4,D0 ; pass the offset BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match MOVE.W #$2C0,D0 ; BSR CmpReplTarget1 ; MOVE.W #$656,D0 ; BSR CmpReplTarget1 ; BRA.S @IncFlag ; and exit Endif ; ; Since the Two-Page v1.2 and Portrait v1.1 are generated from the same source file, the offsets are the ; same. Earlier releases of these two ROMs don't have this interrupt problem. ; @isTwo ; @isPort MOVE.W #$2DA,D0 ; pass the offset BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match MOVE.W #$388,D0 ; BSR CmpReplTarget1 ; MOVE.W #$4D8,D0 ; BSR CmpReplTarget1 ; MOVE.W #$630,D0 ; BSR CmpReplTarget1 ; MOVE.W #$8CC,D0 ; BSR CmpReplTarget1 ; BRA.S @IncFlag ; and exit ; ; Here are the patch offsets for the Mac II Hi-Res Video Card v1.0. I missed updating one case of the ; interrupt disabling code, so there is one special patch for that missed case. ; @isHR MOVE.W #$45A,D0 ; pass the offset BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match MOVE.W #$58A,D0 ; BSR CmpReplTarget1 ; MOVE.W #$6F2,D0 ; BSR CmpReplTarget1 ; BSR CmpReplTarget2 ; here's the one odd case MOVE.W #$A1E,D0 ; BSR CmpReplTarget1 ; @IncFlag ADDQ #1,D5 ; increment patching flag NxtSlot MOVE.L gdNextGD(A3),D0 ; get handle to next gDevice Beq.s @EndSlotLoop ; If nil, weÕre done. Move.l D0,A3 ; Otherwise, copy the handle. Move.l (A3),A3 ; Turn it into a pointer. Bra.s NxtSlotLoop ; Loop until done. @EndSlotLoop ; ; See if the any drivers were patched. If not, then release the patcher block in sysheap. ; If Not ForROM Then TST.B D5 ; if zero, then nobody was patched BNE.S Out ; Out1 LEA ReplObj,A6 ; point to the substitution object MOVE.L 2(A6),A0 ; get the pointer block address from here _DisposPtr ; release it Endif ; ; Release the slot manager block. ; Out LEA spBlockSize(SP),SP ; clean up the stack Endwith ; ; Lets restore more registers than have ever been restored before. (Hey, you can never be too careful.) ; MOVEM.L (SP)+,A5-A6 MOVEM.L (SP)+,A0-A4/D0-D7 ; so we donÕt screw up the boot process UNLK A6 RTS END