mac-rom/QuickDraw/CheckDevicesINIT.a
2017-10-08 23:26:23 +08:00

832 lines
33 KiB
Plaintext

;
; 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):
;
; <SM10> 09-23-93 jmp Quit doing <SM8> below when the Display Manager is around.
; <SM9> 9/1/93 SKH Fixed a bug with fixed CLUT devices (ie: DBLite). SetEntries can not be called for
; direct or fixed devices
; <SM8> 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.
; <SM7> 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).
; <SM6> 10/28/92 SWC Changed SlotEqu.a->Slots.a and VideoEqu.a->Video.a.
; <SM5> 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.
; <SM4> 10/27/92 CSS Changed a short branch to a word branch.
; <SM3> 7/16/92 CSS Update from Reality:
; <27> 7/13/92 DTY #1035553 <csd>: 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 <FOR 7.0 BUILD> 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 ; size of local vars for CheckDevices
UTILVARS EQU VidParms ; 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), <SM9>
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
;
; ----------------------------------------------------------------------------------------------------------
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-A6/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 CheckDevices
nop
Bne.s * + $4A
Bra.s * + $62
@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.
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 A0-A6/D0-D7,-(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 <Control-SetVidMode>
BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match
MOVE.W #$2C0,D0 ; <Control-SetEntries>
BSR CmpReplTarget1 ;
MOVE.W #$656,D0 ; <Utility-WaitVSync>
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 <Control-SetVidMode>
BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match
MOVE.W #$388,D0 ; <Control-SetEntries/nonsequential>
BSR CmpReplTarget1 ;
MOVE.W #$4D8,D0 ; <Control-SetEntries/sequential>
BSR CmpReplTarget1 ;
MOVE.W #$630,D0 ; <Control-DisableVGuts>
BSR CmpReplTarget1 ;
MOVE.W #$8CC,D0 ; <Utility-TFBSetDepth>
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 <Control-SetVidMode>
BSR CmpReplTarget1 ; (compare and replace) or exit to NxtSlot if no match
MOVE.W #$58A,D0 ; <Control-SetEntries>
BSR CmpReplTarget1 ;
MOVE.W #$6F2,D0 ; <Control-DisableVGuts>
BSR CmpReplTarget1 ;
BSR CmpReplTarget2 ; here's the one odd case <Utility-WaitVSync>
MOVE.W #$A1E,D0 ; <Control-TFBSetDepth>
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 <SM6>
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