mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-29 07:29:15 +00:00
0ba83392d4
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
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
|