mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
9c249dafab
The ROM now round-trips with QuickDraw mostly built from source. (~30% of the ROM is now built from source.)
835 lines
33 KiB
Plaintext
835 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-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), <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
|
|
;
|
|
; ----------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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 <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
|