mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-12-01 18:50:30 +00:00
1543 lines
62 KiB
Plaintext
1543 lines
62 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
|
||
;
|
||
; ----------------------------------------------------------------------------------------------------------
|
||
|
||
|
||
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
|
||
;+++ MOVEM.L D6-D7/A2-A4,-(SP) ; save work registers
|
||
|
||
;+++; check to see if the device list needs to be initialized
|
||
;+++
|
||
;+++ MOVE.L DeviceList,A0 ; get handle to device list
|
||
;+++ MOVE.L (A0),A0 ; point to head of device list
|
||
;+++ MOVE GDFlags(A0),D0 ; get the flags word
|
||
;+++ BTST #allInit,D0 ; test initialize flag?
|
||
;+++ BNE GoHome ; => devices already initialized
|
||
|
||
; ••• 1st INIT •••
|
||
;
|
||
; Try to load in the resource. If none, then just do a SetEntries on the boot device (see
|
||
; the comments on the NoScrn code below).
|
||
;
|
||
GetScrn
|
||
CLR.L -(SP) ; make room for function result
|
||
MOVE.L #'scrn',-(SP) ; push desired resource type
|
||
CLR -(SP) ; resource ID = 0
|
||
_GetResource ; get the resource
|
||
MOVE.L (SP)+,D0 ; get the resource handle
|
||
Beq.s NoScrn ; if nil, do the no 'scrn' code
|
||
|
||
; ••• 2nd INIT •••
|
||
;
|
||
; Test the scrnInval low-mem to make sure the screen resource is valid. (Note: scrnInval
|
||
; will generally be cleared by the video card’s primaryInit IF the information in
|
||
; pRAM doesn’t match the current set up). This is ALSO a case where we need to
|
||
; make a SetEntries call so the screen colors don’t change on the the first SetEntries
|
||
; and/or SetGamma call.
|
||
;
|
||
ChkScrn
|
||
Tst.b scrnInval ; If the 'scrn' resource is not invalid,
|
||
Bne.s GotScrn ; then just go on.
|
||
|
||
Move.l D0,A4 ; Save the 'scrn' resource handle.
|
||
|
||
Move.l #gestaltDisplayMgrAttr,D0 ; We need to know if the Display Manager is around.
|
||
_Gestalt ; Ask, and ye shall receive.
|
||
Bne.s @NoDM ; Oops, got an error.
|
||
Move.l A0,D0 ; Get the result into D0.
|
||
Btst #gestaltDisplayMgrPresent,D0 ; If the Display Manager is around, then
|
||
Bne.s NoScrn ; don’t dispose of the 'scrn' resource so
|
||
@NoDM ; so that the Display Manager can deal with it.
|
||
|
||
Clr.w -(Sp) ; Make room for resFile refNum.
|
||
Move.l A4,-(Sp) ; Push 'scrn' resource handle for resFile.
|
||
_HomeResFile ; Get refNum.
|
||
|
||
Move.l A4,-(Sp) ; Push 'scrn' resource handle for remove.
|
||
_RmveResource ; Try to remove it.
|
||
Tst.w ResErr ; If everything is okay, then
|
||
Beq.s @DisposeIt ; just go on.
|
||
|
||
Tst.w (Sp)+ ; Clean up the stack.
|
||
Move.l A4,D0 ; Get 'scrn' resource handle back into D0.
|
||
Bra.s GotScrn ; And we’re screwed.
|
||
|
||
@DisposeIt Movea.l A4,A0 ; Get 'scrn' resource handle into A0.
|
||
_DisposHandle ; Dispose it.
|
||
|
||
_UpdateResFile ; Update the 'scrn's resFile lest we die later.
|
||
|
||
; If a 'scrn' resource is NOT around we’ll get here. The only thing we want to do at this
|
||
; point is to call SetDevEntries on the boot device so that the screen will not change colors
|
||
; after a SetEntries/SetGamma call is made later.
|
||
;
|
||
NoScrn
|
||
Move.l DeviceList,A0 ; A0 contains gDevice.
|
||
Move.l #-1,A1 ; Use gDevice’s PixMap for colorTable.
|
||
Bsr.s SetDevEntries ;
|
||
Bra NoGammaFix
|
||
|
||
; ••• 3rd INIT •••
|
||
;
|
||
; Lock down the 'scrn' handle, and point at the data (in A4).
|
||
;
|
||
GotScrn
|
||
MOVE.L DeviceList,A0 ; get handle to device list
|
||
MOVE.L (A0),A0 ; point to head of device list
|
||
BSET #allInit,GDFlags(A0) ; say list has been initialized
|
||
|
||
MOVE.L D0,-(SP) ; save 'scrn' resource for ReleaseResource
|
||
MOVE.L D0,A0 ; get the resource
|
||
_HLock ; lock it down
|
||
MOVE.L (A0),A4 ; A4 = resource pointer
|
||
|
||
; Validate the 'scrn' resource. There must be a descriptor for every screen device.
|
||
; I assume that there are no duplicate entries and that screens don't overlap.
|
||
; In addition the devices in the 'scrn' resource must be in slot order.
|
||
;
|
||
MOVE.L A4,StartList(A6) ; save pointer to start of list
|
||
MOVE (A4)+,D7 ; get the number of screens in resource
|
||
|
||
WITH spBlock,vpBlock
|
||
|
||
LEA SlotParms(A6),A0 ; get pointer to parameter block
|
||
MOVE.L #((CatDisplay << 16) ++ TypVideo),spCategory(A0)
|
||
; set category ID, type
|
||
MOVE.W #drSwApple,spDrvrSw(A0) ; set software, hardware ID
|
||
MOVE.B #$01,spTBMask(A0) ; ignore spDrvrHw
|
||
MOVE.B #0,spSlot(A0) ; start with desired slot (0 to check built-in devices)
|
||
MOVE.B #0,spID(A0) ; start with first (zeroth) ID
|
||
CLR.B spExtDev(A0) ;
|
||
NxtDev _sNextTypesRsrc ; get next video device
|
||
BEQ.S GotDev ; => there is one
|
||
|
||
; There are no more screens; are there any more entries in the 'scrn' resource?
|
||
;
|
||
TST D7 ; there should have been one per device
|
||
BEQ GoodRsrc ; => there was, go initialize them
|
||
BRA BadScrn ;
|
||
|
||
; Scan through 'scrn' resource entry for this device.
|
||
;
|
||
GotDev MOVE (A4)+,D0 ; get type
|
||
CMP spDrvrHw(A0),D0 ; does it match?
|
||
BNE BadScrn ; => nope, bad screen resource
|
||
MOVE (A4)+,D0 ; get slot
|
||
CMP.B spSlot(A0),D0 ; does it match?
|
||
BNE.S BadScrn ; => nope, bad screen resource
|
||
|
||
; Get the DCE entry for the device and check dCtlDevBase.
|
||
; If no match, look for other devices in the same slot.
|
||
;
|
||
SlotOK MOVE spRefNum(A0),D0 ; get the refNum
|
||
NOT D0 ; refNum to unitnum
|
||
ASL #2,D0 ; offset in unitTable
|
||
MOVE.L UTableBase,A1 ; get the base of the unit table
|
||
MOVE.L (A1,D0),A3 ; A3 = handle to the DCE
|
||
MOVE.L (A3),A1 ; get pointer to the DCE
|
||
MOVE.L dCtlDevBase(A1),D0 ; get dCtlDevBase
|
||
CMP.L (A4)+,D0 ; do they match?
|
||
BNE.S BadScrn ; => nope, bad screen resource
|
||
|
||
; Test to make sure that the requested mode (screen depth) is valid in this video
|
||
; sRsrc list.
|
||
;
|
||
MOVE.B spID(A0),D1 ; save the spID (so that it’s correct for the sNextTypesRsrc)
|
||
MOVE.W (A4)+,D0 ; get the mode
|
||
MOVE.B D0,spID(A0) ; insert into spBlock
|
||
_sFindStruct ; find the sRsrc list entry for this mode
|
||
BNE.S BadScrn ; if not, then the scrn resource is no good
|
||
MOVE.B D1,spID(A0) ; restore the spID
|
||
|
||
; To be completely compulsive about it, make sure there's a gDevice.
|
||
;
|
||
MOVE.L DeviceList,A3 ; A3 = first gDevice in list
|
||
MOVE spRefNum(A0),D1 ; get refnum (unaffected by sFindStruct)
|
||
@NxtGD MOVE.L (A3),A1 ; get pointer to device
|
||
CMP gdRefNum(A1),D1 ; does refnum match?
|
||
BEQ.S RectCheck ; => yes, this device matches!
|
||
MOVE.L gdNextGD(A1),D0 ; get handle of next device
|
||
MOVE.L D0,A3 ; get in A3
|
||
BNE.S @NxtGD ; => check all gDevices
|
||
BRA.S BadScrn ; => no such gDevice, bad 'scrn'
|
||
|
||
; Compare the size of the remembered screenRect to the size of this gDevice's
|
||
; gdRect. At this point, the gdRects are still topleft={0,0} from InitGDevice
|
||
; so we can just check 'scrn' rect against botRight.
|
||
;
|
||
RectCheck
|
||
ADD #8,A4 ; skip to global rect in 'scrn'
|
||
MOVE.W bottom(A4),D0 ; get bottom
|
||
SUB.W top(A4),D0 ; = height
|
||
CMP.W gdRect+bottom(A1),D0 ; is it equal?
|
||
BNE.S BadScrn ; nope, we're out
|
||
MOVE.W right(A4),D0 ; get right
|
||
SUB.W left(A4),D0 ; = width
|
||
CMP.W gdRect+right(A1),D0 ; is it equal?
|
||
BNE.S BadScrn ; nope, we're out
|
||
|
||
; This device matches! Go check the next one.
|
||
;
|
||
SkipData ADD #8,A4 ; skip to control field
|
||
MOVE (A4)+,D0 ; get number of control calls
|
||
BRA.S SkipCtl ; skip control call
|
||
SkipNxt MOVE.L (A4)+,D1 ; get control code, size of params
|
||
ADD D1,A4 ; add size of params to skip block
|
||
SkipCtl DBRA D0,SkipNxt ; => skip next control
|
||
|
||
SUBQ #1,D7 ; decrement device count
|
||
BMI.S BadScrn ; => oops, bad screen resource
|
||
|
||
LEA SlotParms(A6),A0 ; get pointer to parameter block <14>
|
||
BRA.s NxtDev ; => check next device <19>: .s
|
||
|
||
; If the 'scrn' resource is bad, then let's walk down the device list and offset
|
||
; the invalid screens' gdRects so that they don't all pile up at (0,0). Let's keep
|
||
; it simple--just put them all edge-to-edge, with the top edge at 0 (unchanged) and
|
||
; to the right of the previous guys'. Offset the gdPMap's rect also.
|
||
;
|
||
BadScrn
|
||
MOVE.L DeviceList,A0 ; get the head of the list (the boot screen)
|
||
MOVE.L (A0),A0 ; hndl->ptr
|
||
MOVE.W gdRect+right(A0),D1 ; get the boot screen's right edge (if the scrn
|
||
; is invalid, then this is the real right edge)
|
||
@Loop MOVE.L gdNextGD(A0),D0 ; get handle to next screen
|
||
BEQ ScrnDone ; when NIL we're out of here <19>: Done -> ScrnDone
|
||
MOVE.L D0,A0 ; get this device
|
||
MOVE.L (A0),A0 ; handle to ptr
|
||
ADD.W D1,gdRect+left(A0) ; offset the left edge (normally zero)
|
||
ADD.W D1,gdRect+right(A0) ; offset the right edge
|
||
MOVE.L gdPMap(A0),A1 ; get the gdPMap handle
|
||
MOVE.L (A1),A1 ; get the gdPMap pointer
|
||
ADD.W D1,pmBounds+left(A1) ; offset the left edge (normally zero)
|
||
ADD.W D1,pmBounds+right(A1) ; offset the right edge
|
||
|
||
MOVE.W gdRect+right(A0),D1 ; get the new right edge for the next device
|
||
BRA.S @Loop ; for each screen
|
||
|
||
GoodRsrc _HideCursor ; cursor must be hidden here
|
||
MOVE.B #true,CrsrBusy ; MARK CHANGE IN PROGRESS
|
||
|
||
; Configure each entry in the scrn resource
|
||
;
|
||
MOVE.L StartList(A6),A4 ; save pointer to start of list
|
||
MOVE (A4)+,D7 ; get the number of screens in resource
|
||
SUBQ #1,D7 ; make it 0 based
|
||
|
||
; It would be nice if this routine could use sRsrcInfo or sNextsRsrc here, but we
|
||
; don't keep the video sRsrc spID in the scrn resource, just the hw ID!!! To
|
||
; make up for this, we must do a search by type.
|
||
;
|
||
DoNxt LEA SlotParms(A6),A0 ; get pointer to parameter block
|
||
MOVE.L #((CatDisplay << 16) ++ TypVideo),spCategory(A0)
|
||
; set category ID, type
|
||
MOVE.W #drSwApple,spDrvrSw(A0) ;
|
||
; set software, (invalid) hardware ID
|
||
MOVE (A4)+,spDrvrHw(A0) ; set driver hardware ID
|
||
MOVE.B #$00,spTBMask(A0) ; all fields valid
|
||
MOVE (A4)+,D0 ; get slot
|
||
MOVE.B D0,spSlot(A0) ; does it match?
|
||
MOVE.B #0,spID(A0) ; start with first ID
|
||
CLR.B spExtDev(A0) ;
|
||
_sNextTypesRsrc ; get next video device
|
||
;+++ BNE BadScrn ; => this should never be taken (so let’s comment it out) <12>
|
||
|
||
; We found a device that matches the given description! Find its gDevice and configure it.
|
||
;
|
||
MOVE spRefNum(A0),D1 ; D1 = refnum
|
||
|
||
MOVE.L DeviceList,A3 ; A3 = first gDevice in list
|
||
@NxtGD MOVE.L (A3),A0 ; get pointer to device
|
||
CMP gdRefNum(A0),D1 ; does refnum match?
|
||
BEQ.S @GotGD ; => yes, got the gDevice
|
||
MOVE.L gdNextGD(A0),D0 ; get handle of next device
|
||
MOVE.L D0,A3 ; get in A3
|
||
BNE.S @NxtGD ; => check all gDevices
|
||
;+++ BRA BadScrn ; => this should never be taken (so let’s comment it out) <12>
|
||
|
||
@GotGD MOVE.L (A4)+,D0 ; discard dCtlDevBase
|
||
|
||
; Set up the GDFlags word before calling InitGDevice.
|
||
;
|
||
MOVE.L (A3),A1 ; point at the grafDevice
|
||
MOVE gdFlags(A1),D0 ; get the flags word
|
||
AND 2(A4),D0 ; turn off the bits that are used
|
||
OR 4(A4),D0 ; turn on new bits
|
||
BSET #ramInit,D0 ; say we've initialized it
|
||
BSET #screenDevice,D0 ; and flag it as a screen device
|
||
MOVE D0,GDFlags(A1) ; set the flags word
|
||
|
||
; If main device, set up low-memory handles. (Wait: If the ramInit and screenDevice
|
||
; flags are NOT setup, then why would the mainScreen flag be setup? -- jmp)
|
||
;
|
||
MOVE gdFlags(A1),D0 ; get the flags word
|
||
BTST #mainScreen,D0 ; is it the main scrn?
|
||
BEQ.S @InitGD ; => no, go init device
|
||
|
||
MOVE.L A3,MainDevice ; set up as main screen device
|
||
MOVE.L A3,TheGDevice ; set up as default destination device
|
||
MOVE.L A3,SrcDevice ; set up as default source device
|
||
; AllocCursor called by InitCursor to init cursor
|
||
MOVE.L (A3),A0 ; point to gDevice
|
||
MOVE.L gdPMap(A0),A0 ; get pixMap handle
|
||
MOVE.L (A0),A0 ; point to pixMap
|
||
MOVE.L baseAddr(A0),D0 ; get base address
|
||
MOVE.L D0,scrnBase ; and set up screen base
|
||
|
||
LEA SlotParms(A6),A0 ; point at slot manager block again (it's still positioned from above)
|
||
MOVE (A4),D0 ; get the requested mode
|
||
MOVE.B #oneBitMode,spId(A0) ; pass the default mode (assumed to be 1-bit mode)
|
||
_sFindStruct ; point to this mode information
|
||
|
||
MOVE.B #mVidParams,spID(A0) ; now get the device pixmap
|
||
_sGetBlock ; on the current heap (system normally here)
|
||
MOVE.L spResult(A0),A1 ; get the result pointer
|
||
MOVE.w vpRowBytes(A1),screenRow ; get the screen row bytes (WORD)
|
||
|
||
; Set up the low-mem for screen resolution too. They’re only WORD/WORD rather then FIXED/FIXED.
|
||
;
|
||
MOVE.W vpHRes(A1),ScrHRes ; Take the high word of vpHRes
|
||
MOVE.W vpVRes(A1),ScrVRes ; Take the high word of vpVRes
|
||
|
||
MOVE.L spResult(A0),A0 ; Do what it says in IM V (p 446) instead of
|
||
_DisposPtr ; of using _sDispose. <12>
|
||
|
||
@InitGD MOVE D1,-(SP) ; push refnum
|
||
MOVE (A4)+,-(SP) ; push mode
|
||
CLR -(SP) ; which should be long
|
||
MOVE.L A3,-(SP) ; push gDevice
|
||
_InitGDevice ; configure the gDevice
|
||
ADDQ #4,A4 ; mask and flags already used
|
||
|
||
; If there is a gamma table resource id, get the gamma correction table and call the driver.
|
||
; We need to do this before setting the color table (via SetEntries) to make sure it takes
|
||
; effect right away.
|
||
;
|
||
MOVE 2(A4),D0 ; get the gamma table resource id
|
||
CMP #-1,D0 ; is it -1?
|
||
BEQ.S ChkTbl ; => yes, no table
|
||
|
||
; If the gamma table resource id = -2, then request linear gamma from the driver.
|
||
;
|
||
CMP #-2,D0 ; is it -2?
|
||
BNE.S @GetFromSys ; nope, so load the system resource
|
||
|
||
;+++ LEA VidParms(A6),A1 ; point to parameter block
|
||
;+++ CLR.L csGTable(A1) ; pass NIL to tell new drivers to set linear
|
||
;+++ BSR.S GammaControl ; call a common routine to set gamma
|
||
|
||
; <19>: Use SetDevGamma instead of GammaControl
|
||
;
|
||
Move.l A3,A0 ; Put gDevice in A0 for SetDevGamma call.
|
||
Move.l #0,A1 ; (nil) gammaTable Ptr in A1 (to set linear).
|
||
Bsr.s SetDevGamma
|
||
;
|
||
BRA.S ChkTbl
|
||
|
||
; Load the gamma resource from the system and set it.
|
||
;
|
||
@GetFromSys CLR.L -(SP) ; make room for function result
|
||
MOVE.L #'gama',-(SP) ; push gamma table rsrc type
|
||
MOVE D0,-(SP) ; else push resource id
|
||
_GetResource ; try to read in gamma table
|
||
MOVE.L (SP)+,D0 ; get the result
|
||
BEQ.S ChkTbl ; => couldn't find it, use default
|
||
MOVE.L D0,-(SP) ; save a copy for later
|
||
MOVE.L D0,A0 ; setup for HLock
|
||
_HLock ;
|
||
|
||
;+++ LEA VidParms(A6),A1 ; point to params for SetGamma
|
||
;+++ MOVE.L (A0),csGTable(A1) ; gamma table pointer is only param
|
||
;+++ BSR.S GammaControl ; call a common routine
|
||
|
||
; <19>: Use SetDevGamma instead of GammaControl. For <23>, the setup for the
|
||
; SetDevGamma call was backwards.
|
||
;
|
||
Move.l (A0),A1 ; Put pointer to gammaTable in A1, and
|
||
Move.l A3,A0 ; put pointer to GDevice in A0.
|
||
Bsr.s SetDevGamma
|
||
;
|
||
MOVE.L (SP),A0 ; get the resource handle back
|
||
_HUnlock ; free it
|
||
_ReleaseResource ; and release it (fixing the stack)
|
||
|
||
; <19>: Commented out GammaControl as it is replaced by the SetDevGamma utility
|
||
; above. Also, the branch around the GammaControl routine is commented
|
||
; out.
|
||
;
|
||
;+++ BRA.S ChkTbl ; continue on
|
||
;
|
||
; Here's an imbedded utility. I know I burn 2 bytes always BSRing around it, but I
|
||
; would burn two with a word branch if the utility were outside. This routine sets
|
||
; up the iopb and csParam block for a SetGamma control call. It expects the csGTable
|
||
; field to be set up, the csParam block pointer in A1, and the gdevice pointer in A3.
|
||
;
|
||
;GammaControl
|
||
;
|
||
; LEA IOPBlk(A6),A0 ; point to parameter block
|
||
; MOVE.L A1,csParam(A0) ; move addr of parms into block
|
||
; MOVE.W #cscSetGamma,csCode(A0) ; cscSetGamma <12>
|
||
;+++ CLR.L ioCompletion(A0) ; no completion routine <16>: not necessary
|
||
;+++ CLR.W ioVRefNum(A0) ; no volRefNum <16>: not necessary
|
||
; MOVE.L (A3),A1 ; point to gdevice
|
||
; MOVE GDRefNum(A1),ioRefNum(A0) ; set device's refnum
|
||
; _Control ,IMMED ; SetGamma(GammaTable)
|
||
; ; if error here (likely if -2 were passed to
|
||
; ; and old driver) then just use default table
|
||
; RTS ; and back
|
||
;
|
||
;
|
||
; Previously, if there was a color table resource id, this part loaded that table. Now,
|
||
; it checks the state of the gdDevType bit. If it is monochrome (=0), then this routine
|
||
; substitutes pixelSize+32 for the resID. If it is color (=1) and in 2- or 4-bit mode, then
|
||
; pixelSize+64 is substituted to yield a modified color table that includes the highlight
|
||
; color.
|
||
;
|
||
; If we EVER have a gamma ID <> -1 (not default), then be sure to set the color table
|
||
; to flush this gamma into the CLUT hardware.
|
||
;
|
||
; The pointer to the gDevice is still in A1.
|
||
;
|
||
;
|
||
ChkTbl
|
||
MOVE.L (A3),A1 ; point to the gDevice again
|
||
MOVE.L gdPMap(A1),A0 ; get pixmap
|
||
MOVE.L (A0),A0 ; get pixmap ptr
|
||
MOVE.W pmPixelSize(A0),D0 ; get depth
|
||
|
||
CMP #clutType,gdType(A1) ; is it a direct/fixed (SKH) device? <SM9>
|
||
BNE SetGRect ; if so, then do nothing <19>:s <SM4> CSS
|
||
|
||
BTST #gdDevType,gdFlags+1(A1) ; is it color or monochrome mode?
|
||
BNE.S @ClrMode ; if set, then this is color
|
||
CMP.W #2,D0 ; 1 or 2 bit/pixel?
|
||
BLE.S @RegClr ; don't do anything funky
|
||
@MonoMode
|
||
ADD #32,D0 ; add 32 to pixelsize in all modes for linear gray
|
||
BRA.S @GetClut ;
|
||
@ClrMode
|
||
MOVE.W D0,D1 ; copy the depth
|
||
AND #9,D1 ; is it 1- or 8-bit mode?
|
||
BNE.S @RegClr ; if so, then do regular behavior
|
||
@Is2or4
|
||
ADD #64,D0 ; for 2- or 4-bit, add 64 to pixel depth (gives color+highlight)
|
||
;!!! BRA.S @GetClut ;
|
||
|
||
@RegClr
|
||
;!!! MOVE (A4),D1 ; get the color table resource id
|
||
;!!! CMP #-1,D1 ; is it -1?
|
||
;!!! BNE.S @GetClut ; if not, then set the CLUT
|
||
;!!! CMP #-1,2(A4) ; if CLUTid=-1, and gammaID<>-1, then set CLUT to flush
|
||
;!!! BEQ.S SetGRect ; if both are default, then continue
|
||
|
||
@GetClut CLR.L -(SP) ; make room for function result
|
||
MOVE D0,-(SP) ; push resource id
|
||
_GetCTable ; get a color table
|
||
MOVE.L (SP)+,D0 ; get the result
|
||
BEQ.S SetGRect ; => couldn't find it, use default
|
||
|
||
MOVE.L D0,A0 ; save source handle in A0
|
||
MOVE.L (A3),A1 ; point at the gDevice
|
||
MOVE.L gdPMap(A1),A1 ; get handle to its pixMap
|
||
MOVE.L (A1),A1 ; point at the pixMap
|
||
MOVE.L pmTable(A1),A1 ; get handle to existing color table
|
||
MOVE.L A1,-(SP) ; push the color table for later
|
||
MOVE.L A0,-(SP) ; push new table handle for dispose
|
||
|
||
_GetHandleSize ; get the source size
|
||
MOVE.L D0,D1 ; save size in D1
|
||
EXG A0,A1 ; get dest handle in A0
|
||
_SetHandleSize ; set the dest handle size
|
||
EXG A0,A1 ; swap dest back to A1, src to A0
|
||
|
||
MOVE.L (A0),A0 ; get source ptr
|
||
MOVE.L (A1),A1 ; get dst ptr
|
||
MOVE.L D1,D0 ; get size to move
|
||
_BlockMove ; copy it
|
||
|
||
_DisposCTable ; and dispose new handle
|
||
|
||
; Now call the driver to set this color table (handle on stack)
|
||
; <19>: Use SetDevEntries call instead of in-line code.
|
||
;
|
||
Move.l A3,A0 ; A0 contains gDevice.
|
||
Move.l (Sp),A1 ; A1 contain colorTable Handle
|
||
Bsr.s SetDevEntries ;
|
||
|
||
; MOVE.L (SP),A0 ; get handle to color table
|
||
; _HLock ; lock down the color table
|
||
; LEA VidParms(A6),A1 ; point to params for SetEntries
|
||
; MOVE.L (A0),A0 ; get ctabPtr
|
||
; CLR.W csStart(A1) ; start at zero, use sequence mode
|
||
; MOVE.W ctSize(A0),csCount(A1) ; for the length of the table
|
||
; LEA ctTable(A0),A0 ; get pointer to colorspecs
|
||
; MOVE.L A0,csTable(A1) ; color table pointer is first param
|
||
; LEA IOPBlk(A6),A0 ; point to parameter block
|
||
; MOVE.L A1,csParam(A0) ; move addr of parms into block
|
||
; MOVE.W #cscSetEntries,csCode(A0) ; cscSetEntries <12>
|
||
;+++ CLR.L ioCompletion(A0) ; no completion routine <14>: not necessary
|
||
;+++ CLR.W ioVRefNum(A0) ; no volRefNum <14>: not necessary
|
||
; MOVE.L (A3),A1 ; point to gdevice
|
||
; MOVE gdRefNum(A1),ioRefNum(A0) ; set device's refnum
|
||
; _Control ,IMMED ; do a SetEntries on color table
|
||
;
|
||
; MOVE.L (SP),A0 ; get handle to color table
|
||
; _HUnLock ; unlock the color table
|
||
|
||
; Finally, generate an inverse table for the table (handle on stack)
|
||
;
|
||
MOVE.L (A3),A1 ; point at the gDevice
|
||
MOVE.L gdITable(A1),-(SP) ; push inverse table handle
|
||
MOVEQ #4,D0 ; make 4-4-4 inverse tables
|
||
MOVE D0,gdResPref(A1) ; save in GDevice
|
||
MOVE D0,-(SP) ; and push res
|
||
_MakeITable ; and generate inverse table (color/inverse table handles still on stack)
|
||
|
||
; Use the specified rectangle to determine the device's global coordinates
|
||
;
|
||
SetGRect
|
||
ADDA #4,A4 ; skip the CLUT and gamma resID's
|
||
MOVE.L (A3),A0 ; point to the grafDevice
|
||
MOVE.L gdPmap(A0),A1 ; get handle to pixMap
|
||
MOVE.L (A1),A1 ; get pointer to pixMap
|
||
ADDQ #bounds,A1 ; point to pixMap.bounds
|
||
LEA gdRect(A0),A0 ; point to its rectangle
|
||
MOVE.L (A4)+,D0 ; get topLeft for mouse offset
|
||
MOVE.L D0,(A1)+ ; copy topLeft to pixMap.bounds
|
||
MOVE.L D0,(A0)+ ; copy topLeft to GDRect
|
||
MOVE.L (A4),(A1) ; copy botRight to pixMap.bounds
|
||
MOVE.L (A4)+,(A0)+ ; copy botRight to GDRect
|
||
|
||
; Parse and execute the additional control commands
|
||
;
|
||
MOVE (A4)+,D6 ; get number of control calls
|
||
BRA.S ChkNxtCtl ; => jump into end of dbra loop
|
||
DoCtl LEA IOPBlk(A6),A0 ; point to parameter block
|
||
LEA 4(A4),A1 ; point to call parameters
|
||
MOVE.L A1,csParam(A0) ; move addr of parms into block
|
||
MOVE.W (A4)+,csCode(A0) ; set control code
|
||
;+++ CLR.L ioCompletion(A0) ; no completion routine <14>: not necessary
|
||
;+++ CLR.W ioVRefNum(A0) ; no volRefNum <14>: not necessary
|
||
MOVE.L (A3),A1 ; point to gdevice
|
||
MOVE gdRefNum(A1),ioRefNum(A0) ; set device's refnum
|
||
_Control ,IMMED ; and issue the control call
|
||
|
||
MOVE (A4)+,D0 ; get size of param block
|
||
ADD D0,A4 ; skip param block
|
||
ChkNxtCtl DBRA D6,DoCtl ; loop for all control calls
|
||
|
||
ChkNxt DBRA D7,DoNxt ; loop for all screens in resource
|
||
|
||
MOVE.L MainDevice,a0
|
||
move.l a0,CrsrDevice ; cursor is now on main device, no longer on boot device
|
||
|
||
import GetDCtlEntry
|
||
|
||
subq #4,sp ; room for resulting DCE handle
|
||
move.l (a0),a0
|
||
move.w gdRefnum(a0),-(sp) ; get the refNum
|
||
jsr GetDCtlEntry
|
||
move.l (sp)+,a0 ; get handle to DCE
|
||
move.l (a0),a0 ; get pointer to DCE
|
||
move.l #0,d0 ; clear out D0
|
||
move.b dCtlSlot(a0),d0 ; get the slot number
|
||
_AttachVBL ; attach VBL to this slot
|
||
|
||
CLR.B CrsrBusy ; end of change
|
||
_AllocCursor ; make sure all cursor structs are updated
|
||
_ShowCursor ; now redisplay cursor
|
||
|
||
ScrnDone _ReleaseResource ; all done with the resource <19>: Done -> ScrnDone
|
||
|
||
; ••• 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
|
||
|
||
Move.l ROMBase,A0 ; Point to ROMBase with A0.
|
||
If Not ForROM Then
|
||
Cmp.w #$067C,8(A0) ; If we’re not running on a $67C
|
||
Bne GoHome ; ROM, then just go on.
|
||
Else
|
||
Cmp.w #$077D,8(A0) ; If we’re not running on a $77D
|
||
Bne GoHome ; ROM, then just go on.
|
||
Endif
|
||
|
||
; 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.
|
||
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.
|
||
|
||
GoHome
|
||
;+++ MOVEM.L (SP)+,D6-D7/A2-A4 ; restore work registers
|
||
MOVEM.L (SP)+,A0-A6/D0-D7 ; so we don’t screw up the boot process
|
||
UNLK A6
|
||
|
||
; ••• 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 ; save this for driver patching code below
|
||
|
||
;
|
||
; 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
|
||
If Not ForROM Then
|
||
BTST #dRAMBased,dCtlFlags+1(A4) ; test if this is a driver in ROM (Erickson overpatch) <7.0>
|
||
BEQ NxtSlot ; if so, then continue to next slot <7.0>
|
||
Endif
|
||
|
||
MOVE.L dCtlDriver(A4),A1 ; get handle to driver
|
||
MOVE.L (A1),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)+,A0-A6/D0-D7 ; so we don’t screw up the boot process
|
||
|
||
; ••• 6th INIT •••
|
||
;
|
||
if asINIT then
|
||
;
|
||
; 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.
|
||
;
|
||
; Note that for the new boot process this is no longer necessary.
|
||
;
|
||
|
||
PEA -4(A5)
|
||
_InitGraf
|
||
|
||
endif
|
||
|
||
; ••• 7th INIT •••
|
||
;
|
||
If Not ForROM Then
|
||
|
||
;---------------------------------------------------------------------
|
||
; Local variables, definitions, etc....
|
||
;---------------------------------------------------------------------
|
||
|
||
drHwDAFB Equ $001C ; Built-in Video Hardware ID for Macintosh Quadras 700/900/950.
|
||
DrvrVer950 Equ $0001 ; Version number of the Macintosh Quadra 950’s video driver.
|
||
|
||
badEntry Equ $38 ; Location of bad table entry in the Macintosh Quadra 950 driver.
|
||
|
||
; Straight from the Macintosh Quadra 950 ROM’s source code…
|
||
;
|
||
DAFBVidPrivates RECORD 0
|
||
saveBaseAddr DS.L 1 ; the screen base address (NOT ST corrected!)
|
||
saveScreenBase DS.L 1 ; ST corrected version of saveBaseAddr.
|
||
saveSQElPtr DS.L 1 ; the SQ element pointer (for _SIntRemove)
|
||
saveGammaPtr DS.L 1 ; the pointer to the Gamma correction table
|
||
saveGamDispPtr DS.L 1 ; the pointer to the Gamma block
|
||
saveVDACBase DS.L 1 ; the base addr of the VDAC
|
||
saveDAFBBase DS.L 1 ; the base addr of the DAFB
|
||
saveVidPtr DS.L 1 ; pointer to a big block of DAFB video parameters
|
||
GFlags DS.W 1 ; flags word
|
||
has16bppACDC Ds.b 1 ; true if AC842A is around
|
||
pageModeSet Ds.b 1 ; true if the pRam PageMode enable bit is set
|
||
saveMode DS.W 1 ; the current mode setting (in lo-byte)
|
||
saveMonID DS.W 1 ; monitor type ID (in lo-byte)
|
||
saveSlotId DS.W 1 ; spID of video sRsrc (hi-order byte only!)
|
||
DAFBVidPrivSize EQU *
|
||
ENDR
|
||
|
||
; Flags within GFlags word…
|
||
;
|
||
GrayFlag EQU 15 ; luminance mapped if GFlags(GrayFlag) = 1
|
||
IntDisFlag EQU 14 ; interrupts disabled if GFlags(IntFlag) =1
|
||
IsMono EQU 13 ; true if monochrome only display (Portrait/Kong)
|
||
UseSeq EQU 12 ; true if sequence mode SetEntries
|
||
UseTrans Equ 12 ; True if we’re supposed to translate 5-bit into 8 (DAFB 16bpp).
|
||
Is16 EQU 11 ; true if 16Mhz (Slow) CPU
|
||
IsSlow Equ 11 ; True if Slow CPU (for DAFB, 25Mhz is slow).
|
||
IsDirect EQU 10 ; true if direct video mode, else chunkyIndexed
|
||
PsuedoIndex EQU 9 ; true if SetEntries request was mapped to indexed from sequential
|
||
; (due to screen depth hardware requirements)
|
||
Has16bppSRsrc Equ 9 ; True if FifthVidMode is 16bpp instead of 32bpp (DAFB).
|
||
SyncOnGreen Equ 8 ; True if we’re supposed to put sync on green (DAFB).
|
||
|
||
|
||
bra.s PatchQuadra950Driver ; skip over the title
|
||
|
||
String Pascal
|
||
|
||
DAFBVideoTitle Dc.b '.Display_Video_Apple_DAFB'
|
||
Align 2
|
||
|
||
;---------------------------------------------------------------------
|
||
; Main
|
||
;---------------------------------------------------------------------
|
||
|
||
PatchQuadra950Driver
|
||
String AsIs
|
||
With SpBlock,DAFBVidPrivates
|
||
|
||
Quadra950SaveRegs Reg D4-D6 ; Define work registers.
|
||
|
||
If AsInit Then
|
||
Cmp.w #$3FFF,ROM85 ; If Color QuickDraw is not around,
|
||
Bne @ExitNow ; then just leave.
|
||
EndIf
|
||
|
||
Tst.l DeviceList ; If the device list is empty,
|
||
Beq @ExitNow ; then just leave.
|
||
|
||
Move.l DeviceList,A0 ; Get the DeviceList Handle.
|
||
Move.l (A0),A0 ; Make it a pointer.
|
||
Move.w gdRefNum(A0),D0 ; If there’s no driver, then
|
||
Beq @ExitNow ; we can’t do anything here.
|
||
|
||
Movem.l Quadra950SaveRegs,-(Sp) ; Save work registers.
|
||
Suba.w #spBlockSize,Sp ; Allocate SpBlock
|
||
|
||
; The shipping version of the Macintosh Quadra 950’s ROM (1.7F2) has a bug in the built-in video
|
||
; driver which prevents the DirectSetEntries call from working correctly when the attached display
|
||
; is put into 32 bit-per-pixel mode. To fix this problem, we just patch the bad table in place
|
||
; since it resides in the System heap.
|
||
;
|
||
Move.l Sp,A0 ; Get spBlock ptr into A0.
|
||
Clr.b spId(A0) ; Begin at id 0.
|
||
Clr.b spSlot(A0) ; We only care about Slot $0.
|
||
Clr.b spExtDev(A0) ; No external device.
|
||
Clr.b spTBMask(A0) ; No mask in search.
|
||
Move.w #catDisplay,spCategory(A0) ; Look for: Display,
|
||
Move.w #typVideo,spCType(A0) ; Video,
|
||
Move.w #drSwApple,spDrvrSW(A0) ; Apple,
|
||
Move.w #drHwDAFB,spDrvrHW(A0) ; DAFB.
|
||
Clr.l spParamData(A0) ; Look only for enabled sRsrcs.
|
||
Bset #foneslot,spParamData+3(A0) ; Limit search to this slot only.
|
||
_GetTypeSRsrc ; If built-in video is not enabled, then
|
||
Bne.s @AllDone ; just quit.
|
||
|
||
; We found the DAFB-based (Macintosh Quadra 700/900/950) built-in video in Slot $0.
|
||
;
|
||
Moveq #0,D5 ; Prepare D5.
|
||
Move.w spRefNum(A0),D5 ; Get the refNum.
|
||
Beq.s @AllDone ; If nil, then just leave (no driver).
|
||
Not.w D5 ; Convert the refNum into…
|
||
Lsl.w #2,D5 ; …a UTable index.
|
||
|
||
Add.l UTableBase,D5 ; Get a ptr to the AuxDCEHandle.
|
||
Move.l D5,A0 ; Get it into A0.
|
||
|
||
Move.l (A0),A0 ; Get the AuxDCEHandle.
|
||
Move.l (A0),A0 ; Get the AuxDCEPtr.
|
||
Move.l A0,D5 ; Save it for later.
|
||
|
||
move.w dCtlFlags(a0),d0 ; <27> Get driver flags
|
||
Move.l dCtlDriver(A0),A0 ; Get driver.
|
||
btst #dRAMBased,d0 ; <27> Check to see if dCtlDriver is a handle or a pointer
|
||
bz.s @gotDriverPointer ; <27> A ROM based driver means it’s a pointer
|
||
Move.l (A0),A0 ; Get ptr to driver.
|
||
@gotDriverPointer
|
||
Move.l A0,D6 ; Save it for later.
|
||
|
||
Moveq #0,D0 ; Prepare D0.
|
||
Lea drvrName(A0),A0 ; Point to the driver name.
|
||
Move.l A0,D4 ; Save it for later.
|
||
Move.b (A0)+,D0 ; Get its length.
|
||
Swap D0 ; Save it.
|
||
Lea DAFBVideoTitle,A1 ; Point to the driver name we want.
|
||
Move.b (A1)+,D0 ; Get its length.
|
||
_CmpString ; Compare the names.
|
||
Tst.w D0 ; If they are not equal, then we don’t know about
|
||
Bne.s @AllDone ; this DAFB driver, so just leave.
|
||
|
||
Moveq #0,D0 ; Re-prepare D0.
|
||
Move.l D4,A0 ; Re-point to the driver name.
|
||
Move.b (A0),D0 ; Get its length.
|
||
Addq #2,D0 ; Adjust offset to version field.
|
||
Bclr #0,D0 ; Adjust offset for word alignment.
|
||
Move.w (A0,D0),D4 ; Get the driver’s version number.
|
||
Cmp.w #DrvrVer950,D4 ; If this isn’t the Quadra 950’s driver version,
|
||
Bne.s @AllDone ; then just leave.
|
||
|
||
Adda.w D0,A0 ; Point to version part of driver name.
|
||
Move.l A0,D4 ; Save it for later.
|
||
|
||
; We found the Macintosh Quadra 950’s version of the DAFB driver.
|
||
;
|
||
Move.l D5,A0 ; Re-point to the AuxDCEPtr.
|
||
Move.l dCtlStorage(A0),A0 ; Get the Handle to DAFB private storage.
|
||
Move.l (A0),A0 ; Make it a pointer.
|
||
|
||
Btst #Has16bppSRsrc,GFlags(A0) ; If a 16bpp-capable sRsrc is not in use,
|
||
Beq.s @AllDone ; then just leave.
|
||
|
||
Move.l D6,A0 ; Re-point to the DAFB driver.
|
||
Move.b #$FF,badEntry(A0) ; Fix the bad table entry.
|
||
|
||
Move.l D4,A0 ; Re-point to the DAFB driver version number.
|
||
Move.w #DrvrVer950+1,(A0) ; Update it.
|
||
|
||
@AllDone
|
||
Add.w #spBlockSize,Sp ; Deallocate SpBlock.
|
||
Movem.l (Sp)+,Quadra950SaveRegs ; Restore work registers.
|
||
|
||
@ExitNow ; Outta here, dudes.
|
||
Rts
|
||
|
||
Endwith
|
||
|
||
Else
|
||
|
||
Rts
|
||
|
||
Endif
|
||
|
||
END
|