mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-12 20:29:12 +00:00
4283 lines
142 KiB
Plaintext
4283 lines
142 KiB
Plaintext
;
|
||
; File: JMFBDriver.a
|
||
;
|
||
; Contains: Driver for 4•8/8•24 Cards.
|
||
;
|
||
; Written by: Casey King/Mike Puckett
|
||
;
|
||
; Copyright: © 1986-1992 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; This file is used in these builds: Mac32
|
||
;
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM2> 11/18/92 SWC Changed SlotEqu.a->Slots.a and VideoEqu.a->Video.a.
|
||
; <1> 1/7/92 RB first checked in
|
||
; =============== Terror History ========================
|
||
;
|
||
; <4> 6/17/91 jmp Fixed a “memory leak” bug in SetGamma when changing the size of
|
||
; the current gamma table (i.e., form size 3 to 1, or vice-versa).
|
||
; Also, eliminated support for PAL displays & encoder boxes since
|
||
; the versions of the 4•8 & 8•24 cards that we’re patching out
|
||
; don’t have the sRsrcs.
|
||
; <3> 4/4/91 jmp Cleaned up the conditional assembly stuff (i.e., now use ForRom
|
||
; instead of PadForOverPatch).
|
||
; <2> 2/25/91 jmp Rolled in Casey’s latest changes.
|
||
; <1> 01/06/91 jmp Checked into TERROR ROM for the first time.
|
||
; <0> 11/19/90 jmp Formatted for use with TERROR ROM (as opposed to a
|
||
; declaration ROM).
|
||
|
||
|
||
;-------------------------------------------------------------------
|
||
;
|
||
; (c) Apple Computer, Inc. 1986-1990
|
||
; All rights reserved.
|
||
;
|
||
;-------------------------------------------------------------------
|
||
; File : ElmerDrvr.a
|
||
; Author : Casey King (based extensively on Bob and Blackjack)
|
||
;-------------------------------------------------------------------
|
||
; This file contains the video driver for use by the Macintosh
|
||
; OS. It is structured as a normal Mac slot device driver.
|
||
;
|
||
;-------------------------------------------------------------------
|
||
; Mod History :
|
||
; Refer to Projector change history for revision details
|
||
;-------------------------------------------------------------------
|
||
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
MACHINE MC68020
|
||
|
||
LOAD 'StandardEqu.d'
|
||
|
||
Print Off
|
||
INCLUDE 'ColorEqu.a'
|
||
INCLUDE 'ROMEqu.a'
|
||
INCLUDE 'Slots.a'
|
||
INCLUDE 'Video.a'
|
||
|
||
INCLUDE 'JMFBDepVideoEqu.a'
|
||
Print On
|
||
|
||
If ForRom Then
|
||
JMFBDrvr Proc Export
|
||
Else
|
||
VideoDrvr Main Export
|
||
Endif
|
||
|
||
;-------------------------------------------------------------------
|
||
; Equates for privates have been moved to efdepvideoequ.a since
|
||
; one of the values is used in SecondaryInit.a and cannont be
|
||
; forward referenced. They are duplicated here for convenience.
|
||
;-------------------------------------------------------------------
|
||
|
||
; This is device storage which is stored in the dCtlStorage field of the DCE.
|
||
|
||
; saveMode EQU 0 ; the current mode setting
|
||
; savePage EQU saveMode+2 ; the current page setting
|
||
; saveBaseAddr EQU savePage+2 ; the current base address
|
||
; saveSQElPtr EQU saveBaseAddr+4 ; the SQ element pointer (for _SIntRemove).
|
||
; saveGammaPtr EQU saveSQElPtr+4 ; the pointer to the Gamma correction table
|
||
; GFlags EQU saveGammaPtr+4 ; flags word
|
||
; saveVidParms EQU GFlags+2 ; pointer to video configuration data
|
||
; saveID EQU saveVidParms+4 ; saved sense value
|
||
; saveHardBase EQU saveID+2 ; hardware base address
|
||
; saveMonSense EQU saveHardBase+4 ; reformatted sense line combo from videoOpen
|
||
; moreGFlags EQU saveMonSense+2
|
||
; saveGammaPtrHead EQU moreGFlags+2
|
||
; dCtlSize EQU saveGammaPtrHead+4 ; size of dCtlStorage
|
||
|
||
; Flags within GFlags word
|
||
|
||
; GrayFlag EQU 15 ; luminance mapped if GFlags(GrayFlag) = 1
|
||
; IntDisFlag EQU 14 ; interrupts disabled if GFlags(IntFlag) =1
|
||
; RAM512KFlag EQU 13 ; 512K vidRAM if GFlags(RAM512K) = 1
|
||
; MonoFlag EQU 12 ; true if monochrome monitor
|
||
; Interlaced EQU 11 ; true if 12MHz NTSC mode
|
||
; DirectModeFlag EQU 10 ; true if direct mode (24 BPP) otherwise indexed
|
||
; BigScreen EQU 9 ; true if Kong or Portrait, false otherwise
|
||
; sRsrc32Bit EQU 8 ; true if the spID indicates it's a 32 bit sRsrc
|
||
|
||
; Flags within moreGFlags word
|
||
|
||
; UnderScanFlag EQU 15
|
||
; ConvOnFlag EQU 14
|
||
; PALFlag EQU 13
|
||
; NationalFlag EQU 12
|
||
;-------------------------------------------------------------------
|
||
; Video Driver Header
|
||
;-------------------------------------------------------------------
|
||
|
||
|
||
VidDrvr DC.W $4C00 ; ctl,status,needsLock
|
||
DC.W 0,0,0 ; not an ornament
|
||
|
||
; Entry point offset table
|
||
|
||
DC.W VideoOpen-VidDrvr ; open routine
|
||
DC.W VidDrvr-VidDrvr ; no prime
|
||
DC.W VideoCtl-VidDrvr ; control
|
||
DC.W VideoStatus-VidDrvr ; status
|
||
DC.W VideoClose-VidDrvr ; close
|
||
|
||
|
||
STRING Pascal
|
||
VideoTitle DC.B '.Display_Video_Apple_MDC'
|
||
STRING ASIS
|
||
ALIGN ; make sure we're aligned
|
||
DC.W CurJMFBDrvrVersion ;
|
||
|
||
;
|
||
; Here are the Elmer miscellaneous data and hardware parameters for the 4 different monitors.
|
||
; The interlaced monitor has 2 sets of parameters (no convolution and convolution).
|
||
;
|
||
; The miscellaneous data contains page size, rowbytes, and number of scanlines for all allowable
|
||
; modes of operation for a particular monitor.
|
||
;
|
||
; The six lines of hardware parameters data correspond to the initialization setup sequence
|
||
; summarized below.
|
||
;
|
||
; Line 1 - CLUT PBCR
|
||
; Line 2 - JMFB CSR, JMFB load divisor register, JMFB base register,JMFB row long words register
|
||
; Line 3 - Programable clock generator registers (interlaced convolved only)
|
||
; Line 4 - Stopwatch horizontal timing control parameters (see Stopwatch spec)
|
||
; Line 5 - Stopwatch vertical timing control parameters (see Stopwatch spec)
|
||
; Line 6 - Stopwatch composite timing control parameters (see Stopwatch spec)
|
||
;
|
||
; Note that the ROM can be built for the prototype VRAM or production VRAM. This ROM can now be
|
||
; used independent of whether the National or Endeavor clock generators are present. The implication
|
||
; of this is that the first JMFB register is setup in the data tables below for the National Part,
|
||
; (i.e. the PIXSEL1 bit = 1 for Kong and 0 for all other cases). In JMFBSetDepth, a check is made to
|
||
; see which clock part we're using and if it's Endeavor, PIXSEL1 will be set to 1. Otherwise the
|
||
; National setup would result in reseting Endeavor (to 10MHz) except for the Kong.
|
||
;
|
||
|
||
Mode100Data
|
||
Pages1024 DC.B OBMPages100B,TBMPages100B,FBMPages100B,EBMPages100B,TFBMPages100B
|
||
Pages512 DC.B OBMPages100A,TBMPages100A,FBMPages100A,EBMPages100A,TFBMPages100A
|
||
RowBites DC.W OBM100RB,TBM100RB,FBM100RB,EBM100RB,TFBM100RB
|
||
Height DC.W defmBounds_B100
|
||
|
||
Mode100
|
||
OBM100Parms DC.W $00C0
|
||
IF ProtoVRAM THEN
|
||
DC.W $2003,$00F8,defmBaseOffsetBS>>5,OBM100RB/4
|
||
ELSE
|
||
DC.W $2002,$00F8,defmBaseOffsetBS>>5,OBM100RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0090,$011E,$0016,$001E,$0012
|
||
DC.W $0003,$0000,$06CC,$004E,$0006,$0006
|
||
DC.W $0000,$014c
|
||
|
||
TBM100Parms DC.W $00C8
|
||
IF ProtoVRAM THEN
|
||
DC.W $2003,$00FC,defmBaseOffsetBS>>5,TBM100RB/4
|
||
ELSE
|
||
DC.W $2002,$00FC,defmBaseOffsetBS>>5,TBM100RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0090,$011E,$001A,$001E,$000E
|
||
DC.W $0003,$0000,$06CC,$004E,$0006,$0006
|
||
DC.W $0000,$014c
|
||
|
||
FBM100Parms DC.W $00D0
|
||
IF ProtoVRAM THEN
|
||
DC.W $2003,$00FE,defmBaseOffsetBS>>5,FBM100RB/4
|
||
ELSE
|
||
DC.W $2002,$00FE,defmBaseOffsetBS>>5,FBM100RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0090,$011E,$001C,$001E,$000C
|
||
DC.W $0003,$0000,$06CC,$004E,$0006,$0006
|
||
DC.W $0000,$014c
|
||
|
||
EBM100Parms DC.W $00D8
|
||
IF ProtoVRAM THEN
|
||
DC.W $2003,$00FF,defmBaseOffsetBS>>5,EBM100RB/4
|
||
ELSE
|
||
DC.W $2002,$00FF,defmBaseOffsetBS>>5,EBM100RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0090,$011E,$001D,$001E,$000B
|
||
DC.W $0003,$0000,$06CC,$004E,$0006,$0006
|
||
DC.W $0000,$014c
|
||
|
||
Mode57Data
|
||
DC.B OBMPages57B,TBMPages57B,FBMPages57B,EBMPages57B,TFBMPages57B
|
||
DC.B OBMPages57A,TBMPages57A,FBMPages57A,EBMPages57A,TFBMPages57A
|
||
DC.W OBM57RB,TBM57RB,FBM57RB,EBM57RB,TFBM57RB
|
||
DC.W defmBounds_B57
|
||
|
||
Mode57
|
||
OBM57Parms DC.W $00A0
|
||
IF ProtoVRAM THEN
|
||
DC.W $0003,$00F0,defmBaseOffsetBS>>5,OBM57RB/4
|
||
ELSE
|
||
DC.W $0002,$00F0,defmBaseOffsetBS>>5,OBM57RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$00A0,$013E,$0012,$0026,$0022
|
||
DC.W $0003,$0000,$06CC,$0054,$0006,$0006
|
||
DC.W $0000,$0178
|
||
|
||
TBM57Parms DC.W $00A8
|
||
IF ProtoVRAM THEN
|
||
DC.W $0003,$00F8,defmBaseOffsetBS>>5,TBM57RB/4
|
||
ELSE
|
||
DC.W $0002,$00F8,defmBaseOffsetBS>>5,TBM57RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$00A0,$013E,$001A,$0026,$001A
|
||
DC.W $0003,$0000,$06CC,$0054,$0006,$0006
|
||
DC.W $0000,$0178
|
||
|
||
FBM57Parms DC.W $00B0
|
||
IF ProtoVRAM THEN
|
||
DC.W $0003,$00FC,defmBaseOffsetBS>>5,FBM57RB/4
|
||
ELSE
|
||
DC.W $0002,$00FC,defmBaseOffsetBS>>5,FBM57RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$00A0,$013E,$001E,$0026,$0016
|
||
DC.W $0003,$0000,$06CC,$0054,$0006,$0006
|
||
DC.W $0000,$0178
|
||
|
||
EBM57Parms DC.W $00B8
|
||
IF ProtoVRAM THEN
|
||
DC.W $0003,$00FE,defmBaseOffsetBS>>5,EBM57RB/4
|
||
ELSE
|
||
DC.W $0002,$00FE,defmBaseOffsetBS>>5,EBM57RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$00A0,$013E,$0020,$0026,$0014
|
||
DC.W $0003,$0000,$06CC,$0054,$0006,$0006
|
||
DC.W $0000,$0178
|
||
|
||
Mode30Data
|
||
DC.B OBMPages30B,TBMPages30B,FBMPages30B,EBMPages30B,TFBMPages30B
|
||
DC.B OBMPages30A,TBMPages30A,FBMPages30A,EBMPages30A,TFBMPages30A
|
||
DC.W OBM30RB,TBM30RB,FBM30RB,EBM30RB,TFBM30RB
|
||
DC.W defmBounds_B30
|
||
|
||
Mode30
|
||
OBM30Parms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00E0,defmBaseOffset>>5,OBM30RB/4
|
||
ELSE
|
||
DC.W $0082,$00E0,defmBaseOffset>>5,OBM30RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$013A,$027E,$0034,$003E,$0068
|
||
DC.W $0003,$0000,$03C0,$004E,$0006,$0006
|
||
DC.W $0004,$0320
|
||
|
||
TBM30Parms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00F0,defmBaseOffset>>5,TBM30RB/4
|
||
ELSE
|
||
DC.W $0082,$00F0,defmBaseOffset>>5,TBM30RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$012A,$027E,$0044,$003E,$0058
|
||
DC.W $0003,$0000,$03C0,$004E,$0006,$0006
|
||
DC.W $0004,$0320
|
||
|
||
FBM30Parms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00F8,defmBaseOffset>>5,FBM30RB/4
|
||
ELSE
|
||
DC.W $0082,$00F8,defmBaseOffset>>5,FBM30RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0122,$027E,$004C,$003E,$0050
|
||
DC.W $0003,$0000,$03C0,$004E,$0006,$0006
|
||
DC.W $0004,$0320
|
||
|
||
EBM30Parms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00FC,defmBaseOffset>>5,EBM30RB/4
|
||
ELSE
|
||
DC.W $0082,$00FC,defmBaseOffset>>5,EBM30RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$011E,$027E,$0050,$003E,$004C
|
||
DC.W $0003,$0000,$03C0,$004E,$0006,$0006
|
||
DC.W $0004,$0320
|
||
|
||
TFBM30Parms
|
||
IF ProtoVRAM THEN
|
||
DC.W $009A
|
||
DC.W $0087,$00FF,(defmBaseOffset*3/4)>>5>>1,(TFBM30RB*3/4/4)>>1
|
||
ELSE
|
||
DC.W $009A
|
||
DC.W $0086,$00FF,(defmBaseOffset*3/4)>>5>>1,(TFBM30RB*3/4/4)>>1
|
||
ENDIF
|
||
DC.W $0003,$0000,$0140,$027E,$0053,$003E,$0049
|
||
DC.W $0003,$0000,$03C0,$004E,$0006,$0006
|
||
DC.W $0004,$0320
|
||
|
||
Mode16Data
|
||
DC.B OBMPages16B,TBMPages16B,FBMPages16B,EBMPages16B,TFBMPages16B
|
||
DC.B OBMPages16A,TBMPages16A,FBMPages16A,EBMPages16A,TFBMPages16A
|
||
DC.W OBM16RB,TBM16RB,FBM16RB,EBM16RB,TFBM16RB
|
||
DC.W defmBounds_B16
|
||
|
||
Mode16
|
||
OBM16Parms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00E0,defmBaseOffset>>5,OBM16RB/4
|
||
ELSE
|
||
DC.W $0082,$00E0,defmBaseOffset>>5,OBM16RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0100,$01FE,$024,$001E,$0038
|
||
DC.W $0003,$0000,$0300,$0026,$0006,$0002
|
||
DC.W $0004,$0260
|
||
|
||
TBM16Parms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00F0,defmBaseOffset>>5,TBM16RB/4
|
||
ELSE
|
||
DC.W $0082,$00F0,defmBaseOffset>>5,TBM16RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0100,$01FE,$034,$001E,$0028
|
||
DC.W $0003,$0000,$0300,$0026,$0006,$0002
|
||
DC.W $0004,$0260
|
||
|
||
FBM16Parms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00F8,defmBaseOffset>>5,FBM16RB/4
|
||
ELSE
|
||
DC.W $0082,$00F8,defmBaseOffset>>5,FBM16RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0100,$01FE,$03C,$001E,$0020
|
||
DC.W $0003,$0000,$0300,$0026,$0006,$0002
|
||
DC.W $0004,$0260
|
||
|
||
EBM16Parms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $0083,$00FC,defmBaseOffset>>5,EBM16RB/4
|
||
ELSE
|
||
DC.W $0082,$00FC,defmBaseOffset>>5,EBM16RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0100,$01FE,$040,$001E,$001C
|
||
DC.W $0003,$0000,$0300,$0026,$0006,$0002
|
||
DC.W $0004,$0260
|
||
|
||
TFBM16Parms
|
||
IF ProtoVRAM THEN
|
||
DC.W $009A
|
||
DC.W $0087,$00FF,(defmBaseOffset*3/4)>>5>>1,(TFBM16RB*3/4/4)>>1
|
||
ELSE
|
||
DC.W $009A
|
||
DC.W $0086,$00FF,(defmBaseOffset*3/4)>>5>>1,(TFBM16RB*3/4/4)>>1
|
||
ENDIF
|
||
DC.W $0003,$0000,$0100,$01FE,$043,$001E,$0019
|
||
DC.W $0003,$0000,$0300,$0026,$0006,$0002
|
||
DC.W $0004,$0260
|
||
|
||
Mode14Data
|
||
DC.B InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt
|
||
DC.B OBMPages14A,TBMPages14A,FBMPages14A,EBMPages14A,TFBMPages14A
|
||
DC.W OBM14RB,TBM14RB,FBM14RB,EBM14RB,TFBM14RB
|
||
DC.W defmBounds_B14
|
||
|
||
;
|
||
; There is an interesting twist to all of the PAL timing parameters and it is in the vertical
|
||
; timing section. Since PAL doesn't have a half line at the top of one field and a half
|
||
; line at the bottom of the other field, but rather has a full line at the top of both
|
||
; fields and half lines at both bottoms, we have to adjust for this in Stopwatch. The way
|
||
; that this happens is a half line is taken of from active video and added to the back
|
||
; porch and then Stopwatch is reset as it normally is. Hey it works and it's late!
|
||
;
|
||
Mode14
|
||
|
||
OBM14Parms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00E0,defmBaseOffset12>>5,OBM14RB/4
|
||
ELSE
|
||
DC.W $8112,$00E0,defmBaseOffset12>>5,OBM14RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0160,$02FE,$0031,$0043,$0036
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
TBM14Parms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F0,defmBaseOffset12>>5,TBM14RB/4
|
||
ELSE
|
||
DC.W $8112,$00F0,defmBaseOffset12>>5,TBM14RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0150,$02FE,$0041,$0043,$0026
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
FBM14Parms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F8,defmBaseOffset12>>5,FBM14RB/4
|
||
ELSE
|
||
DC.W $8112,$00F8,defmBaseOffset12>>5,FBM14RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0148,$02FE,$0049,$0043,$001E
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
EBM14Parms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00FC,defmBaseOffset12>>5,EBM14RB/4
|
||
ELSE
|
||
DC.W $8112,$00FC,defmBaseOffset12>>5,EBM14RB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0144,$02FE,$004D,$0043,$001A
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
Mode14CData
|
||
DC.B OBMPages14CB,TBMPages14CB,FBMPages14CB,EBMPages14CB,TFBMPages14CB
|
||
DC.B InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt
|
||
DC.W OBM14CRB,TBM14CRB,FBM14CRB,EBM14CRB,TFBM14CRB
|
||
DC.W defmBounds_B14
|
||
Mode14C
|
||
|
||
OBM14CParms DC.W $00C1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0160,$02FE,$0031,$0043,$0036
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
TBM14CParms DC.W $00C9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0150,$02FE,$0041,$0043,$0026
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
FBM14CParms DC.W $00D1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0148,$02FE,$0049,$0043,$001E
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
EBM14CParms DC.W $00D9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0144,$02FE,$004D,$0043,$001A
|
||
DC.W $0003,$0000,$023F,$0028,$0005,$0005
|
||
DC.W $005E,$0193
|
||
;
|
||
; 24 bpp is not an allowable mode for overscan PAL, so no table here!
|
||
;
|
||
|
||
Mode14uData
|
||
DC.B InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt
|
||
DC.B OBMPages14Au,TBMPages14Au,FBMPages14Au,EBMPages14Au,TFBMPages14Au
|
||
DC.W OBM14uRB,TBM14uRB,FBM14uRB,EBM14uRB,TFBM14uRB
|
||
DC.W defmBounds_B14u
|
||
|
||
Mode14u
|
||
|
||
OBM14uParms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00E0,defmBaseOffset12>>5,OBM14uRB/4
|
||
ELSE
|
||
DC.W $8112,$00E0,defmBaseOffset12>>5,OBM14uRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0120,$027e,$0071,$0043,$0076
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
TBM14uParms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F0,defmBaseOffset12>>5,TBM14uRB/4
|
||
ELSE
|
||
DC.W $8112,$00F0,defmBaseOffset12>>5,TBM14uRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0110,$027e,$0081,$0043,$0066
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
FBM14uParms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F8,defmBaseOffset12>>5,FBM14uRB/4
|
||
ELSE
|
||
DC.W $8112,$00F8,defmBaseOffset12>>5,FBM14uRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0108,$027e,$0089,$0043,$005e
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
EBM14uParms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00FC,defmBaseOffset1212>>5,EBM14uRB/4
|
||
ELSE
|
||
DC.W $8112,$00FC,defmBaseOffset12>>5,EBM14uRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0104,$027e,$008d,$0043,$005a
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
Mode14CuData
|
||
DC.B OBMPages14CB,TBMPages14CB,FBMPages14CB,EBMPages14CB,TFBMPages14Bu
|
||
DC.B InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt,InvalPageCnt
|
||
DC.W OBM14CRB,TBM14CRB,FBM14CRB,EBM14CRB,TFBM14uRB
|
||
DC.W defmBounds_B14u
|
||
Mode14Cu
|
||
|
||
OBM14CuParms DC.W $00C1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0120,$027e,$0071,$0043,$0076
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
TBM14CuParms DC.W $00C9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0110,$027e,$0081,$0043,$0066
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
FBM14CuParms DC.W $00D1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0108,$027e,$0089,$0043,$005e
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
EBM14CuParms DC.W $00D9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM14CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM14CRB/4
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$01,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0104,$027e,$008d,$0043,$005a
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
;
|
||
; Note that the 24 BPP convolution parameters are identical to the 24 BPP no convolution parameters
|
||
; since convolution cannot be performed in 24 BPP mode. The no convolution parameters will be used
|
||
; when only one bank of vRAM is present on the card and the convolution parameters will be used
|
||
; when the second bank is present.
|
||
;
|
||
TFBM14CuParms DC.W $009A
|
||
IF ProtoVRAM THEN
|
||
DC.W $8117,$00FF,$0000,(TFBM14uRB*3/4/4)>>1
|
||
ELSE
|
||
DC.W $8116,$00FF,$0000,(TFBM14uRB*3/4/4)>>1
|
||
ENDIF
|
||
DC.W $0000,$0000,$0000
|
||
DC.B $0D,$09,$01,$00,$06,$04,$00,$01
|
||
DC.B $01,$03,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0101,$027e,$0090,$0043,$0057
|
||
DC.W $0003,$0000,$020f,$0058,$0005,$0005
|
||
DC.W $005E,$0193
|
||
|
||
Mode12Data
|
||
DC.B OBMPages12B,TBMPages12B,FBMPages12B,EBMPages12B,TFBMPages12B
|
||
DC.B OBMPages12A,TBMPages12A,FBMPages12A,EBMPages12A,TFBMPages12A
|
||
DC.W OBM12CRB,TBM12CRB,FBM12CRB,EBM12CRB,TFBM12CRB
|
||
DC.W defmBounds_B12
|
||
|
||
Mode12
|
||
|
||
; There is a bug with the 1 BPP ntsc parameters since we can't meet the horizontal timing requirements!!
|
||
|
||
OBM12Parms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00E0,defmbaseOffset12>>5,OBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00E0,defmbaseOffset12>>5,OBM12CRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0136,$027E,$0012,$003A,$003a
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
TBM12Parms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F0,defmbaseOffset12>>5,TBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00F0,defmbaseOffset12>>5,TBM12CRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$0126,$027E,$0022,$003A,$002a
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
FBM12Parms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F8,defmbaseOffset12>>5,FBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00F8,defmbaseOffset12>>5,FBM12CRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$011e,$027E,$002a,$003A,$0022
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
EBM12Parms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00FC,defmbaseOffset12>>5,EBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00FC,defmbaseOffset12>>5,EBM12CRB/4
|
||
ENDIF
|
||
DC.W $0003,$0000,$011a,$027E,$002e,$003A,$001e
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
Mode12CData
|
||
DC.B OBMPages12CB,TBMPages12CB,FBMPages12CB,EBMPages12CB,TFBMPages12B
|
||
DC.B OBMPages12CA,TBMPages12CA,FBMPages12CA,EBMPages12CA,TFBMPages12CA
|
||
DC.W OBM12CRB,TBM12CRB,FBM12CRB,EBM12CRB,TFBM12CRB
|
||
DC.W defmBounds_B12C
|
||
Mode12C
|
||
|
||
OBM12CParms DC.W $00C1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM12CRB/4
|
||
ENDIF
|
||
BeginEndeavor
|
||
DC.W $006C,$00B0,$0000
|
||
EndEndeavor
|
||
Natl DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
EndNatl
|
||
DC.W $0003,$0000,$0136,$027E,$0012,$003A,$003A
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
TBM12CParms DC.W $00C9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$0126,$027E,$0022,$003A,$002A
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
FBM12CParms DC.W $00D1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$011e,$027E,$002A,$003A,$0022
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
EBM12CParms DC.W $00D9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$011a,$027E,$002E,$003A,$001E
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
;
|
||
; Note that the 24 BPP convolution parameters are identical to the 24 BPP no convolution parameters
|
||
; since convolution cannot be performed in 24 BPP mode. The no convolution parameters will be used
|
||
; when only one bank of vRAM is present on the card and the convolution parameters will be used
|
||
; when the second bank is present.
|
||
;
|
||
TFBM12CParms DC.W $009A
|
||
IF ProtoVRAM THEN
|
||
DC.W $8117,$00FF,$0000,(TFBM12RB*3/4/4)>>1
|
||
ELSE
|
||
DC.W $8116,$00FF,$0000,(TFBM12RB*3/4/4)>>1
|
||
ENDIF
|
||
DC.W $001B,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$04,$0D,$06,$00,$01,$00,$00
|
||
DC.W $0003,$0000,$011d,$027E,$002B,$003A,$0021
|
||
DC.W $0003,$0000,$01E0,$0021,$0006,$0006
|
||
DC.W $006E,$014a
|
||
|
||
Mode12uData
|
||
DC.B OBMPages12B,TBMPages12B,FBMPages12B,EBMPages12B,TFBMPages12B
|
||
DC.B OBMPages12A,TBMPages12A,FBMPages12A,EBMPages12A,TFBMPages12A
|
||
DC.W OBM12CRB,TBM12CRB,FBM12CRB,EBM12CRB,TFBM12CRB
|
||
DC.W defmBounds_B12u
|
||
|
||
Mode12u
|
||
|
||
OBM12uParms DC.W $0080
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00E0,defmbaseOffset12>>5,OBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00E0,defmbaseOffset12>>5,OBM12CRB/4
|
||
ENDIF
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00f4,$01fe,$0054,$003A,$0078
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
TBM12uParms DC.W $0088
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F0,defmbaseOffset12>>5,TBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00F0,defmbaseOffset12>>5,TBM12CRB/4
|
||
ENDIF
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00e4,$01fe,$0064,$003A,$0068
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
FBM12uParms DC.W $0090
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00F8,defmbaseOffset12>>5,FBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00F8,defmbaseOffset12>>5,FBM12CRB/4
|
||
ENDIF
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00dc,$01fe,$006c,$003A,$0060
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
EBM12uParms DC.W $0098
|
||
IF ProtoVRAM THEN
|
||
DC.W $8113,$00FC,defmbaseOffset12>>5,EBM12CRB/4
|
||
ELSE
|
||
DC.W $8112,$00FC,defmbaseOffset12>>5,EBM12CRB/4
|
||
ENDIF
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00d8,$01fe,$0070,$003A,$005c
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
Mode12CuData
|
||
DC.B OBMPages12CB,TBMPages12CB,FBMPages12CB,EBMPages12CB,TFBMPages12B
|
||
DC.B OBMPages12CA,TBMPages12CA,FBMPages12CA,EBMPages12CA,TFBMPages12CA
|
||
DC.W OBM12CRB,TBM12CRB,FBM12CRB,EBM12CRB,TFBM12CRB
|
||
DC.W defmBounds_B12u
|
||
Mode12Cu
|
||
|
||
OBM12CuParms DC.W $00C1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00F8,(defmbaseOffset12-convBOfix)>>5,OBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00f4,$01fe,$0054,$003A,$0078
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
TBM12CuParms DC.W $00C9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FC,(defmbaseOffset12-convBOfix)>>5,TBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00e4,$01fe,$0064,$003A,$0068
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
FBM12CuParms DC.W $00D1
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FE,(defmbaseOffset12-convBOfix)>>5,FBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00dc,$01fe,$006c,$003A,$0060
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
EBM12CuParms DC.W $00D9
|
||
IF ProtoVRAM THEN
|
||
DC.W $8133,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM12CRB/4
|
||
ELSE
|
||
DC.W $8132,$00FF,(defmbaseOffset12-convBOfix)>>5,EBM12CRB/4
|
||
ENDIF
|
||
DC.W $006C,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$02,$0D,$06,$00,$01,$00,$00
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00d8,$01fe,$0070,$003A,$005c
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
;
|
||
; Note that the 24 BPP convolution parameters are identical to the 24 BPP no convolution parameters
|
||
; since convolution cannot be performed in 24 BPP mode. The no convolution parameters will be used
|
||
; when only one bank of vRAM is present on the card and the convolution parameters will be used
|
||
; when the second bank is present.
|
||
;
|
||
TFBM12CuParms DC.W $009A
|
||
IF ProtoVRAM THEN
|
||
DC.W $8117,$00FF,$0000,(TFBM12RB*3/4/4)>>1
|
||
ELSE
|
||
DC.W $8116,$00FF,$0000,(TFBM12RB*3/4/4)>>1
|
||
ENDIF
|
||
DC.W $001B,$00B0,$0000
|
||
DC.B $0c,$01,$02,$00,$07,$03,$00,$00
|
||
DC.B $00,$04,$0D,$06,$00,$01,$00,$00
|
||
; Based on lab measurements the delta value to fp/bp is $8 rather than $20.
|
||
DC.W $0003,$0000,$00d5,$01fe,$0073,$003A,$0059
|
||
DC.W $0003,$0000,$01B0,$0051,$0006,$0006
|
||
DC.W $006E,$014A
|
||
|
||
;
|
||
; Here are the offsets to each of the various data fields. The size of all miscellaneous data blocks
|
||
; is the same.
|
||
;
|
||
|
||
D_Pages1024 EQU Pages1024-Mode100
|
||
D_Pages512 EQU Pages512-Mode100
|
||
D_RowBytes EQU RowBites-Mode100
|
||
D_Height EQU Height-Mode100
|
||
D_OBP EQU OBM100Parms-Mode100
|
||
D_TBP EQU TBM100Parms-Mode100
|
||
D_FBP EQU FBM100Parms-Mode100
|
||
D_EBP EQU EBM100Parms-Mode100
|
||
D_TFBP EQU TFBM30Parms-Mode30 ; Use Mode30 here since Mode100 doesn't do 24 BPP
|
||
D_ClockParams EQU EndNatl-BeginEndeavor
|
||
D_Endeavor EQU EndEndeavor-BeginEndeavor
|
||
D_Natl EQU EndNatl-Natl
|
||
|
||
;
|
||
; CountTbl is the number of entries to change in each mode, set up to be indexed
|
||
; via the modeID.
|
||
;
|
||
|
||
CountTbl DC.B $01,$03,$0F,$FF,$FF
|
||
DC.B 'Software by Casey King, Hardware by James Lundblad and Mohammed Sriti'
|
||
|
||
|
||
ALIGN 2 ; correct odd alignment
|
||
|
||
*******************************************************************
|
||
*
|
||
* VideoOpen allocates private storage for the device in the DCE and locks
|
||
* it down for perpetuity. Also, install the interrupt handler and enable
|
||
* the interrupts.
|
||
*
|
||
* VideoOpen is broken up into 7 main steps:
|
||
*
|
||
* 1. Allocate private storage and point to it with dCtlStorage from DCE.
|
||
* 2. Form 32 bit base address and store in privates.
|
||
* 3. Determine whether it's a 24 bit or 32 bit sRsrc and store in privates.
|
||
* 4. Size VRAM and store in privates.
|
||
* 5. Read sense lines from hw and ...
|
||
* a. Save a ptr to the appropriate hw setup params.
|
||
* b. Calc and save the BigScreen, GrayFlag, MonoFlag, Interlaced, PALFlag, and underScan flags.
|
||
* c. If connected to interlaced monitor, determine whether to ntsc or pal and to oscan or uscan
|
||
* 6. Get and install the interrupt handler.
|
||
* 7. Load the correct gamma table as a f(monitor).
|
||
*
|
||
* Called by:
|
||
*
|
||
* Normally only Mac OS and A/UX.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _ResrvMem, _NewHandle, _HLock, _StripAddress, _SwapMMUMode, _sReadPRAMRec,
|
||
* EnableVGuts
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A0 = param block pointer
|
||
* A1 = DCE pointer
|
||
*
|
||
* Output
|
||
* D0 = error code.
|
||
*
|
||
* Locally used
|
||
* D0 = scratch
|
||
* D1 = scratch
|
||
* D3 = saves the spID from the AuxDCE
|
||
*
|
||
* A0 = points to the cards base address
|
||
* = later points to the hw setup params
|
||
* = later as a ptr to a parameter block
|
||
* A3 = pointer to private storage
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
WITH VDPageInfo,SlotIntQElement,SEBlock,spBlock
|
||
|
||
VideoOpen
|
||
|
||
|
||
;
|
||
; Allocate private storage (since block is CLEAR, GFlags are zeroed) and get
|
||
; a pointer to it in A3
|
||
;
|
||
|
||
MOVEQ #dCtlSize,D0 ; get size of parameters
|
||
_ResrvMem ,SYS ; make room as low as possible
|
||
MOVEQ #dCtlSize,D0 ; get size of parameters
|
||
_NewHandle ,SYS,CLEAR ; get some memory for private storage
|
||
BNE OpError ; => return an error in open
|
||
MOVE.L A0,dCtlStorage(A1) ; save returned handle in DCE
|
||
_HLock ; and lock it down
|
||
|
||
MOVE.L (A0),D0 ; get a pointer to it
|
||
_StripAddress ; strip it since we'll use it in 32 bit addressing
|
||
MOVE.L D0,A3 ; and put it in A3
|
||
|
||
;
|
||
; form the 32 bit base address in A0 and save in saveHardBase(A3). We
|
||
; cannot be assured that dctlDevBase(A1) contains the correct 32 bit
|
||
; address since a 24 bit sRsrc may be the active one if the new version of
|
||
; the slot manager is not present.
|
||
;
|
||
MOVE.L #$F0000000,D1
|
||
MOVE.B dCtlSlot(A1),D0
|
||
BFINS D0,D1{4:4}
|
||
MOVE.L D1,A0
|
||
MOVE.L A0,saveHardBase(A3) ; save this in privates for the interrupt handler
|
||
|
||
;
|
||
; determine if we're using a National or Endeavor Clock
|
||
;
|
||
MOVE.L A0,-(SP) ; save A0 as it is used later
|
||
SUBA #spBlockSize,SP ; get slot param block
|
||
MOVE.L SP,A0 ; save pointer to it in A0
|
||
MOVE.B D0,spSlot(A0) ; put slot in slot param block
|
||
SUBA #sizesPRAMRec,SP ; get PRAM record
|
||
MOVE.L SP,spResult(A0) ; set up a pointer to result
|
||
_SReadPRAMRec
|
||
|
||
CMP.B #0,SavedClockType(SP) ; check for Endeavor
|
||
BEQ.S EndClkCheck
|
||
BSET #NationalFlag,moreGFlags(A3)
|
||
EndClkCheck
|
||
ADDA #sizesPRAMRec+spBlockSize,SP ; flush param blocks
|
||
MOVE.L (SP)+,A0 ; restore A0
|
||
|
||
; determine if the installed sResource is 24 bit (0) or 32 bit (1) from the AuxDCE record
|
||
; - Refer to OMD software ERS for definition of all spID bits
|
||
;
|
||
MOVE.B dCtlSlotID(A1),D3 ; get the current sResource ID
|
||
BTST #fSRsrc24Bit,D3 ; check for b4 state (24 bit=1, 32 bit=0)
|
||
BNE.S @sizeVRAM
|
||
BSET #sRsrc32bit,GFlags(A3) ; set the 32bit sRsrc bit in GFlags
|
||
|
||
;
|
||
; determine the memory size of the active sRsrc from the AuxDCE spID and set private storage bit
|
||
;
|
||
|
||
@sizeVRAM
|
||
BTST #fSRsrcXMemBit,D3
|
||
BNE.S @monSense
|
||
BSET #RAM512KFlag,GFlags(A3) ; and set 512K vRAM flag (this is why we strip address)
|
||
|
||
;
|
||
; read the monitor sense lines to determine the configuration. Use this info
|
||
; to pick up a pointer to the parameter table for this hardware mode and
|
||
; save this pointer off in private storage. Since we had to get through
|
||
; primary init, the monitor sense line must be valid. The monitor sense
|
||
; combination is read from the JMFB CSR which is located at zero offset
|
||
; from the JMFB control space. Note that we can't use the sRsrc ID from
|
||
; the AuxDCE here because not all bits are saved in the spID. To support
|
||
; the RGB Kong and Portrait in the future we must go back out to the
|
||
; card and get the whole sense!
|
||
;
|
||
; Note that we're providing minimal functionality with the Sarnoff breakout
|
||
; box. We use the extended sense scheme to support both the Sarnoff NTSC mode
|
||
; and the Sarnoff PAL mode. At this time there is no support for the monitor
|
||
; connected to the auxillary DB15 connector on Sarnoff.
|
||
;
|
||
|
||
@monSense
|
||
MOVEQ #true32b,D0 ; change to 32 bit addressing to get
|
||
_SwapMMUMode ; sense lines
|
||
MOVE D0,-(SP) ; save the past mode on the stack
|
||
|
||
MOVE.L #JMFB,D0 ; get offset in register
|
||
BFEXTU (A0,D0.L){20:3},D1 ; get the state of the sense lines
|
||
|
||
CMP.B #NoSense,D1 ; check for no sense
|
||
BNE.S @DoNext ; if we get a valid sense, go on
|
||
|
||
MOVE.L D0,D1 ; setup for GetXtndSense (so we use same interface as pinit)
|
||
MOVE.L A1,-(SP) ; setup for GetXtndSense (save A1)
|
||
MOVE.L A0,A1 ; setup for GetXtndSense (so we use same interface as pinit)
|
||
BSR GetXtndSense ; go see if we see an xtended sense
|
||
MOVE.L (SP)+,A1 ; restore A1
|
||
|
||
CMP.B #Sarnoff,D0 ; we only understand sarnoff
|
||
|
||
If ForROM Then
|
||
Bne.s @NoConnect ; if not Sarnoff (NTSC), then no connect
|
||
Else
|
||
BNE.S @TryPAL ; if not Sarnoff (NTSC), then try for PAL
|
||
EndIf
|
||
|
||
MOVE.B #_NTSC_,D1 ; force sarnoff to ntsc timing for now
|
||
BRA.S @SwapBack ; we have a current mode so go on
|
||
|
||
If Not ForROM Then
|
||
@TryPAL CMP.B #PAL,D0 ; check for PAL xtnded sense
|
||
BNE.S @TryPAL2
|
||
MOVE.B #rPAL,D1
|
||
BRA.S @SwapBack
|
||
@TryPAL2 CMP.b #PALmonitor,D0 ; check for PAL monitor xtnded sense
|
||
BNE.S @NoConnect ; if not found then do no connect
|
||
MOVE.B #rPAL,D1
|
||
BRA.S @SwapBack
|
||
EndIf
|
||
|
||
@NoConnect MOVE.B #0,D1 ; no valid xtnd sense so do no connect
|
||
BRA.S @SwapBack ;
|
||
@DoNext
|
||
CMP.B #RGBKong,D1 ; check to see if its an RGBKong
|
||
BNE.S @SwapBack ; if not skip and go on
|
||
MOVE.B #rRGBKong,D1 ; if it is, reformat to maintain convention
|
||
|
||
; All done with 32 bit addressing needs so go back into 24 bit addressing.
|
||
|
||
@SwapBack MOVE (SP)+,D0 ; restore old addr mode into D0
|
||
_SwapMMUMode
|
||
|
||
BTST #fSRsrcBigScrnBit,D1 ; check for Kong or Portrait monitor (bit 0 = 1)
|
||
BEQ.S @colorMon ; if its other (0), then branch
|
||
BSET #BigScreen,GFlags(A3) ; while we are here not that it's a big screen!
|
||
BCLR #fSRsrcRGBBit,D1 ; b2 is not significant in Portrait or Kong sRsrcs so get rid of it
|
||
BNE.S @colorMon ; remember BCLR tests before CLR, so check for color
|
||
BSET #GrayFlag,GFlags(A3)
|
||
BSET #MonoFlag,GFlags(A3)
|
||
|
||
@colorMon
|
||
MOVE.L D1,D0 ; use D0 for the jump tbl, since we want to keep D1 intact for interlaced selection.
|
||
CMP.W #7,D0 ; range check the monitor id
|
||
BHI OpError ; Error, out of bounds
|
||
MOVE.W VOpenJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine
|
||
JMP VOpenJumpTbl(PC,D0.W) ; GOTO the proper routine
|
||
|
||
VOpenJumpTbl
|
||
DC.W VOPAL-VOpenJumpTbl ; $00 => PAL monitor (use common code)
|
||
DC.W VOPortrait-VOpenJumpTbl ; $01 => B/W Portrait (no difference between RGB and BW)
|
||
DC.W VORubik-VOpenJumpTbl ; $02 => Rubik monitor
|
||
DC.W VOKong-VOpenJumpTbl ; $03 => B/W Kong (no difference between RGB and BW)
|
||
DC.W VONTSC-VOpenJumpTbl ; $04 => NTSC monitor (use common code)
|
||
DC.W VOPortrait-VOpenJumpTbl ; $05 => RGB Portrait (no difference between RGB and BW)
|
||
DC.W VOStandard-VOpenJumpTbl ; $06 => Standard monitor
|
||
DC.W VOKong-VOpenJumpTbl ; $07 => RGB Kong (no difference between RGB and BW)
|
||
|
||
VOStandard LEA Mode30,A0 ; else it better be standard size monitor
|
||
BRA SaveIt ; branch to the setup code
|
||
|
||
VORubik LEA Mode16,A0 ; point to the parameters
|
||
BRA SaveIt ; branch to the setup code
|
||
|
||
VOKong LEA Mode100,A0 ; point to the parameters
|
||
BRA SaveIt ; branch to the setup code
|
||
|
||
VOPortrait LEA Mode57,A0 ; point to the parameters
|
||
BRA SaveIt ; branch to the setup code
|
||
|
||
VOPAL BSET #PALFlag,moreGFlags(A3) ; set PALFlag for PAL
|
||
BRA.S VOInterlaced ; go to common code
|
||
|
||
VONTSC BCLR #PALFlag,moreGFlags(A3) ; set PALFlag for NTSC (not PAL)
|
||
|
||
VOInterlaced
|
||
BSET #Interlaced,GFlags(A3) ; set 12MHz mode flag
|
||
|
||
;
|
||
; if we're doing ntsc, check the underscan/overscan bit in the sRsrc ID (again from AuxDCE)
|
||
;
|
||
|
||
BTST #fSRsrcOscanBit,D3 ; test the state of the underscan (0) / overscan (1) flag
|
||
BNE.S testRAMFlag
|
||
BSET #underScanFlag,moreGFlags(A3) ; it was 0 so set it for underscan
|
||
|
||
testRAMFlag
|
||
BTST #RAM512KFlag,GFlags(A3) ; test to see if we have one bank (no convol) or two (convol)
|
||
BEQ.S useNTSCcon ; if two banks then its convolution capable so use Mode12C
|
||
|
||
BTST #underScanFlag,moreGFlags(A3) ; test to see if we're underscan or overscan
|
||
BNE.S useNTSCu ; if 1 then underscan so branch
|
||
CMP.B #_NTSC_,D1
|
||
BEQ.S @useNTSC
|
||
LEA Mode14,A0
|
||
BRA.S SaveIt
|
||
@useNTSC
|
||
LEA Mode12,A0 ; otherwise point to the overscan interlace flicker ones
|
||
|
||
BRA.S SaveIt
|
||
|
||
useNTSCu
|
||
CMP.B #_NTSC_,D1
|
||
BEQ.S @useNTSC
|
||
LEA Mode14u,A0
|
||
BRA.S SaveIt
|
||
@useNTSC
|
||
LEA Mode12u,A0 ; point to the underscan interlace flicker params
|
||
BRA.S SaveIt
|
||
|
||
useNTSCcon
|
||
BSET #convOnFlag,moreGFlags(A3) ; set if we're in a convolution mode
|
||
BTST #underScanFlag,moreGFlags(A3) ; test to see if we're underscan or overscan
|
||
BNE.S useConvUscan ; if 1 then underscan so branch
|
||
CMP.B #_NTSC_,D1
|
||
BEQ.S @useNTSC
|
||
LEA Mode14C,A0
|
||
BRA.S SaveIt
|
||
@useNTSC
|
||
LEA Mode12C,A0 ; must have both vRAM banks and be overscanning so use Oscan convolution
|
||
BRA.S SaveIt
|
||
|
||
useConvUscan
|
||
CMP.B #_NTSC_,D1
|
||
BEQ.S @useNTSC
|
||
LEA Mode14Cu,A0
|
||
BRA.S SaveIt
|
||
@useNTSC
|
||
LEA Mode12Cu,A0 ; we have 2 banks and doing underscan so use Uscan convolution
|
||
|
||
SaveIt MOVE.L A0,saveVidParms(A3) ; and save it for later
|
||
MOVE.W D1,saveMonSense(A3) ; also save the LS 3 bits of reformatted monitor value
|
||
;
|
||
; clear a couple of bits in D3 since it will be used to get the right gamma table in a second
|
||
;
|
||
BCLR #fSRsrcOscanBit,D3 ; clear the underscan/overscan bit if set
|
||
BCLR #fSRsrc24Bit,D3 ; clear the 24b/32b sRsrc bit if set
|
||
BCLR #fSRsrcXMemBit,D3 ; clear the 512k/1024k bit if set
|
||
|
||
SUBA #spBlockSize,SP ; make room for the spBlock (done here so I can conveniently flush operror1)
|
||
;
|
||
; Get and install the interrupt handler. Call the SetInterrupt utility code to do
|
||
; this. This utility also starts the interrupts going. If there is an error
|
||
; condition, EnableVGuts returns with Z-bit cleared.
|
||
|
||
MOVEQ #sqHDSize,D0 ; allocate a slot queue element
|
||
_NewPtr ,SYS,CLEAR ; get it from system heap cleared
|
||
BNE OpError1 ; if not allocated, return bad
|
||
MOVE.L A0,saveSQElPtr(A3) ; save the queue element for eventual disposal
|
||
|
||
BSR EnableVGuts ; do it
|
||
BNE OpError1 ;
|
||
;
|
||
; load the default gamma table from the slot resource list
|
||
;
|
||
MOVE.L SP,A0 ; get pointer to block in A0
|
||
MOVE.B dCtlSlot(A1),spSlot(A0) ; copy the slot number
|
||
CLR.W spID(A0) ; zero the spID.B,spExtDev.B
|
||
CLR.B spTBMask(A0) ; we're going for an exact match to this card
|
||
MOVE.W #CatDisplay,spCategory(A0) ; look for this card
|
||
MOVE.W #TypVideo,spCType(A0) ;
|
||
MOVE.W #DrSwApple,spDrvrSW(A0) ;
|
||
MOVE.W #DrHwJMFB,spDrvrHW(A0) ;
|
||
CLR.B spHWDev(A0) ; ????
|
||
_sNextTypesRsrc ; get the spsPointer
|
||
|
||
MOVE.B #sGammaDir,spID(A0) ; look for the gamma directory
|
||
_sFindStruct ; get that baby
|
||
|
||
MOVE.B #128,spID(A0) ; get the default gamma table, (always 128)
|
||
_sGetBlock ; we can use this since we want a ptr in sysheap
|
||
BNE.S DoLinear ; if we can't find it, use linear one!
|
||
|
||
;
|
||
; skip over header
|
||
;
|
||
|
||
MOVE.L spResult(A0),A0 ; point to head of the block
|
||
MOVE.L A0,saveGammaPtrHead(A3) ; save head of the GammaPtr for disposal
|
||
ADDA #2,A0 ; skip resID
|
||
@Name TST.B (A0)+ ; skip over gamma name
|
||
BNE.S @Name ;
|
||
ADDA #1,A0 ; word align pointer
|
||
MOVE.L A0,D0 ; get in d-reg
|
||
AND.L #$FFFFFFFE,D0 ; round it
|
||
|
||
MOVE.L D0,saveGammaPtr(A3) ; put it in private storage
|
||
BRA.S OpenDone
|
||
;
|
||
; build a linear default gamma table
|
||
;
|
||
|
||
DoLinear MOVEQ.L #gFormulaData,D0 ; get gamma table header size
|
||
ADD #256,D0 ; and one byte per element for data
|
||
_NewPtr ,SYS,CLEAR ; and clear it too
|
||
BNE.S OpError1 ; die if allocation failed
|
||
|
||
MOVE.L A0,saveGammaPtrHead(A3) ; save head of the GammaPtr for disposal
|
||
MOVE.L A0,saveGammaPtr(A3) ; save a pointer to it
|
||
MOVE.W #DrHwJMFB,gType(A0) ;
|
||
MOVE.W #1,gChanCnt(A0) ;
|
||
MOVE.W #256,gDataCnt(A0) ;
|
||
MOVE.W #8,gDataWidth(A0) ; eight bits/value
|
||
ADD #gFormulaData,A0 ; point to data table
|
||
MOVE.W #$FF,D0 ; put linear data in table
|
||
MOVEQ #0,D1
|
||
@Loop MOVE.B D1,(A0)+ ; write the value
|
||
ADDQ #1,D1
|
||
DBRA D0,@Loop ; for all positions
|
||
|
||
;
|
||
; all done!
|
||
;
|
||
|
||
OpenDone
|
||
ADDA #spBlockSize,SP ; release the slot manager block
|
||
MOVEQ #0,D0 ; no error
|
||
EndOpen RTS ; return
|
||
|
||
OpError1 MOVE.L dCtlStorage(A1),A0 ; dispose of private storage
|
||
_DisposHandle ; do it
|
||
ADDA #spBlockSize,SP ; get rid of spBlock
|
||
|
||
OpError MOVE.L #OpenErr,D0 ; say can't open driver
|
||
BRA.S EndOpen
|
||
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* Video Driver Control Call Handler. There are ten calls- the nine
|
||
* calls from the Bob driver and a new one that allows alteration of the
|
||
* CLUT when operating as a direct device (24 bpp for us).
|
||
*
|
||
* (0) Reset (VAR mode, page: INTEGER; VAR BaseAddr: Ptr);
|
||
* (1) KillIO
|
||
* (2) SetMode(mode, page: INTEGER; VAR BaseAddr: Ptr);
|
||
* (3) SetEntries ( Table: Ptr; Start,Count : integer );
|
||
* (4) SetGamma ( Table : Ptr );
|
||
* (5) GrayPage (page);
|
||
* (6) SetGray (csMode = 0 for color, 1 for gray)
|
||
* (7) SetInterrupt ( csMode = 0 for enable, 1 for disable)
|
||
* (8) DirectSetEntries ( Table: Ptr; Start,Count : integer );
|
||
* (9) SetDefaultMode (mode);
|
||
*
|
||
* The Control Call Handler is broken up into 4 main steps:
|
||
*
|
||
* 1. Strip the upper byte of the DCE pointer (A1). It can be used in 32 bit mode.
|
||
* 2. Get the pointer to private storage in A3 and strip the upper byte.
|
||
* 3. Get the pointer to the csParams in A2.
|
||
* 4. Get the csCode and dispatch the call to the right control call.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Device Manager
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _StripAddress, appropriate control call
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A0 = param block pointer
|
||
* A1 = DCE pointer
|
||
*
|
||
* Output:
|
||
* D0 = error code
|
||
*
|
||
* Locally used:
|
||
* D0 = scratch, then returns error code as output
|
||
*
|
||
* A2 = cs parameters (ie. A2 <- csParam(A0)) (must be preserved)
|
||
* A3 = ptr to private storage (passed to all control calls)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
VideoCtl MOVE.L A0,-(SP) ; save work registers (A0 is saved because it is used by ExitDrvr)
|
||
|
||
MOVE.L A1,D0 ; need to clean up the pointer to the DCE
|
||
_StripAddress ; because it is used in 32 bit mode later
|
||
MOVE.L D0,A1 ; in DisableVGuts
|
||
|
||
MOVE.L dCtlStorage(A1),A3
|
||
MOVE.L (A3),D0 ; get pointer to private storage
|
||
_StripAddress ; strip the hi byte for 32 bit addressing
|
||
MOVE.L D0,A3 ; move back into A3
|
||
|
||
MOVE.L csParam(A0),D0 ; A2 <- Ptr to control parameters
|
||
_StripAddress ; strip the hi byte for 32 bit addressing
|
||
MOVE.L D0,A2 ; put into A2
|
||
|
||
MOVE.W csCode(A0),D0 ; get the opCode
|
||
|
||
CMP.W #9,D0 ; IF csCode NOT IN [0..10] THEN
|
||
BHI.S CtlBad ; Error, csCode out of bounds
|
||
MOVE.W CtlJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine
|
||
JMP CtlJumpTbl(PC,D0.W) ; GOTO the proper routine
|
||
|
||
CtlJumpTbl DC.W VidReset-CtlJumpTbl ; $00 => VidReset
|
||
DC.W CtlGood-CtlJumpTbl ; $01 => CtlGood
|
||
DC.W SetVidMode-CtlJumpTbl ; $02 => SetVidMode
|
||
DC.W SetEntries-CtlJumpTbl ; $03 => SetEntries
|
||
DC.W SetGamma-CtlJumpTbl ; $04 => SetGamma
|
||
DC.W GrayPage-CtlJumpTbl ; $05 => GrayPage
|
||
DC.W SetGray-CtlJumpTbl ; $06 => SetGray
|
||
DC.W SetInterrupt-CtlJumpTbl ; $07 => SetInterrupt
|
||
DC.W DirectSetEntries-CtlJumpTbl ; $08 => DirectSetEntries
|
||
DC.W SetDefaultMode-CtlJumpTbl ; $09 => SetDefault mode
|
||
|
||
CtlBad MOVEQ #controlErr,D0 ; else say we don't do this one
|
||
BRA.S CtlDone ; and return
|
||
|
||
CtlGood MOVEQ #noErr,D0 ; return no error
|
||
|
||
CtlDone MOVE.L (SP)+,A0 ; restore registers.
|
||
BRA ExitDrvr
|
||
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* VidReset resets the card to its default mode (1bpp).
|
||
*
|
||
* VidReset is broken up into 1 main steps:
|
||
*
|
||
* 1. Reset the card to 1 bpp mode.
|
||
*
|
||
* Called by:
|
||
*
|
||
* No one that I know of today.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* JMFBSetDepth, JMFBSetPage, GrayScreen
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* csMode(A2) - new mode (1bpp)
|
||
* csPage(A2) - new page (0)
|
||
* csBaseAddr(A2) - base address
|
||
* saveMode(A3) - new mode saved in privates
|
||
*
|
||
* Locally used:
|
||
* D1 - used to pass the requested depth to JMFBSetDepth
|
||
* D4 - used to pass the requested page to JMFBSetPage
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
VidReset
|
||
|
||
MOVE #FirstVidMode,csMode(A2) ; return default mode
|
||
MOVE #FirstVidMode,saveMode(A3) ; remember firstVidMode as the requested mode
|
||
MOVE #1,D1 ; get default depth in D1
|
||
MOVEQ #0,D4 ; get page in D4 (used since SwapMMUMode uses D0)
|
||
MOVE D4,csPage(A2) ; return the page
|
||
BSR JMFBSetDepth ; set the depth from D1
|
||
BSR JMFBSetPage ; set the page from D4
|
||
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
|
||
BSR GrayScreen ; paint the screen gray
|
||
BRA.S CtlGood ; => no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* SetVidMode sets the card to the specified mode and page. If either
|
||
* is invalid, returns badMode error. If the card is already set to
|
||
* the specified mode, then do nothing.
|
||
*
|
||
* SetVidMode is broken up into 7 main steps:
|
||
*
|
||
* 1. Check the requested mode against allowable modes and exit if bad.
|
||
* 2. Check the requested page number against max pages and exit if bad.
|
||
* 3. If the requested mode is the same as the current mode then exit.
|
||
* 4. Get the gamma corrected value for half intensity gray.
|
||
* 5. Set the entire CLUT to the value in above step prior to changing modes.
|
||
* 6. Call JMFBSetDepth to change modes.
|
||
* 7. Call JMFBSetPage to change pages (will reset the hw base address)
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* ChkMode, ChkPage, _SwapMMUMode, WaitVSync, JMFBSetDepth, JMFBSetPage
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* csBaseAddr(A2) - base address of frame buffer
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* D1 - used to pass requested mode to ChkMode (comes back as depth)
|
||
* - later used to pass depth to JMFBSetDepth
|
||
* D2 - scratch
|
||
* D3 - used to hold the gamma corrected half intensity value for gray
|
||
* D4 - used to pass requested page to ChkMode
|
||
*
|
||
* A0 - used to point to CLUT address space
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
SetVidMode
|
||
|
||
MOVE.W csMode(A2),D1 ; D1 = mode
|
||
BSR ChkMode ; check mode, map to depth in D1 (1,2,4,8, or 24)
|
||
BNE.S CtlBad ; => not a valid mode
|
||
|
||
MOVE.W csPage(A2),D0 ; D0 = page
|
||
MOVE.W D0,D4 ; use d4 as the parameter since SwapMMU mode uses D0
|
||
BSR ChkPage ; check page
|
||
BNE.S CtlBad ; => not a valid page
|
||
|
||
; Only set the mode if it has changed
|
||
; JMFBSetDepth and JMFBSetPage update the saved data in the dCtlStorage
|
||
|
||
SetEm
|
||
MOVE.W csMode(A2),D2 ; D2 = mode
|
||
CMP saveMode(A3),D2 ; has the mode changed?
|
||
BEQ.S ModeOK1 ; => no, check the page
|
||
|
||
; remember the newly requested mode
|
||
|
||
MOVE.W csMode(A2),saveMode(A3) ; remember requested mode
|
||
|
||
; set the entire color table to gray before switching to avoid screen anomalies
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma data structure
|
||
MOVE GFormulaSize(A0),D3 ; get the size of formula data
|
||
MOVE.W GDataCnt(A0),D2 ; get number of gamma entries
|
||
LSR.W #1,D2 ; divide by two to find midpoint
|
||
LEA GFormulaData(A0),A0 ; point to formula data
|
||
ADD D3,A0 ; first correction table starts here
|
||
MOVE.B (A0,D2),D3 ; get corrected gray from middle of red table
|
||
|
||
MOVE.L saveHardBase(A3),A0 ; A0 <- base address of device.
|
||
ADD.L #CLUT+CLUTDataReg,A0 ; add offset to color table data register for later
|
||
|
||
; switch to 32 bit addressing here since all calls to WaitVSync must be done in 32 bit mode, and
|
||
; we also need to be in 32 bit mode to get up to the CLUT.
|
||
|
||
MOVEQ #true32b,D0 ; we'll be addr in 32 bit so get ready
|
||
_SwapMMUMode ; swap to 32 bit mode
|
||
MOVE D0,-(SP) ; save past addr mode on stack
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
|
||
BSR WaitVSync ; wait for next blanking period (A0 saved)
|
||
|
||
MOVE.L #$00,CLUTAddrReg-CLUTDataReg(A0) ; hit that baby (all writes to Trident hw must be longs!)
|
||
|
||
MOVE.W #$FF,D2 ; get count
|
||
@Repeat MOVE.L D3,(A0) ; put red (all writes to Trident hw must be longs!)
|
||
MOVE.L D3,(A0) ; put green (all writes to Trident hw must be longs!)
|
||
MOVE.L D3,(A0) ; put blue (all writes to Trident hw must be longs!)
|
||
DBRA D2,@Repeat ;
|
||
|
||
MOVE (SP)+,SR ; restore the status reg
|
||
|
||
MOVE (SP)+,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode ; swap back to previous addr mode
|
||
|
||
BSR JMFBSetDepth ; set the depth, get rowbytes
|
||
ModeOK1
|
||
BSR JMFBSetPage ; set the page
|
||
|
||
NoChange MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
|
||
BRA CtlGood ; => return no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* The SetEntries call has two modes. In SEQUENCE mode, csCount entries are changed
|
||
* in the CLUT, starting at csStart. In INDEX mode, csCount entries are
|
||
* installed into the CLUT at the positions specified by their .value fields.
|
||
* This mode is selected by passing csStart = -1. In both cases, entries are
|
||
* range-checked to the dynamic range of the video mode (bits/pixel).
|
||
*
|
||
* This call has common code that is shared between SetEntries and DirectSetEntries.
|
||
*
|
||
* Before the entries in the CLUT are actually set up, they are first gamma corrected.
|
||
* The gamma table has the following structure:
|
||
*
|
||
* record GammaTable of
|
||
* gVersion : integer (0 for all current cards)
|
||
* gType : integer (holds drHWId to identify board the table was measured for)
|
||
* gFormulaSize : integer (size of gFormulaData in bytes, 0 for Apple cards)
|
||
* gChanCnt : integer (number of gamma tables in gData, 1 for Apple cards)
|
||
* gDataCnt : integer (number of elements in each channels correction table, 2**gDataWidth)
|
||
* gDataWidth : integer (width of each element in a channels correction table)
|
||
* gFormulaData : array [0..gFormulaSize] of byte (not used for Apple cards)
|
||
* gData : array [0..gDataCnt] of byte (correction table data)
|
||
* end
|
||
*
|
||
* SetEntries is broken up into 4 main steps:
|
||
*
|
||
* 1. If there is no requested color table or if we're in 24 bpp mode, then exit.
|
||
* 2. Get the current gamma table.
|
||
* 3. Construct a gamma corrected and hw specific color table on the stack.
|
||
* 4. Write to the hardware in requested mode ( for mono BigScreens, use 1 channel only).
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _StripAddress, GetGammaCSpec, _SwapMMUMode, WaitVSync
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csTable -> table of colorSpecs (not colortable)
|
||
* csStart -> where to start setting, or -1
|
||
* csCount -> # of entries to change
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* D1 - scratch
|
||
* D2 - holds the reformatted cSpec that is hw dependent
|
||
* D3 - scratch
|
||
* D4 - Size of the stack color table buffer
|
||
* D5 - GFlags word from private storage
|
||
* D6 - holds the max number of entries to change as a f(mode)
|
||
* - later used to save SR state
|
||
* D7 - holds the csStart parameter
|
||
*
|
||
* A0 - scratch
|
||
* A3 - points to the color spec table
|
||
* A4 - pointer to gamma red table
|
||
* A5 - pointer to gamma red table
|
||
* A6 - pointer to gamma red table
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
SetEntries
|
||
MOVE.L csTable(A2),D0 ; Check for a nil pointer
|
||
BEQ CtlBad
|
||
|
||
BTST #DirectModeFlag,GFlags(A3) ; SetEntries is not allowed for direct devices
|
||
BNE CtlBad ; Indexed Mode (0) and Direct Mode (1)
|
||
|
||
SetEntCom
|
||
MOVEM.L A4-A6/D4-D7,-(SP) ; save registers for gamma (D4 saved by VideoCtl)
|
||
|
||
MOVE.W GFlags(A3),D5 ; get GFlags word in D5 to be used to determine gray mode
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma table data structures
|
||
LEA GFormulaData(A0),A4 ; get a pointer to the first gammatable
|
||
ADDA GFormulaSize(A0),A4 ;
|
||
|
||
MOVE.L A4,A5 ; get default pointer to green data (assuming gChanCnt=1)
|
||
MOVE.L A4,A6 ; get default pointer to blue data (assuming gChanCnt=1)
|
||
|
||
MOVE GDataWidth(A0),D7 ; get width of each entry in bits to be used later
|
||
|
||
CMP #1,GChanCnt(A0) ; if only only one table, we're set
|
||
BEQ.S OneTbl ; => just one table
|
||
|
||
MOVE GDataCnt(A0),D0 ; get # entries in table
|
||
MOVE D7,D1 ; copy it to goof around
|
||
ADD #7,D1 ; round to nearest byte
|
||
LSR #3,D1 ; get bytes per entry
|
||
MULU D1,D0 ; get size of table in bytes
|
||
|
||
ADDA D0,A5 ; calc base of green (red base + D0)
|
||
ADDA D0,A6 ; calc base of blue
|
||
ADDA D0,A6 ; calc base of blue (red base + D0 + D0)
|
||
|
||
OneTbl
|
||
|
||
; get the maximum number of entries, zero based from a convenient table
|
||
|
||
MOVE.W saveMode(A3),D1 ; get the current video mode
|
||
SUB.W #FirstVidMode,D1 ; convert to index
|
||
LEA CountTbl,A3 ; point to little table of counts
|
||
MOVEQ #0,D6 ; clear the entire long (only need word tho!)
|
||
MOVE.B (A3,D1),D6 ; pick the zero-based byte
|
||
|
||
;
|
||
; allocate a temporary color table on the stack. We'll pre-process all the entries that will
|
||
; change here so we can hit the hardware as quickly as possible.
|
||
;
|
||
|
||
MOVE.W csCount(A2),D3 ; get the number of entries to change
|
||
CMP.W D6,D3 ; is it in the allowable range?
|
||
BHI BadExit ; if outside, then exit w/bad result
|
||
MOVE.W csStart(A2),D0 ; get the start number to range check
|
||
ADDQ.W #1,D0
|
||
BMI BadExit ; if csStart < -1 then it's out of range
|
||
|
||
MOVE.L SP,D1 ; get stack
|
||
MOVE.L D1,D0 ; copy stack
|
||
NEG D0 ; get amount to subtract
|
||
AND #$3,D0 ; get low bits
|
||
BEQ.S StkOk ; => already long aligned
|
||
SUB D0,SP ; else make stack long aligned
|
||
StkOk MOVE.L D1,-(SP) ; save original stack on stack
|
||
|
||
MOVE.L D3,D4 ; make a copy of the table size (zero-based!)
|
||
ADDQ #1,D4 ; make it a counting number
|
||
ASL #2,D4 ; multiply times 4 (always less than 1024)
|
||
SUB.W D4,SP ; allocate the buffer
|
||
|
||
;
|
||
; construct the stack version of the color table. This table includes all translations and
|
||
; inversion required to drive the hardware. It looks like a color table, but each of the
|
||
; four components is only eight bits (rather than 16).
|
||
;
|
||
|
||
MOVE.L SP,A0 ; copy the stack buffer pointer
|
||
MOVE.L csTable(A2),D0 ; get colorSpec pointer in D0
|
||
_StripAddress ; clear upper byte for 32 bit mode
|
||
MOVE.L D0,A3 ; put it in A3
|
||
|
||
@a BSR GetGammaCSpec ; go get a reformatted colorSpec in D2
|
||
MOVE.L D2,(A0)+ ; put the BBGGRRVV colorSpec in stack table
|
||
DBRA D3,@a ; do it for all cSpecArray records
|
||
|
||
; Hit the hardware as quick as possible!
|
||
|
||
MOVE.W csCount(A2),D3 ; get the number of entries to change again
|
||
MOVE.L dCtlStorage(A1),A3
|
||
MOVE.L (A3),D0 ; get pointer to private storage again
|
||
_StripAddress ; strip address for 32 bit addressing
|
||
MOVE.L D0,A3
|
||
|
||
MOVEQ #true32b,D0 ; we'll be addr in 32 bit so get ready
|
||
_SwapMMUMode ; swap over from 24 bit to 32 bit mode
|
||
MOVE D0,D1 ; save past addr mode for later (can't use stack here!)
|
||
|
||
MOVE.W SR,D6 ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
ROR.W #8,D6 ; roll to get the 3 interrupt bits in low byte
|
||
AND.B D6,D0 ; D0 now holds current interrupt level
|
||
ROL.W #8,D6 ; restore D6 since it holds the sr to be restored
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
BSR WaitVSync ; wait for next VSync before writing to CLUT
|
||
|
||
MOVE.L saveHardBase(A3),A3 ; point to the base address of device
|
||
ADD.L #CLUT+CLUTDataReg,A3 ; add offset to get to the data register
|
||
|
||
MOVE.W csStart(A2),D7 ; get the starting position (also indicates mode)
|
||
BPL.S SeqWrite ; do sequence mode if its sequence
|
||
|
||
|
||
|
||
IndexWrite MOVE.L (SP)+,D2 ; get a stack table reformatted colorSpec
|
||
MOVE.L D2,CLUTAddrReg-CLUTDataReg(A3) ; write the addr to be modified to CLUT addr register
|
||
LSR.L #8,D2 ; get red CLUT data in low byte of D2
|
||
IF NOT ProtoVRAM THEN
|
||
BTST #MonoFlag,D5 ; if it's a monochrome monitor, only turn on 1 gun (red)
|
||
BEQ.S @iAllThree ; if it's a color monitor (0), all 3 guns are active
|
||
ELSE
|
||
BRA.S @iAllThree ; for the prototype always turn all 3 guns on
|
||
ENDIF
|
||
MOVE.L #0,(A3) ; write black (off) to red
|
||
MOVE.L #0,(A3) ; write black (off) to green
|
||
MOVE.L D2,(A3) ; write blue to CLUT data register
|
||
BRA.S @iJustBlue
|
||
|
||
@iAllThree
|
||
MOVE.L D2,(A3) ; write red to CLUT data register
|
||
LSR.L #8,D2 ; get green CLUT data in low byte of D2
|
||
MOVE.L D2,(A3) ; write green to CLUT data register
|
||
LSR.L #8,D2 ; get blue CLUT data in low byte of D2
|
||
MOVE.L D2,(A3) ; write blue to CLUT data register
|
||
|
||
@iJustBlue DBRA D3,IndexWrite ; do for all (remember CLUT address autoincrements after blue)
|
||
BRA.S SEDone ; all done with index mode so exit
|
||
|
||
SeqWrite MOVE.L D7,CLUTAddrReg-CLUTDataReg(A3) ; write the start addr to be modified to CLUT addr register
|
||
|
||
@b MOVE.L (SP)+,D2 ; get a stack table reformatted colorSpec
|
||
LSR.L #8,D2 ; since sequence mode doesn't care about value field, flush byte
|
||
BTST #MonoFlag,D5 ; If it's a monochrome monitor, only turn on 1 gun (red)
|
||
BEQ.S @allThree ; if it's a color monitor (0), all 3 guns are active
|
||
MOVE.L #0,(A3) ; write black (off) to red
|
||
MOVE.L #0,(A3) ; write black (off) to green
|
||
MOVE.L D2,(A3) ; write blue to CLUT data register
|
||
BRA.S @JustBlue
|
||
|
||
@allThree
|
||
MOVE.L D2,(A3) ; write red to CLUT data register
|
||
LSR.L #8,D2 ; get green CLUT data in low byte of D2
|
||
MOVE.L D2,(A3) ; write green to CLUT data register
|
||
LSR.L #8,D2 ; get blue CLUT data in low byte of D2
|
||
MOVE.L D2,(A3) ; write blue to CLUT data register
|
||
|
||
@JustBlue DBRA D3,@b ; do for all (remember CLUT address autoincrements after blue)
|
||
|
||
; All done!
|
||
|
||
SEDone
|
||
MOVE D1,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode ; swap from 32 bit to 24 bit addressing
|
||
MOVE D6,SR ; restore status register
|
||
MOVE.L (SP)+,SP ; restore stack pointer
|
||
MOVEM.L (SP)+,A4-A6/D4-D7 ; restore registers
|
||
BRA CtlGood ; return O-Tay!
|
||
|
||
BadExit MOVEM.L (SP)+,A4-A6/D4-D7 ; restore registers
|
||
BRA CtlBad ; return an error code
|
||
|
||
|
||
GetGammaCSpec
|
||
*******************************************************************
|
||
*
|
||
* GetGammaCSpec takes a Color Manager format colorSpec (see IM-V), performs weighted luminance
|
||
* mapping to gray scales if necessary, performs gamma correction and returns in D2 a reformatted
|
||
* colorSpec in the form BBGGRRVV where:
|
||
*
|
||
* BB = gamma corrected blue CLUT data
|
||
* GG = gamma corrected green CLUT data
|
||
* RR = gamma corrected red CLUT data
|
||
* VV = 8 bit colorSpec value data (CLUT address for RGB triplet only used in index mode)
|
||
*
|
||
* GetGammaCSpec is broken up into 4 main steps:
|
||
*
|
||
* 1. Get the raw 16 bit values from the Mac OS color model and put into working registers
|
||
* 2. Perform luminance mapping if gray mode is set (R=30%, G=59%, B=11%)
|
||
* 3. Convert 16 bit format to 8 bit format to play with our hardware. The value field is
|
||
* right justified in a word, and R,G,B fields are left justified. (See IM-V137)
|
||
* 4. Perform gamma correction by indexing into appropriate R,G, or B gamma table, and pack
|
||
* reformatted colorSpec into a 32 bit register, D2, in the form BBGGRRVV.
|
||
*
|
||
* Called by:
|
||
*
|
||
* SetEntries
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
*
|
||
* D5 - GFlags word where MSB identifies state of grayflag
|
||
* D7 - contains width of CLUT channel
|
||
*
|
||
* A3 - points to colorSpec table
|
||
* A4 - points to red gamma correction table
|
||
* A5 - points to green gamma correction table
|
||
* A6 - points to blue gamma correction table
|
||
*
|
||
* Output
|
||
*
|
||
* D2 - reformatted colorSpec in the form BBGGRRVV
|
||
* A3 - incremented to point to next entry in colorSpec table
|
||
*
|
||
* Locally used
|
||
*
|
||
* D0 - to hold 16 bit red data from raw colorSpec
|
||
* D1 - to hold 16 bit green data from raw colorSpec
|
||
* D2 - to hold 16 bit blue data from raw colorSpec
|
||
* D3 - to hold 16 bit value data from raw colorSpec (restored since it holds csCount)
|
||
*
|
||
*******************************************************************
|
||
MOVE.L D3,-(SP)
|
||
|
||
MOVE.W (A3)+,D3 ; get value
|
||
MOVE.W (A3)+,D0 ; get red
|
||
MOVE.W (A3)+,D1 ; get green
|
||
MOVE.W (A3)+,D2 ; get blue
|
||
|
||
TST D5 ; test hi bit of the flags
|
||
BPL.S NoGray ; if not set, don't luminence map
|
||
BTST #DirectModeFlag,D5 ; test for direct mode flag
|
||
BNE.S NoGray ; never luminance map if we're direct
|
||
|
||
; we're luminence mapping here
|
||
|
||
MULU #$4CCC,D0 ; multiply by red weight
|
||
MULU #$970A,D1 ; multiply by green weight
|
||
MULU #$1C29,D2 ; multiply by blue weight
|
||
ADD.L D1,D0 ; sum red and green
|
||
ADD.L D2,D0 ; blue also
|
||
BFEXTU D0{0:D7},D1 ; get gChanWidth bits for gamma table lookup
|
||
MOVE.W D1,D0 ; copy into red register
|
||
MOVE.W D1,D2 ; copy into blue register
|
||
|
||
BRA.S WriteSP ; go on and write it in the stack buffer
|
||
|
||
NoGray
|
||
|
||
BFEXTU D0{16:D7},D0 ; get gChanWidth bits of red
|
||
BFEXTU D1{16:D7},D1 ; get gChanWidth bits of green
|
||
BFEXTU D2{16:D7},D2 ; get gChanWidth bits of blue
|
||
|
||
WriteSP
|
||
MOVE.B (A6,D2),D2 ; get gamma corrected blue (D2 = xxxxxxBB)
|
||
LSL.L #8,D2 ; reposition blue (D2 = xxxxBBxx)
|
||
MOVE.B (A5,D1),D2 ; get gamma corrected green (D2 = xxxxBBGG)
|
||
LSL.L #8,D2 ; reposition blue/green (D2 = xxBBGGxx)
|
||
MOVE.B (A4,D0),D2 ; get gamma corrected red (D2 = xxBBGGRR)
|
||
LSL.L #8,D2 ; reposition blue/green/red (D2 = BBGGRRxx)
|
||
MOVE.B D3,D2 ; put value byte into D2 (D2 = BBGGRRVV)
|
||
|
||
MOVE.L (SP)+,D3
|
||
RTS
|
||
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* SetGamma sets the gamma table. This call copies the supplied gTable so the
|
||
* caller does not have to put the source on the system heap. It
|
||
* tests if the gamma table is exactly a match to the currently
|
||
* connected monitor, or always allows it if the monitor number in
|
||
* the FormulaData is -1. Note that since the CLUT response curve of the AC/DC
|
||
* chip is so close to the response of DAC's used on previous Apple cards,
|
||
* that we let TFB tables thru too (GType=0), but only for the standard monitor!.
|
||
*
|
||
* SetGamma is broken up into 4 main steps:
|
||
*
|
||
* 1. if we're passed a nil table, then setup a linear one and skip to step 4.
|
||
* 2. Get the gamma table and see if it's for us
|
||
* 3. Copy the new gamma table.
|
||
* 4. If we're operating as a direct device, then also set up the CLUT directly.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _DisposPtr, _NewPtr, _SwapMMUMode
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csGTable -> pointer to gamma table
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* D1 - used to create linear clut data index
|
||
* D2 - scratch
|
||
* D7 - scratch
|
||
*
|
||
* A0 - holds pointer to current gamma table
|
||
* A4 - pointer to gamma red table (direct mode only)
|
||
* A5 - pointer to gamma red table (direct mode only)
|
||
* A6 - pointer to gamma red table (direct mode only)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
SetGamma
|
||
|
||
; get new gamma table and check that we know how to handle it
|
||
|
||
MOVE.L csGTable(A2),D0 ; test for a NIL pointer
|
||
BEQ LinearTab ; if so, then set a linear gamma table
|
||
MOVE.L D0,A2 ; get pointer to new gamma table
|
||
|
||
TST.W GVersion(A2) ; version = 0?
|
||
BNE CtlBad ; => no, return error
|
||
|
||
CMP.W #Standard,saveMonSense(A3) ; allow tfb table only for standard monitor
|
||
BNE.S @chkHWMatch ; if not standard then it must be exact match
|
||
TST.W GType(A2) ; test the hardware ID
|
||
BEQ.S ChangeTable ; if 0, then accept a TFB table
|
||
|
||
@chkHWMatch
|
||
CMP.W #drHwJMFB,GType(A2) ; type = Bob the card?
|
||
BNE CtlBad ; => no, return error
|
||
TST.W gFormulaSize(A2) ; if gType=JMFB, then check for monID in gFormulaData
|
||
BEQ.S ChangeTable ; if zero, then generic, so continue
|
||
|
||
MOVE.W gFormulaData(A2),D0 ; get the monitor ID this table was intended for
|
||
CMP.W saveID(A3),D0 ; is this the monitor?
|
||
BEQ.S ChangeTable ; yes, so do it
|
||
ADDQ #1,D0 ; was it -1?
|
||
BNE CtlBad ; nope, so must be wrong monitor
|
||
|
||
; if new table is different size, reallocate memory
|
||
|
||
ChangeTable
|
||
MOVE.L saveGammaPtr(A3),A0 ; get current gamma in A0
|
||
MOVE GFormulaSize(A2),D0 ; get size of formula in new
|
||
CMP GFormulaSize(A0),D0 ; same as current gamma table
|
||
BNE.S @GetNew ; =>no, resize pointer
|
||
MOVE GChanCnt(A2),D0 ; get number of tables in new
|
||
CMP GChanCnt(A0),D0 ; same as current gamma table?
|
||
BEQ.S @SizeOK ; => yes, data size ok
|
||
BGT.S @GetNew ; => new one is bigger, save old one
|
||
@NewSize Move.l saveGammaPtrHead(A3),A0 ; if new one smaller,
|
||
_DisposPtr ; dispose old one
|
||
CLR.L saveGammaPtrHead(A3) ; flag it's been disposed
|
||
|
||
@GetNew MOVE GDataCnt(A2),D0 ; get number of entries
|
||
MULU GChanCnt(A2),D0 ; multiply by number of tables
|
||
ADD GFormulaSize(A2),D0 ; add size of formula data
|
||
ADD #GFormulaData,D0 ; add gamma table header size
|
||
_NewPtr ,Sys ; and allocate a new pointer
|
||
BNE CtlBad ; => unable to allocate storage
|
||
|
||
MOVE.L saveGammaPtrHead(A3),D0 ; get old gamma table
|
||
MOVE.L A0,saveGammaPtr(A3) ; save new gamma table
|
||
TST.L D0 ; was there an old one?
|
||
BEQ.S @SizeOK ; => no, already disposed
|
||
MOVE.L D0,A0 ; else get old table
|
||
_DisposPtr ; and dispose of old gamma table
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get new gamma table back
|
||
Move.l A0,saveGammaPtrHead(A3) ; save it for disposal
|
||
|
||
; copy the gamma table header
|
||
|
||
@SizeOK MOVE GChanCnt(A2),D0 ; get number of tables
|
||
MOVE GFormulaSize(A2),D1 ; get size of formula data
|
||
MOVE gDataCnt(A2),D2 ; get number of entries
|
||
MOVE.L (A2)+,(A0)+ ; copy gamma header
|
||
MOVE.L (A2)+,(A0)+ ; which is
|
||
MOVE.L (A2)+,(A0)+ ; 12 bytes long
|
||
|
||
; copy the data
|
||
|
||
MULU D0,D2 ; multiply by number of tables
|
||
ADD D1,D2 ; add in size of formula data
|
||
SUBQ #1,D2 ; get count - 1
|
||
@NxtByte MOVE.B (A2)+,D0 ; get a byte
|
||
MOVE.B D0,(A0)+ ; move a byte
|
||
DBRA D2,@NxtByte ; => repeat for all bytes
|
||
|
||
BRA.S GammaDone ; check to see if it's a direct device
|
||
|
||
; set up a linear gamma table. To prevent memory thrash, build this new one
|
||
; the same size as the existing one (one or three channel)
|
||
;
|
||
|
||
LinearTab
|
||
MOVE.L saveGammaPtr(A3),A0 ; get current gamma in A0
|
||
MOVE.W GFormulaSize(A0),D0 ; get size of formula in new
|
||
MOVE.W GChanCnt(A0),D2 ; get the number of tables
|
||
SUBQ #1,D2 ; zero based, of course
|
||
ADDA #GFormulaData,A0 ; point to tables
|
||
ADDA D0,A0 ; point past monID, if present
|
||
@ChanLoop MOVE.W #255,D0 ; loop count within each channel
|
||
@entryLoop MOVE.B D0,(A0) ; write value
|
||
NOT.B (A0)+ ; invert it to make table ramp properly
|
||
DBRA D0,@entryLoop ; for each entry in channel
|
||
DBRA D2,@ChanLoop ; and each channel
|
||
|
||
GammaDone
|
||
BTST #DirectModeFlag,GFlags(A3) ; If the mode is not direct, then all done
|
||
BEQ CtlGood ; direct = 1, indexed = 0
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma table data structures
|
||
LEA GFormulaData(A0),A4 ; get a pointer to the first gammatable
|
||
ADDA GFormulaSize(A0),A4 ;
|
||
|
||
MOVE.L A4,A5 ; get default pointer to green data (assuming gChanCnt=1)
|
||
MOVE.L A4,A6 ; get default pointer to blue data (assuming gChanCnt=1)
|
||
|
||
MOVE GDataWidth(A0),D7 ; get width of each entry in bits to be used later
|
||
|
||
CMP #1,GChanCnt(A0) ; if only only one table, we're set
|
||
BEQ.S OnlyOneTbl ; => just one table
|
||
|
||
MOVE GDataCnt(A0),D0 ; get # entries in table
|
||
MOVE D7,D1 ; copy it to goof around
|
||
ADD #7,D1 ; round to nearest byte
|
||
LSR #3,D1 ; get bytes per entry
|
||
MULU D1,D0 ; get size of table in bytes
|
||
|
||
ADDA D0,A5 ; calc base of green (red base + D0)
|
||
ADDA D0,A6 ; calc base of blue
|
||
ADDA D0,A6 ; calc base of blue (red base + D0 + D0)
|
||
|
||
OnlyOneTbl ; in direct modes we want a gamma corrected linear CLUT
|
||
|
||
MOVE.L saveHardBase(A3),A0 ; get base addr of card
|
||
ADD.L #CLUT+CLUTDataReg,A0 ; point to data reg of clut
|
||
MOVEQ #true32b,D0 ; swap to 32 bit addr mode
|
||
_SwapMMUMode
|
||
MOVE D0,-(SP) ; save past addr mode for later
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
BSR WaitVSync
|
||
|
||
MOVE.L #0,CLUTAddrReg-CLUTDataReg(A0) ; start at index 0
|
||
|
||
MOVE.W #$FF,D0 ; set up for 256 rgb triplets
|
||
MOVEQ #0,D1 ; d1 is used as the data index
|
||
@1 MOVE.B (A4,D1),D2 ; temp move to d2
|
||
MOVE.L D2,(A0) ; write red (all Trident hw writes must be longs!)
|
||
MOVE.B (A5,D1),D2
|
||
MOVE.L D2,(A0) ; write green (all Trident hw writes must be longs!)
|
||
MOVE.B (A6,D1),D2
|
||
MOVE.L D2,(A0) ; write blue (all Trident hw writes must be longs!)
|
||
ADDQ #1,D1 ; increment data index by 1
|
||
DBRA D0,@1 ; decrement loop counter and branch
|
||
MOVE (SP)+,SR
|
||
MOVE (SP)+,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode
|
||
BRA CtlGood
|
||
|
||
*******************************************************************
|
||
*
|
||
* GrayPage clears the specified page in the current mode to gray. If we
|
||
* are operating on a direct device, GrayPage is also responsible for
|
||
* setting up the CLUT directly (with linear and gamma corrected ramps).
|
||
*
|
||
* GrayPage is broken up into 4 main steps:
|
||
*
|
||
* 1. Check the requested mode against allowable modes and exit if bad.
|
||
* 2. Check the requested page number against max pages and exit if bad.
|
||
* 3. Call the GrayScreen utility
|
||
* 4. If we're operating as a direct device, then also set up the CLUT directly.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* GrayScreen, _SwapMMUMode, ChkMode, ChkPage
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csPage -> page number to gray
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D0 - used to pass requested page to ChkPage
|
||
* D1 - used to pass requested mode to ChkMode (comes back as depth)
|
||
* D7 - scratch
|
||
*
|
||
* A0 - holds pointer to current gamma table
|
||
* A4 - pointer to gamma red table (direct mode only)
|
||
* A5 - pointer to gamma red table (direct mode only)
|
||
* A6 - pointer to gamma red table (direct mode only)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GrayPage
|
||
|
||
MOVE saveMode(A3),D1 ; D1 = mode
|
||
MOVE D1,csMode(A2) ; force current mode, just in case for ChkPage
|
||
BSR ChkMode ; convert mode to depth in D1
|
||
BNE CtlBad ; => not a valid depth
|
||
|
||
MOVE csPage(A2),D0 ; D0 = page
|
||
BSR ChkPage ; check page
|
||
BNE CtlBad ; => not a valid page
|
||
|
||
BSR GrayScreen ; paint the screen gray
|
||
|
||
BTST #DirectModeFlag,GFlags(A3) ; If the mode is not direct, then all done
|
||
BEQ CtlGood ; direct = 1, indexed = 0
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma table data structures
|
||
LEA GFormulaData(A0),A4 ; get a pointer to the first gammatable
|
||
ADDA GFormulaSize(A0),A4 ;
|
||
|
||
MOVE.L A4,A5 ; get default pointer to green data (assuming gChanCnt=1)
|
||
MOVE.L A4,A6 ; get default pointer to blue data (assuming gChanCnt=1)
|
||
|
||
MOVE GDataWidth(A0),D7 ; get width of each entry in bits to be used later
|
||
|
||
CMP #1,GChanCnt(A0) ; if only only one table, we're set
|
||
BEQ.S Only1Tbl ; => just one table
|
||
|
||
MOVE GDataCnt(A0),D0 ; get # entries in table
|
||
MOVE D7,D1 ; copy it to goof around
|
||
ADD #7,D1 ; round to nearest byte
|
||
LSR #3,D1 ; get bytes per entry
|
||
MULU D1,D0 ; get size of table in bytes
|
||
|
||
ADDA D0,A5 ; calc base of green (red base + D0)
|
||
ADDA D0,A6 ; calc base of blue
|
||
ADDA D0,A6 ; calc base of blue (red base + D0 + D0)
|
||
|
||
Only1Tbl ; in direct modes we want a gamma corrected linear CLUT
|
||
|
||
MOVE.L saveHardBase(A3),A0
|
||
ADD.L #CLUT+CLUTDataReg,A0
|
||
MOVEQ #true32b,D0
|
||
_SwapMMUMode
|
||
MOVE D0,-(SP) ; save past addr mode for later
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
BSR WaitVSync
|
||
MOVE.L #0,CLUTAddrReg-CLUTDataReg(A0)
|
||
|
||
MOVE.W #$FF,D0
|
||
MOVEQ #0,D1
|
||
@1 MOVE.B (A4,D1),D2
|
||
MOVE.L D2,(A0)
|
||
MOVE.B (A5,D1),D2
|
||
MOVE.L D2,(A0)
|
||
MOVE.B (A6,D1),D2
|
||
MOVE.L D2,(A0)
|
||
ADDQ #1,D1
|
||
DBRA D0,@1
|
||
MOVE (SP)+,SR
|
||
MOVE (SP)+,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode
|
||
|
||
BRA CtlGood ; => return no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* SetGray sets luminance mapping on (csMode = 1) or off (csMode = 0)
|
||
*
|
||
* When luminance mapping is on, RGB values passed to setEntries are mapped
|
||
* to grayscale equivalents before they are written to the CLUT.
|
||
*
|
||
* SetGray is broken up into 2 main steps:
|
||
*
|
||
* 1. If the monitor is monochrome always luminance map.
|
||
* 2. Set GrayFlag in private storage based on requested mode.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* SetIntCom
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csmode -> gray or color mode
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D1 - used as the bit position of grayFlag bit in GFlags word
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* SetGray should always be followed by a SetEntries/GrayScreen call.
|
||
*
|
||
*******************************************************************
|
||
SetGray
|
||
|
||
BTST #MonoFlag,GFlags(A3) ; is this a mono-only monitor?
|
||
BEQ.S @1 ; if not, then go ahead
|
||
MOVE.B #1,csMode(A2) ; always turn on for mono devices
|
||
@1 MOVEQ #(15-GrayFlag),D1 ; set up for BFEXTU to point to GrayFlag
|
||
BSR.S SetIntCom ; call common code
|
||
BRA CtlGood ; all done
|
||
|
||
;
|
||
; this shared routine setup up a flag in GFlags. It takes a pointer to
|
||
; private storage in A3, and the bit field start location in D1
|
||
;
|
||
|
||
SetIntCom
|
||
MOVE.B csMode(A2),D0 ; get boolean
|
||
BFINS D0,GFlags(A3){D1:1} ; set flag bit
|
||
RTS ; and return
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* SetInterrupt enables (csMode = 0) or disable (csMode = 1) VBL interrupts
|
||
*
|
||
* As a future performance enhancement, interrupts on the card can be
|
||
* disabled or enabled from software. For instance, if the cursor is
|
||
* not on a screen, and there is nothing in the Slot Interrupt Queue
|
||
* for that device, interrupts may be disabled reducing interrupt
|
||
* overhead for the system.
|
||
*
|
||
* SetInterrupt is broken up into 3 main steps:
|
||
*
|
||
* 1. Set the IntDisFlag in private storage based on csMode
|
||
* 2. If enable, then call EnableVGuts and save SaveSQElPtr in privates
|
||
* 3. If disable, then call DisableVGuts
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* SetIntCom, EnableVGuts, DisableVGuts
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csmode -> 0 enables, 1 disables
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D1 - used as the bit position of IntDisFlag bit in GFlags word
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
SetInterrupt
|
||
|
||
WITH VDPageInfo,SlotIntQElement
|
||
|
||
MOVEQ #(15-IntDisFlag),D1 ; set up for BFEXTU to point to IntDisFlag
|
||
BSR.S SetIntCom ; call common code
|
||
BNE.S DisableThem ; if zero, then enable
|
||
|
||
;
|
||
; this code enables interrupts and installs the interrupt handler
|
||
;
|
||
|
||
BSR.S EnableVGuts ; call common code
|
||
BNE CtlBad ; error, flag problem
|
||
BRA CtlGood ; and go home
|
||
|
||
;
|
||
; this code disables VBL interrupts, then removes the interrupt handler
|
||
;
|
||
|
||
DisableThem
|
||
BSR.S DisableVGuts ; jump to the disabling utility
|
||
BRA CtlGood ; all done
|
||
|
||
;
|
||
; the following two routines are common code shared between the Open call
|
||
; and the SetInterrupt control call
|
||
;
|
||
|
||
DisableVGuts
|
||
|
||
; gotta be in 32 bit mode prior to calling WaitVSync
|
||
|
||
MOVEQ #true32b,D0 ; change to 32 bit addressing to get
|
||
_SwapMMUMode ; at hardware
|
||
MOVE D0,D3 ; save past addr mode for later (not using stack here)
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
|
||
;+++ BSR WaitVSync ; to be safe, wait for the next VBL
|
||
CLR D0 ; clear D0.W
|
||
MOVE.B dctlSlot(A1),D0 ; setup slot # for _SIntRemove
|
||
MOVE.L saveHardBase(A3),A0 ; get the device base
|
||
ADD.L #StopWatch+SWICReg,A0 ; point to StopWatch Interrupt and control register
|
||
MOVE.L #7,(A0) ; disable both interrupts, but don't reset stowpwatch ???
|
||
|
||
MOVE D3,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode
|
||
|
||
MOVE.L saveSQElPtr(A3),A0 ; get the SQ element pointer
|
||
_SIntRemove ; remove the interrupt handler
|
||
|
||
MOVE.W (SP)+,SR ; restore the interrupt level
|
||
RTS
|
||
|
||
EnableVGuts
|
||
MOVE.L saveSQElPtr(A3),A0 ; dispose of the VBL queue element
|
||
LEA BeginIH,A2 ; save Pointer to interrupt handler
|
||
MOVE.L A2,D0
|
||
_StripAddress
|
||
MOVE.L D0,A2
|
||
|
||
MOVE.W #SIQType,SQType(A0) ; setup queue ID
|
||
MOVE.L A2,SQAddr(A0) ; setup int routine address
|
||
MOVE.L saveHardBase(A3),A2 ; get slot base addr
|
||
ADD.L #StopWatch+SWClrVInt,A2 ; point to the Stopwatch interrupt clear register
|
||
MOVE.L A2,SQParm(A0) ; pass this as the parameter
|
||
MOVEQ.L #0,D0 ; parameter size to SInstall is not byte sized so clr whole long
|
||
MOVE.B dctlSlot(A1),D0 ;
|
||
_SIntInstall ; and do install
|
||
BNE.S IntBad
|
||
|
||
ADD.L #SWICReg-SWClrVInt,A2 ; point back to the Stopwatch Interrupt and Control Register
|
||
|
||
MOVEQ #true32b,D0 ; change to 32 bit addressing to get
|
||
_SwapMMUMode ; at hardware
|
||
|
||
MOVE.L #5,(A2) ; no line interrupts, enable Vert Interrupts (and keep SRST = 1)
|
||
|
||
_SwapMMUMode ; swap to previous mode (d0 still valid)
|
||
|
||
CMP.W D1,D1 ; set Z-bit for good result
|
||
|
||
RTS ; return home
|
||
|
||
;
|
||
; in the event there is a problem, return Z-flag off
|
||
;
|
||
|
||
IntBad
|
||
MOVEQ #1,D0 ; clear Z bit
|
||
RTS
|
||
|
||
ENDWITH
|
||
|
||
*******************************************************************
|
||
*
|
||
* The DirectSetEntries control call will allow color table animation in direct modes.
|
||
* The code will be almost identical to the indexed modes SetEntries.
|
||
* Note it will be the applications responsibility to restore the linear
|
||
* ramps in all three CLUT channels upon completion of color table
|
||
* animation.
|
||
*
|
||
* This call shares common code with SetEntries.
|
||
*
|
||
* DirectSetEntries is broken up into ***x*** main steps:
|
||
*
|
||
* 1. If there is no requested color table or if mode is indexed, then exit.
|
||
* 2. Go and execute the SetEntries common code.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* Refer to SetEntries header.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Refer to SetEntries header.
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* Refer to SetEntries header.
|
||
*
|
||
*******************************************************************
|
||
DirectSetEntries
|
||
|
||
MOVE.L csTable(A2),D0 ; Check for a nil pointer
|
||
BEQ CtlBad
|
||
|
||
BTST #DirectModeFlag,GFlags(A3) ; DirectSetEntries is not allowed for indexed devices
|
||
BEQ CtlBad ; Indexed Mode (0) and Direct Mode (1)
|
||
|
||
BRA SetEntCom
|
||
|
||
*******************************************************************
|
||
*
|
||
* SetDefaultMode writes the requested card default mode into slot pRAM.
|
||
*
|
||
* This routine is called by Monitors when somebody selects an alternate
|
||
* video mode family in the Options-Option dialog. Upon restart, PrimaryInit
|
||
* will detect a change to the new sRsrc ID and set the card up for that
|
||
* mode. The Trident card uses multiple members of video mode families
|
||
* in the interlaced modes (RS170 and PAL) only.
|
||
*
|
||
* SetDefaultMode is broken up into 2 main steps:
|
||
*
|
||
* 1. Get the current PRAM record for the card.
|
||
* 2. Modify the saved sRsrc ID and write out the record to PRAM.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Control Call Handler (call is initiated only by Monitors cdev)
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _sReadPRAMRec, _sPutPRAMRec
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csmode -> new spID to be put into PRAM
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Locally used:
|
||
* A0 - used to point to slot parameter block
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
SetDefaultMode
|
||
|
||
WITH spBlock
|
||
|
||
;
|
||
; set up a slot parameter block on the stack
|
||
;
|
||
|
||
SUBA #spBlockSize,SP ; make an slot parameter block on stack
|
||
MOVE.L SP,A0 ; get pointer to parm block now
|
||
MOVE.B dCtlSlot(A1),spSlot(A0) ; put slot in pBlock
|
||
CLR.B spExtDev(A0) ; external device = 0
|
||
|
||
|
||
;
|
||
; read the slot pRAM to determine what the currently saved mode is. The first
|
||
; word is the board ID, followed by the default mode. Trident uses the vendoruse2
|
||
; field to save the Monitor type.
|
||
;
|
||
;+++ vendoruse2 should really be the savedsRsrcID, check/change all occurances
|
||
;
|
||
|
||
SUBA #SizesPRAMRec,SP ; allocate block for pRAM record
|
||
MOVE.L SP,spResult(A0) ; point to it
|
||
_sReadPRAMRec ; read it
|
||
|
||
MOVE.B csMode(A2),savedSRsrcID(SP) ; return the result
|
||
|
||
MOVE.L SP,spsPointer(A0) ; set up param block
|
||
_sPutPRAMRec
|
||
ADDA #SizesPRAMRec+spBlockSize,SP ; deallocate buffer
|
||
BRA CtlGood
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* VideoClose releases the device's private storage and removes the
|
||
* interrupt handler.
|
||
*
|
||
* VideoClose is broken up into 4 main steps:
|
||
*
|
||
* 1. Clean up DCE pointer as it's used in 32 bit mode later
|
||
* 2. Get a pointer to the driver private storage to release
|
||
* 3. Call DisableVGuts to turn off interrupts, etc.
|
||
* 4. Dispose of private storage memory.
|
||
*
|
||
* Called by:
|
||
*
|
||
* A/UX (I'm not aware of the Mac OS ever calling Close for video drivers)
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _StripAddress, DisableVGuts, _DisposPtr, _DisposHandle
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A0 - parameter block pointer
|
||
* A1 - pointer to the AuxDCE
|
||
*
|
||
* Output:
|
||
* D0 - always returns no error.
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* A3 - pointer to private storage
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
VideoClose
|
||
|
||
MOVE.L A1,D0 ; need to clean up the pointer to the DCE
|
||
_StripAddress ; because it is used in 32 bit mode later
|
||
MOVE.L D0,A1 ; in DisableVGuts
|
||
|
||
MOVE.L dCtlStorage(A1),A3
|
||
MOVE.L (A3),D0 ; get pointer to private storage
|
||
_StripAddress ; strip hi byte for 32 bit addressing in DisableVGuts
|
||
MOVE.L D0,A3 ; put back into A3
|
||
|
||
BSR DisableVGuts ; call utility to deactivate interrupts
|
||
|
||
MOVE.L saveGammaPtrHead(A3),A0 ; get pointer to the head of gamma table
|
||
_DisposPtr ; and dispose it
|
||
|
||
MOVE.L dCtlStorage(A1),A0 ; Dispose of the private storage
|
||
_DisposHandle ;
|
||
|
||
MOVE.L saveSQElPtr(A3),A0 ; dispose of the VBL queue element
|
||
_DisposPtr ; release it
|
||
|
||
MOVEQ #0,D0 ; no error
|
||
RTS ; and return
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* Video Driver Status Call Handler. There are eight valid calls. No
|
||
* new status calls have been introduced since Bob, although they
|
||
* have been modified.
|
||
*
|
||
* (0) Error
|
||
* (1) Error
|
||
* (2) GetMode
|
||
* (3) GetEntries
|
||
* (4) GetPage
|
||
* (5) GetPageBase
|
||
* (6) GetGray
|
||
* (7) GetInterrupt
|
||
* (8) GetGamma
|
||
* (9) GetDefault
|
||
*
|
||
* The Control Call Handler is broken up into 4 main steps:
|
||
*
|
||
* 1. Note : A1 (DCE pointer) is not StripAddressed for status calls!
|
||
* 2. Get the pointer to private storage in A3 and strip the upper byte.
|
||
* 3. Get the pointer to the csParams in A2.
|
||
* 4. Get the csCode and dispatch the call to the right status call.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Device Manager
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _StripAddress, appropriate control call
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A0 = param block pointer
|
||
* A1 = DCE pointer
|
||
*
|
||
* Output:
|
||
* D0 = error code
|
||
*
|
||
* Locally used:
|
||
* D0 = scratch, then returns error code as output
|
||
*
|
||
* A2 = cs parameters (ie. A2 <- csParam(A0)) (must be preserved)
|
||
* A3 = ptr to private storage (passed to all control calls)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
VideoStatus
|
||
|
||
MOVE.L A0,-(SP) ; save a register
|
||
MOVE.L dCtlStorage(A1),A3
|
||
MOVE.L (A3),D0 ; get pointer to private storage
|
||
_StripAddress ; strip hi byte for 32 bit addressing
|
||
MOVE.L D0,A3 ; put back in A3
|
||
|
||
MOVE.W csCode(A0),D0 ; get the opCode
|
||
MOVE.L csParam(A0),A2 ; A2 <- Ptr to control parameters
|
||
CMP.W #9,D0 ;IF csCode NOT IN [0..9] THEN
|
||
BHI.S StatBad ; Error, csCode out of bounds.
|
||
LSL.W #1,D0 ;Adjust csCode to be an index into the table.
|
||
MOVE.W StatJumpTbl(PC,D0.W),D0 ;Get the relative offset to the routine.
|
||
JMP StatJumpTbl(PC,D0.W) ;GOTO the proper routine.
|
||
|
||
StatJumpTbl DC.W StatBad-StatJumpTbl ;$00 => Error
|
||
DC.W StatBad-StatJumpTbl ;$01 => Error
|
||
DC.W GetMode-StatJumpTbl ;$02 => GetMode
|
||
DC.W GetEntries-StatJumpTbl ;$03 => GetEntries
|
||
DC.W GetPage-StatJumpTbl ;$04 => GetPage
|
||
DC.W GetPageBase-StatJumpTbl ;$05 => GetPageBase
|
||
DC.W GetGray-StatJumpTbl ;$06 => GetGray
|
||
DC.W GetInterrupt-StatJumpTbl ;$07 => GetInterrupt
|
||
DC.W GetGamma-StatJumpTbl ;$08 => GetGamma
|
||
DC.W GetDefaultMode-StatJumpTbl ;$09 => GetDefaultMode
|
||
|
||
StatBad MOVEQ #statusErr,D0 ; else say we don't do this one
|
||
BRA.S StatDone ; and return
|
||
|
||
StatGood MOVEQ #noErr,D0 ; return no error
|
||
|
||
StatDone MOVE.L (SP)+,A0 ; restore registers.
|
||
BRA ExitDrvr
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetMode returns the current operating mode in csMode, the current
|
||
* display page in csPage, and the base address of the frame buffer
|
||
* in csBaseAddr.
|
||
*
|
||
* GetMode is broken up into 3 main steps:
|
||
*
|
||
* 1. Copy the current saved mode into csMode(A2).
|
||
* 2. Copy the current saved page into csPage(A2).
|
||
* 3. Copy the current saved baseaddr into csBaseAddr(A2).
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code.
|
||
*
|
||
* Locally used:
|
||
* None.
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetMode
|
||
|
||
MOVE.W saveMode(A3),csMode(A2) ; return the mode
|
||
MOVE.W savePage(A3),csPage(A2) ; return the page number
|
||
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; and the base address
|
||
|
||
BRA.S StatGood ; => return no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetEntries reads the current contents of the CLUT.
|
||
*
|
||
* GetEntries is broken up into 4 main steps:
|
||
*
|
||
* 1. Get the pointer to the output table and strip upper byte.
|
||
* 2. Range check the requested index count.
|
||
* 3. If index mode write all value fields to table.
|
||
* 4. Read the CLUT data registers and write data (components) to table.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _StripAddress, _SwapMMUMode
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* D1 - scratch and loop counter
|
||
* D2 - used to hold the value index in indexed modes
|
||
* D3 - holds max number of valid entries in current depth mode
|
||
* D4 - loop counter for CLUT reads
|
||
*
|
||
* A0 - pointer to output table
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* Note that due to gamma correction, the data in the CLUT will probably
|
||
* not be the data that you wrote with SetEntries or DirectSetEntries (unless
|
||
* the gamma table was a linear one).
|
||
*
|
||
*******************************************************************
|
||
GetEntries
|
||
|
||
MOVE.L csTable(A2),D0 ; Check for a nil pointer
|
||
BEQ.S StatBad
|
||
_StripAddress ; strip hi byte prior to 32 bit addressing
|
||
MOVE.L D0,A0 ; A0 <- pointer to table
|
||
|
||
; calculate the index range in D3
|
||
|
||
MOVE.W saveMode(A3),D1 ; get the current video mode
|
||
SUB.W #FirstVidMode,D1 ; convert to index
|
||
LEA CountTbl,A3 ; point to little table of counts
|
||
MOVEQ #0,D3 ; clear the long (only need word size tho!)
|
||
MOVE.B (A3,D1),D3 ; pick the zero-based byte
|
||
|
||
MOVE.W csCount(A2),D4 ; get the count
|
||
TST.W D4
|
||
BMI.S StatBad
|
||
CMP.W D3,D4 ; D4-D3 > 0 (req count > max count) then bad
|
||
BHI.S StatBad
|
||
MOVE.W D4,D2 ; make a copy of the count
|
||
|
||
CMP.W #-1,csStart(A2) ; is it index or sequence mode?
|
||
BEQ.S GECom ; if index, then continue
|
||
|
||
MOVE.W D4,D1 ; copy count into another loop counter
|
||
ADD.W csStart(A2),D2 ; get last index
|
||
@1
|
||
MOVE.W D2,value(A0,D1*8) ; write the index into the table
|
||
SUBQ #1,D2 ; decrease index
|
||
DBRA D1,@1 ; for all indices
|
||
|
||
GECom
|
||
MOVE.L dCtlStorage(A1),A3
|
||
MOVE.L (A3),D0 ; get pointer to private storage
|
||
_StripAddress ; strip hi byte prior to 32 bit addressing
|
||
MOVE.L D0,A3 ; put back into A3
|
||
MOVE.L saveHardBase(A3),A3 ; A3 <- base address of device
|
||
ADD.L #CLUT+CLUTDataReg,A3 ; Add offset to CLUT read register
|
||
|
||
MOVEQ #true32b,D0
|
||
_SwapMMUMode
|
||
|
||
@Repeat MOVE.W value(A0),D1 ; get the next position in D1
|
||
CMP.W D3,D1 ; Is this request in range?
|
||
BHI.S @Until ; if hi, then no, the request is invalid
|
||
|
||
MOVE.L D1,CLUTAddrReg-CLUTDataReg(A3) ; set the CLUT to read from this address
|
||
|
||
MOVE.L (A3),D1 ; get red
|
||
MOVE.B D1,rgb+red(A0) ; write hi byte
|
||
MOVE.B D1,rgb+red+1(A0) ; write lo byte
|
||
|
||
MOVE.L (A3),D1 ; get green
|
||
MOVE.B D1,rgb+green(A0) ; write hi byte
|
||
MOVE.B D1,rgb+green+1(A0) ; write lo byte
|
||
|
||
MOVE.L (A3),D1 ; get blue
|
||
MOVE.B D1,rgb+blue(A0) ; write hi byte
|
||
MOVE.B D1,rgb+blue+1(A0) ; write lo byte
|
||
|
||
@Until ADDQ.L #colorSpecSize,A0 ; advance A0 to the next color table element
|
||
DBRA D4,@Repeat ; and loop until done
|
||
|
||
_SwapMMUMode
|
||
|
||
BRA StatGood ; => return no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetPage returs the number of pages in the specified mode.
|
||
* Note that this routine is the only one that deals with non-zero
|
||
* based page counts. All of the other ones, including the equates
|
||
* are zero based!
|
||
*
|
||
* GetPage is broken up into 2 main steps:
|
||
*
|
||
* 1. Call ChkMode to see if mode is a valid one.
|
||
* 2. Get the number of pages from the misc. param. table as a f(memorysize)
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* ChkMode
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csMode - screen depth
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code.
|
||
*
|
||
* csPage(A2) - number of pages for current mode and memorysize
|
||
*
|
||
* Locally used:
|
||
* D1 - scratch
|
||
* D2 - holds mode and used to index into misc. param. table
|
||
*
|
||
* A0 - points to the active hw video parameters
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetPage
|
||
|
||
MOVE csMode(A2),D1 ; get the mode
|
||
MOVE D1,D2 ; keep a copy
|
||
BSR ChkMode ; is this mode OK?
|
||
BNE StatBad ; => not a valid mode
|
||
|
||
SUB #FirstVidMode,D2 ; mode, zero-based
|
||
MOVE.L saveVidParms(A3),A0 ; get pointer to vid parameters
|
||
BTST #RAM512KFlag,GFlags(A3) ; how much RAM?
|
||
BNE.S @1 ; if TRUE, then 512K of RAM
|
||
MOVE.B (D_Pages1024,A0,D2),D1 ; get the number of video pages
|
||
EXT.W D1 ; extend to word sized (especially important for -1 invalid case)
|
||
BRA.S @2 ;
|
||
@1 MOVE.B (D_Pages512,A0,D2),D1 ;
|
||
EXT.W D1 ; extend to word sized (especially important for -1 invalid case)
|
||
@2 ADDQ.W #1,D1 ; convert 0 based page count to non 0 based
|
||
MOVE.W D1,csPage(A2) ; return page count (high byte zero from ChkMode)
|
||
BRA StatGood ; => return no error
|
||
|
||
|
||
GetPageBase
|
||
*******************************************************************
|
||
*
|
||
* GetPageBase returns the base address for the specified page
|
||
* in the current mode
|
||
*
|
||
* GetPageBase is broken up into 6 main steps:
|
||
*
|
||
* 1. Call ChkMode to see if mode is a valid one.
|
||
* 2. Call ChkPage to see if page is a valid one.
|
||
* 3. Get the rowbytes and screenrows from the misc. param. table
|
||
* 4. Calculate base address (page num * rowbytes * screenrows)
|
||
* 5. Call GetBaseOffset to get additional offset if any and add.
|
||
* 6. Add to slot space of the card (Fs000000).
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* ChkMode, ChkPage, GetBaseOffset
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* csPage - display page number
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - error code
|
||
*
|
||
* csBaseAddr(A2) - base address
|
||
*
|
||
* Locally used:
|
||
* D0 - used to pass page number to ChkPage
|
||
* - later used to return base offset from GetBaseOffset
|
||
* D1 - used to pass mode to ChkMode and returns with depth mode
|
||
* - later used to index into misc. parameters
|
||
* - later used to pass to save interim calc
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
MOVE saveMode(A3),D1 ; get the current mode
|
||
MOVE D1,csMode(A2) ; force current mode, just in case for ChkPage
|
||
BSR ChkMode ; convert to depth in D1
|
||
; (assume current mode ok - we set it, after all)
|
||
MOVE.W csPage(A2),D0 ; get the requested page
|
||
BSR ChkPage ; is the page valid?
|
||
BNE StatBad ; => no, just return
|
||
|
||
MOVE saveMode(A3),D1 ; get the current "real" mode
|
||
SUB #FirstVidMode,D1 ; make it 0 based
|
||
MOVE.L saveVidParms(A3),A0 ; point to data table
|
||
MULU (D_RowBytes,A0,D1*2),D0 ; calc page * rowBytes
|
||
MULU D_Height(A0),D0 ; calc page * rowBytes * height
|
||
MOVE.L D0,D1 ; move page pass to D1 since GetBaseOffset returns D0
|
||
BSR GetBaseOffset ; get appropriate base address in D0
|
||
ADD.L D1,D0 ; add together into D0
|
||
ADD.L saveHardBase(A3),D0 ; add base address for card
|
||
|
||
BTST #sRsrc32Bit,GFlags(A3) ; check for 32 bit sRsrc (base address = Fsxx xxxx)
|
||
BNE.S @saveIt ; if it is 32 bit sRsrc page base address is setup right
|
||
BFEXTU D0{4,4},D1 ; else it's 24 bit (Fssx xxxx) so get slot number
|
||
BFINS D1,D0{8,4} ; and insert it into D0 to form Fssx xxxx
|
||
|
||
@saveit MOVE.L D0,csBaseAddr(A2) ; return the base address
|
||
|
||
BRA StatGood ; => return no error
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetGray returns a boolean, set true if luminance mapping is on
|
||
*
|
||
* GetGray is broken up into 1 main steps:
|
||
*
|
||
* 1. Get the GrayFlag state from private storage and put in csMode.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - always returns good error code
|
||
*
|
||
* csMode(A2) - boolean indicating flag state
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetGray
|
||
|
||
MOVEQ #(15-GrayFlag),D1 ; set up for BFEXTU
|
||
GetFlagCom BFEXTU GFlags(A3){D1:1},D0 ; get the state of flag
|
||
MOVE.B D0,csMode(A2) ; return value
|
||
BRA StatGood ; => and return
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetInterrupt returns a boolean, set true if interrupts are disabled.
|
||
*
|
||
* GetInterrupt is broken up into 1 main steps:
|
||
*
|
||
* 1. Get the IntDisFlag state from private storage and put in csMode.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - always returns good error code
|
||
*
|
||
* csMode(A2) - boolean indicating flag state
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetInterrupt
|
||
|
||
MOVEQ #(15-IntDisFlag),D1 ; set up BFEXTU to point at IntDisFlag
|
||
BRA.S GetFlagCom ; and use common code
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetGamma returns the pointer to the current gamma table
|
||
*
|
||
* GetGamma is broken up into 1 main steps:
|
||
*
|
||
* 1. Retrieve the gamma pointer from privates and put in csGTable.
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* D0 - always returns good error code
|
||
*
|
||
* Locally used:
|
||
* None.
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetGamma
|
||
|
||
MOVE.L saveGammaPtr(A3),csGTable(A2) ; return the pointer to the structure
|
||
BRA StatGood ; and return a good result
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetDefaultMode reads the card default mode from slot pRAM.
|
||
*
|
||
* GetDefaultMode is broken up into 2 main steps:
|
||
*
|
||
* 1. Read the PRAM record.
|
||
* 2. Return the result in csMode
|
||
*
|
||
* Called by:
|
||
*
|
||
* Status Call Handler.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _sReadPRAMRec
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
*
|
||
* Output:
|
||
* D0 - always returns good status
|
||
*
|
||
* Locally used:
|
||
* A0 - pointer to slot parameter block
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetDefaultMode
|
||
|
||
WITH spBlock
|
||
|
||
;
|
||
; set up a slot parameter block on the stack
|
||
;
|
||
|
||
SUBA #spBlockSize,SP ; make an slot parameter block on stack
|
||
MOVE.L SP,A0 ; get pointer to parm block now
|
||
MOVE.B dCtlSlot(A1),spSlot(A0) ; put slot in pBlock
|
||
CLR.B spExtDev(A0) ; external device = 0
|
||
|
||
;
|
||
; read the slot pRAM to determine what the currently saved mode is. The first
|
||
; byte is the board ID, followed by the default mode.
|
||
;
|
||
|
||
SUBA #SizesPRAMRec,SP ; allocate block for pRAM record
|
||
MOVE.L SP,spResult(A0) ; point to it
|
||
_sReadPRAMRec ; read it
|
||
|
||
MOVE.B savedSRsrcID(SP),csMode(A2) ; return the result
|
||
ADDA #SizesPRAMRec+spBlockSize,SP ; release buffer
|
||
BRA StatGood ;
|
||
|
||
ENDWITH
|
||
|
||
*******************************************************************
|
||
*
|
||
* Exit from control or Status.
|
||
*
|
||
*******************************************************************
|
||
|
||
ExitDrvr BTST #NoQueueBit,ioTrap(A0) ; no queue bit set?
|
||
BEQ.S GoIODone ; => no, not immediate
|
||
RTS ; otherwise, it was an immediate call
|
||
|
||
GoIODone MOVE.L JIODone,A0 ; get the IODone address
|
||
JMP (A0) ; invoke it
|
||
|
||
|
||
|
||
|
||
*=====================================================================
|
||
*
|
||
* Utilities
|
||
*
|
||
*=====================================================================
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetXtndSense reads the extended sense code from the sense lines.
|
||
* In this driver, we are looking for the Sarnoff breakout box, which
|
||
* has the sense lines assigned as 010100. Note that the returned sense
|
||
* is of the format bc ac ab, where the first two bits are read when a
|
||
* is set high, the second two bits are read when b is set high, and the
|
||
* third two bits are read when c is set high. a, b, and c correspond to
|
||
* sense lines 2, 1, and 0 where 2 is the msb.
|
||
*
|
||
* Called by:
|
||
*
|
||
* PrimaryInit, VideoOpen
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
*
|
||
* A1 - card base address
|
||
* D1 - offset to JMFB CSR (contains sense lines)
|
||
*
|
||
* Output:
|
||
* D0 - returns the extended sense.
|
||
*
|
||
* Locally used:
|
||
* D2 - scratch (saved and restored)
|
||
* D3 - scratch (used to hold the sense line to be output to the CSR
|
||
* (i.e. 100, 010, or 001)
|
||
* D4 - scratch used to build up the data to be output to the CSR
|
||
* D5 - holds the number of bits to shift to get the sense code in the right place
|
||
* (can't use immediate since max valid shift count is only 8 and we need 9)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* 1. Must be called in 32 bit addressing mode.
|
||
*
|
||
*******************************************************************
|
||
GetXtndSense
|
||
|
||
MOVEM.L D2-D6,-(SP) ; save D2 working register
|
||
CLR D0 ; initialize the return value
|
||
MOVE.L #9,D5 ; initialize the number of bits to shift due to byte swapping
|
||
MOVE.L #readBC,D3 ; set up 1 bit to be output
|
||
|
||
|
||
LSL D5,D3 ; shift up due to byte swapping
|
||
MOVE.L (A1,D1.L),D4 ; get current state of the JMFB CSR
|
||
ANDI.W #MaskSenseLine,D4 ; Ensure sense lines will be written out as 000
|
||
OR.L D3,D4 ; write out
|
||
MOVE.L D4,(A1,D1.L)
|
||
;+++ BFINS D3,(A1,D1.L){20:3} ; set a in sense reg high (This doesn't work to the card!)
|
||
|
||
BFEXTU (A1,D1.L){20:3},D2 ; read the sense register a,b,c
|
||
MOVE.B D2,D0 ; move into return register
|
||
LSL.B #2,D0 ; move over 2 bits for next one
|
||
|
||
MOVE.L #readAC,D3 ; set up 1 bit to be output
|
||
|
||
LSL D5,D3 ; shift up due to byte swapping
|
||
MOVE.L (A1,D1.L),D4 ; get current state of the JMFB CSR
|
||
ANDI.W #MaskSenseLine,D4 ; Ensure sense lines will be written out as 000
|
||
OR.L D3,D4 ; write out
|
||
MOVE.L D4,(A1,D1.L)
|
||
;+++ BFINS D3,(A1,D1.L){20:3} ; set b in sense reg high (This doesn't work to the card!)
|
||
|
||
BFEXTU (A1,D1.L){20:3},D2 ; read the sense register a,b,c
|
||
MOVE.B D2,D6 ; save bit c
|
||
ANDI.B #1,D6 ; and only bit c
|
||
LSR.B #1,D2 ; move bit a over 1 to form 2 bit code
|
||
OR.B D6,D2 ; form it
|
||
OR.B D2,D0 ; move into return register
|
||
LSL.B #2,D0 ; move over 2 bits for next one
|
||
|
||
MOVE.L #readAB,D3 ; set up 1 bit to be output
|
||
|
||
LSL.L D5,D3 ; shift up due to byte swapping
|
||
MOVE.L (A1,D1.L),D4 ; get current state of the JMFB CSR
|
||
ANDI.W #MaskSenseLine,D4 ; Ensure sense lines will be written out as 000
|
||
OR.L D3,D4 ; write out
|
||
MOVE.L D4,(A1,D1.L)
|
||
;+++ BFINS D3,(A1,D1.L){20:3} ; set c in sense reg high (This doesn't work to the card!)
|
||
|
||
BFEXTU (A1,D1.L){20:3},D2 ; read the sense register a,b,c
|
||
LSR.L #1,D2 ; shift a,b into lo 2 bits
|
||
OR.B D2,D0 ; move into return register
|
||
|
||
MOVEM.L (SP)+,D2-D6 ; restore D2
|
||
|
||
RTS
|
||
|
||
*******************************************************************
|
||
*
|
||
* ChkMode maps the mode to a depth (1, 2, 4, 8, or 16 (really 24 BPP)), and then
|
||
* determines if this request is a valid one as a function of memory
|
||
* configuration and connected monitor type. This routine is also responsible
|
||
* for controlling the state of the DirectModeFlag. It is set for 24 BPP and
|
||
* clear for all other modes.
|
||
*
|
||
* ChkMode is broken up into 3 main steps:
|
||
*
|
||
* 1. Make the mode request zero-based and range check, exit if bad.
|
||
* 2. Convert mode request to depth.
|
||
* 3. Determine if valid mode based on the table below.
|
||
*
|
||
* Called by:
|
||
*
|
||
* SetVidMode, GrayPage, GetPage, GetPageBase
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* D1 - Mode (in spID form)
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* Equal flag is set if mode is ok.
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch (trashed)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* 1. This routine implements the valid mode table in the Elmer Fudd
|
||
* software ERS, and is repeated here.
|
||
*
|
||
* 640x480 640x870 1152x870 640x480 (NTSC oscan) 768x576 (PAL oscan)
|
||
* 512x384 512x384 (NTSC uscan) 616x460 (PAL uscan)
|
||
* A B A B A B A B A B
|
||
*
|
||
* 1BPP NI Y Y Y Y Y Y - - - -
|
||
* I - - - - - - Y N Y N
|
||
* IC - - - - - - N Y N Y
|
||
* --------------------------------------------------------------------------------
|
||
* 2BPP NI Y Y Y Y Y Y - - - -
|
||
* I - - - - - - Y N Y N
|
||
* IC - - - - - - N Y N Y
|
||
* --------------------------------------------------------------------------------
|
||
* 4BPP NI Y Y Y Y Y Y - - - -
|
||
* I - - - - - - Y N Y N
|
||
* IC - - - - - - N Y N Y
|
||
* --------------------------------------------------------------------------------
|
||
* 8BPP NI Y Y N Y N Y - - - -
|
||
* I - - - - - - Y N (uscan only!)Y N
|
||
* IC - - - - - - N Y N Y
|
||
* --------------------------------------------------------------------------------
|
||
* 24BPP NI N Y - - - - - - - -
|
||
* I - - - - - - N Y N Y (uscan only!)
|
||
* IC - - - - - - - - - -
|
||
* --------------------------------------------------------------------------------
|
||
*
|
||
* Legend: NI - NonInterlaced, I - Interlaced, IC - Interlaced with Convolution
|
||
* A - 512K vRAM, B - 1024K vRAM
|
||
*
|
||
* Y - Mode Valid, N - Mode Invalid, '-' - Not Applicable (Mode Invalid)
|
||
*
|
||
* 2. The mode that is passed in to this routine (in D1) is the sResource list parameter
|
||
* ID number and has a range between FirstVidMode and FifthVidMode ($80-$84). To
|
||
* generate a screen depth from this parameter, it is desirable to make it 0 based.
|
||
* The process is summarized by:
|
||
*
|
||
* parameter ID 0 based Depth
|
||
*
|
||
* $80 (1BPP) 0 (1BPP) 1 (1BPP)
|
||
* $81 (2BPP) 1 (2BPP) 2 (2BPP)
|
||
* $82 (4BPP) == Make it 0 based => 2 (4BPP) == Form Depth => 4 (4BPP)
|
||
* $83 (8BPP) 3 (8BPP) 8 (8BPP)
|
||
* $84 (24BPP) 4 (24BPP) 16 (24BPP)**
|
||
*
|
||
* ** Note that the returned depth for 24 BPP is really 16 not 24 or 32 as expected!
|
||
*
|
||
* 3. Certain modes are only allowed for certain monitors. For instance, 24 bpp is only
|
||
* allowed on the small screens (and not in PAL oscan mode). The local variable
|
||
* BigScreen is used in this routine.
|
||
*
|
||
*******************************************************************
|
||
ChkMode
|
||
SUB #FirstVidMode,D1 ; make it 0 based
|
||
BMI.S ModeBad ; =>bad mode, return
|
||
|
||
CMP #Mode24BPP,D1 ; range check the mode parameter
|
||
BGT.S ModeBad ; exit with error if too big
|
||
|
||
BCLR #DirectModeFlag,GFlags(A3) ; anticipate that it's not 24 BPP
|
||
|
||
MOVEQ #Depth1BPP,D0 ; convert mode request into depth
|
||
LSL D1,D0
|
||
MOVE D0,D1
|
||
|
||
CMP.W #Depth4BPP,D1 ; all 1,2,4 BPP modes are OK for all monitors with 512K
|
||
BLE.S ModeOK
|
||
|
||
BTST #RAM512KFlag,GFlags(A3) ; check to see if card has 512K (1) or 1024K (0)
|
||
BNE.S @512K ; branch to the 512K section
|
||
|
||
CMP.W #Depth8BPP,D1 ; 8 BPP mode is OK for all monitors with 1024K
|
||
BEQ.S ModeOK
|
||
|
||
BTST #BigScreen,GFlags(A3) ; is it a small screen (0) or larger screen (1)
|
||
BNE.S ModeBad ; 24 BPP mode is only allowed on the small screen
|
||
BTST #sRsrc32Bit,GFlags(A3) ; make sure that we're an sRsrc that supports 24 bpp
|
||
BEQ.S ModeBad ; if 0 then we're 24 bit sRsrc and no 24 bpp!
|
||
BTST #PALFlag,moreGFlags(A3) ; check for PAL since 24 bpp is not supported in overscan mode
|
||
BEQ.S @notPAL ; if it's not PAL, then 24 bpp mode request is ok
|
||
BTST #underScanFlag,moreGFlags(A3) ; if it is PAL, check to see if it's underscan
|
||
BEQ.S ModeBad ; if it is not underscan then the mode request is bad
|
||
@notPAL
|
||
BSET #DirectModeFlag,GFlags(A3) ; must be 24 BPP and the 640x480 small screen
|
||
BRA.S ModeOK ;
|
||
|
||
@512K BTST #BigScreen,GFlags(A3) ; is it a small screen (0) or larger screen (1)
|
||
BNE.S ModeBad ; depths > 4 BPP are only supported on small screen
|
||
BTST #PALFlag,moreGFlags(A3) ; special case for PAL oScan as it only supports 1,2,4 bpp with 1 bank
|
||
BEQ.S @cont512K ; if it's not PAL, then don't do next check
|
||
BTST #UnderScanFlag,moreGFlags(A3) ; check to see if we're overscanning
|
||
BEQ.S ModeBad ; if we are then bad news so get out with error.
|
||
|
||
@cont512K CMP.W #Depth8BPP,D1 ; 8 BPP is the max for small screen with 512K vRAM
|
||
BNE.S ModeBad
|
||
|
||
ModeOK CMP.W D1,D1
|
||
BRA.S EndCM
|
||
ModeBad ST D1 ; set if error
|
||
TST.B D1 ; and test condition
|
||
EndCM RTS
|
||
|
||
*******************************************************************
|
||
*
|
||
* ChkPage checks to see if the page number in D0 is valid for the depth in D1,
|
||
* given the amount of RAM on the card.
|
||
*
|
||
* ChkPage is broken up into 2 main steps:
|
||
*
|
||
* 1. Get the max number of pages allowed in current mode
|
||
* 2. Compare with request and return EQ if valid
|
||
*
|
||
* Called by:
|
||
*
|
||
* SetVidMode, GrayPage, GetPageBase
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* D0 - page
|
||
*
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* csMode(A2) - current mode
|
||
*
|
||
* Output:
|
||
* Set equal flag in SR if valid
|
||
*
|
||
* Locally used:
|
||
* D2 - used to form mode and zero based mode and indexes into misc params.
|
||
* D3 - used to hold the max number of valid pages
|
||
* A1 - pointer to the hw setup parameters
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
|
||
ChkPage MOVEM.L D2-D3/A0-A1,-(SP) ; save work registers
|
||
TST.W D0 ; check for bad value (negative)
|
||
BMI.S PageBad
|
||
MOVEQ #0,D3 ; clear D3 (at least word size)
|
||
MOVE.W csMode(A2),D2 ; get offset to page data
|
||
SUB.W #FirstVidMode,D2 ; zero-based offset in D2
|
||
MOVE.L saveVidParms(A3),A1 ; get pointer to data tables
|
||
BTST #RAM512KFlag,GFlags(A3) ; 512K (0) or 1024K (1)
|
||
BNE.S @1 ; if <> 0, then 1024K
|
||
MOVE.B (D_Pages1024,A1,D2),D3 ; get max number of pages
|
||
EXT.W D3
|
||
CMP.W D3,D0 ; is it a valid page?
|
||
BRA.S @2
|
||
@1 MOVE.B (D_Pages512,A1,D2),D3 ; get max number of pages
|
||
EXT.W D3
|
||
CMP.W D3,D0 ;
|
||
@2
|
||
SGT D2 ; set flag if too big
|
||
TST.B D2 ; and test condition
|
||
BRA.S EndCP
|
||
PageBad ST D2
|
||
TST.B D2
|
||
EndCP MOVEM.L (SP)+,D2-D3/A0-A1 ; restore work registers
|
||
RTS
|
||
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* WaitVSync waits for vertical blanking.
|
||
*
|
||
* Called by:
|
||
*
|
||
* SetVidMode, SetEntries, DisableVGuts, JMFBSetDepth.
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A1 - pointer to the AuxDCE
|
||
* A2 - pointer to the csParams
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Locally used:
|
||
* D0 - working register to hold the VSP~ state (saved)
|
||
* A0 - used to point to the stopwatch status register (saved)
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* 1. The VSP~ state is obtained by reading 1 bit in the StopWatch
|
||
* Status Register. This bit is in bit position 2
|
||
* of the least signifcant byte when viewed from the 68020 world.
|
||
* If you're looking here, you've probably already figured out
|
||
* the byte swapping mess! Refer to the JMFB Spec to see the
|
||
* address mapping requirement.
|
||
*
|
||
* IMPORTANT ... The sensing of the VSP~ register from Stopwatch is
|
||
* inverted (from that defined in the spec) due to NuBus, so when a
|
||
* vertical state is entered, we will read a 1, not a 0 !!!!
|
||
*
|
||
* 2. The BFEXTU instruction is used to extract the VSP~ state into
|
||
* a working register. The offset is 29 bits into the register
|
||
* (bit 0 is MSB of the long word, so bit 29 is bit 2 of the
|
||
* least significant byte of the long word). The data width of
|
||
* VSP~ is 1 bit.
|
||
*
|
||
* 3. The first loop waits for the VSP~ state to transition from 0
|
||
* to 1 (inverted from 1 -> 0) signifying that the vertical sync
|
||
* pulse state was just entered. When VSP goes zero, we know that
|
||
* the state is now vertical back porch.
|
||
*
|
||
* 4. The second loop waits for the VSP~ state to transition
|
||
* to 0 (nverted 1) indicating that the vertical sync pulse state
|
||
* has been exited.
|
||
*
|
||
* 5. The last loop waits for the VSP~ state to transition from 0
|
||
* to 1 again (inverted from 1 -> 0), insuring that we have delayed
|
||
* for at least 1 vertical blanking period and that we are now at
|
||
* the start of the next one.
|
||
*
|
||
* 6. IMPORTANT - 32 bit addressing must be in effect prior to calling
|
||
* this utility subroutine!
|
||
*
|
||
*******************************************************************
|
||
|
||
WaitVSync
|
||
|
||
|
||
MOVEM.L A0/D0,-(SP) ; save work registers
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
|
||
MOVE.L saveHardBase(A3),A0 ; A0 <- slot base addr
|
||
ADD.L #StopWatch+SWStatusReg,A0 ; point to stapwatch status register
|
||
|
||
; detect the 1 -> 0 transition of VSP~ signifying we've entered the vertical sync pulse state
|
||
|
||
@0 BFEXTU (A0){29:1},D0
|
||
CMP.B #1,D0
|
||
BNE.S @0
|
||
|
||
; detect the 0 -> 1 transition of VSP~ signifying we've exited the vertical sync pulse state
|
||
|
||
@1 BFEXTU (A0){29:1},D0
|
||
CMP.B #0,D0
|
||
BNE.S @1
|
||
|
||
; detect the 1 -> 0 transition of VSP~ again ensuring that we've delayed at least 1 vertical blanking
|
||
; period and it is now at the beginning of the next one!
|
||
|
||
@2 BFEXTU (A0){29:1},D0
|
||
CMP.B #1,D0
|
||
BNE.S @2
|
||
|
||
|
||
MOVE.W (SP)+,SR ; restore interrupt state
|
||
MOVEM.L (SP)+,A0/D0 ; restore work registers
|
||
RTS
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* JMFBSetDepth sets the JMFB up for the requested depth mode. The setup
|
||
* is identical to primaryinit with the following exception, the clock
|
||
* generation chip is not set up here for all modes except NTSC mode because
|
||
* the setup would be redundant. In addition it is only necessary to change
|
||
* the clock generation chip’s timing in modes that support convolution, since
|
||
* that is the only mode where more than one dot clock may be necessary.
|
||
* The dot clock for interlaced ops is 12.27 MHz and convolution ops is 4*12.27 MHz.
|
||
*
|
||
* The depth has already been range checked before getting here and
|
||
* the requested mode should have already been saved!!
|
||
*
|
||
* JMFBSetDepth is broken up into 8 main steps:
|
||
*
|
||
* 1. Range check the requested mode (should have been checked previously).
|
||
* 2. Get a pointer to the right setup parameters as a f(depth)
|
||
* 3. Setup CLUT.
|
||
* 4. Setup clock generator chip if NTSC and convolved mode.
|
||
* 5. Reset JMFB.
|
||
* 6. Setup Stopwatch (timing generation).
|
||
* 7. Start VRAM refresh.
|
||
* 8. Start video transfers
|
||
*
|
||
* Called by:
|
||
*
|
||
* VidReset, SetVidMode
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _SwapMMUMode, GetClockType
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* D1 - depth mode, later used for other things
|
||
* A3 - pointer to private storage, later used for other things
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Locally used:
|
||
* D0 - scratch
|
||
* D1 - scratch
|
||
* D2 - used to fix A0 if we're NTSC convolved. (only mode that still has Natl)
|
||
* A0 - pointer to hw setup parameters for requested mode.
|
||
* A1 - pointer to hw control registers
|
||
* A2 - pointer to the JMFB base (JMFB CSR)
|
||
* A3 - holds a copy of the pointer to slot base addr
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* 1. Note it is important that A3 be the pointer to driver private storage
|
||
* prior to calling WaitVSync.
|
||
*
|
||
* 2. Since most monitor types have the same dot clock requirements across
|
||
* all modes, it is redundant to resetup the clock each time that a mode
|
||
* change occurs. The exception to this are the NTSC modes that are doing
|
||
* convolution. In this mode a 49.08 MHz clock is used in 1,2,4, and 8 bit
|
||
* modes, however a 12.27 MHz clock is used in 24 bpp mode (since we will
|
||
* gracefully default to normal interlaced ops in that mode). To take
|
||
* advantage of this space saving opportunity (~500 bytes), we must live
|
||
* with 2 hardships. First we must fix the pointer to the hw setup params
|
||
* if we're in the mode that has the extra data (convolution), since all
|
||
* data blocks are assumed to be fixed in size and equal to the blocks that
|
||
* don't have the National (or Endeavor) parameters. Second, we must
|
||
* special case this mode out in the setup section, so we can adapt to the
|
||
* different size hw setup blocks.
|
||
*
|
||
*******************************************************************
|
||
JMFBSetDepth
|
||
MOVEM.L D0-D2/A0-A4,-(SP) ; save regs we are using
|
||
CMP #Depth24BPP,D1 ; depth too big?
|
||
BGT NoDepth ; =>yes, just exit
|
||
|
||
MOVE.W csMode(A2),saveMode(A3) ; save mode number
|
||
|
||
MOVE.L saveVidParms(A3),A0 ; get pointer to parms for this mode
|
||
|
||
CMP #Depth1BPP,D1 ; test for 1 BPP mode
|
||
BEQ.S @DoIt
|
||
CMP #Depth2BPP,D1 ; test for 2 BPP mode
|
||
BEQ.S @2BPP
|
||
CMP #Depth4BPP,D1 ; test for 4 BPP mode
|
||
BEQ.S @4BPP
|
||
CMP #Depth8BPP,D1 ; test for 8 BPP mode
|
||
BEQ.S @8BPP
|
||
ADD.L #D_TFBP,A0 ; use 24 BPP parameters
|
||
BRA.S @DoIt
|
||
@8BPP ADD.L #D_EBP,A0 ; use 8 BPP parameters
|
||
BRA.S @DoIt
|
||
@4BPP ADD.L #D_FBP,A0 ; use 4 BPP parameters
|
||
BRA.S @DoIt
|
||
@2BPP ADD.L #D_TBP,A0 ; use 2 BPP parameters
|
||
|
||
;
|
||
; Initialize the hardware.
|
||
;
|
||
|
||
@DoIt
|
||
MOVEQ #true32b,D0 ; change to 32 bit addressing to get
|
||
_SwapMMUMode ; at hardware
|
||
MOVE D0,-(SP) ; save past addr mode for later
|
||
|
||
MOVE.W SR,-(SP) ; get the current interrupt level
|
||
MOVEQ.L #7,D0 ; setup to get interrupt level
|
||
AND.B (SP),D0 ; D0 now holds current interrupt level
|
||
SUBQ #2,D0 ;
|
||
BGE.S @itsOK ; if >= 2 then intr level is ok
|
||
ORI.W #$0200,SR ; if <2 then raise intr level to at least 2
|
||
ANDI.W #$FAFF,SR ; may have to drop it to 2
|
||
@itsOK
|
||
BSR WaitVSync ; wait for vertical blanking
|
||
|
||
BTST #ConvOnFlag,moreGFlags(A3) ; test to see if we're convoling or not
|
||
BEQ.S @noKludge ; if we're not conv, then hw param size is ok
|
||
MOVE.W saveMode(A3),D2 ; otherwise, adjust for additional clock params
|
||
SUB #FirstVidMode,D2 ; make zero based
|
||
MULU #D_ClockParams,D2 ; we are now using a universal ROM for Endeavor and Natl so use common param size
|
||
ADD.L D2,A0 ; add to pointer to get to right table
|
||
@noKludge
|
||
|
||
MOVE.L saveHardBase(A3),A1 ; A1 <- slot base addr
|
||
MOVE.W moreGFlags(A3),D2 ; save GFlags
|
||
MOVE.L A3,A4 ; must save since it is passed to WaitVSync later
|
||
|
||
MOVE.L A1,A3 ; A3 <- slot base addr
|
||
ADD.L #CLUT+CLUTPBCR,A1 ; point to the CLUT Pixel Bus Control Register
|
||
|
||
CLR.L D0 ; to ensure that the upper 2 bytes are 0
|
||
MOVE.W (A0)+,D0 ; setup the CLUT PBCR (data table field is word sized)
|
||
MOVE.L D0,(A1) ; make a long write to hw always for this card
|
||
|
||
MOVE.L A3,A1 ; get back to the slot base addr
|
||
ADD.L #JMFB,A1 ; point to the base of the JMFB Registers
|
||
MOVE.L A1,A2 ; save for later
|
||
MOVE.W #2,D1 ; setup the 4 JMFB registers (the first one will be done outside the loop)
|
||
|
||
CLR.L D0 ; to ensure that the upper 2 bytes are 0
|
||
MOVE.W (A0)+,D0
|
||
BTST #NationalFlag,moreGFlags(A4) ; all parameters are setup for National use so...
|
||
BNE.S @writeOne ; if it's Natl, no need to do anything special
|
||
ORI.W #PIXSEL1,D0 ; else it's Endeavor and we don't want to Reset (PIXSEL1=1)
|
||
@writeOne MOVE.L D0,(A1)+
|
||
@part1 MOVE.W (A0)+,D0 ; do it (data table field is word sized)
|
||
MOVE.L D0,(A1)+ ; make a long write to hw always for this card
|
||
DBRA D1,@part1
|
||
|
||
MOVE.L A3,A1 ; get back to the slot base addr
|
||
ADD.L #Endeavor,A1 ; point to the base of the Endeavor Registers
|
||
|
||
BTST #ConvOnFlag,D2 ; test to see if we're convoling or not
|
||
BEQ.S @skipPart2
|
||
|
||
BTST #NationalFlag,moreGFlags(A4)
|
||
BNE.S @NatlSetup
|
||
MOVE.W #2,D1 ; setup the 3 Endeavor registers
|
||
|
||
CLR.L D0 ; to ensure that the upper 2 bytes are 0
|
||
@part2 MOVE.W (A0)+,D0 ; do it (data table field is word sized)
|
||
MOVE.L D0,(A1)+ ; make a long write to hw always for this card
|
||
DBRA D1,@part2
|
||
ADD.L #D_Natl,A0
|
||
BRA.S @skipPart2
|
||
|
||
@NatlSetup ADD.L #D_Endeavor,A0
|
||
MOVE.W #15,D1 ; setup the 16 National registers
|
||
|
||
CLR.L D0 ; to ensure that the upper 3 bytes are 0
|
||
@part2a MOVE.B (A0)+,D0 ; do it (data table field is byte sized)
|
||
MOVE.L D0,(A1)+ ; make a long write to hw always for this card
|
||
DBRA D1,@part2a
|
||
|
||
|
||
@skipPart2
|
||
ADD.L #JMFBCSR,A2 ; point to JMFB CSR
|
||
BTST #NationalFlag,moreGFlags(A4) ; Are we National or Endeavor
|
||
BNE.S @InitDelay ; if National, no need to reset Endeavor
|
||
MOVE.L (A2),D1
|
||
ANDI.W #MaskSenseLine,D1 ; Ensure sense lines will be written out as 000
|
||
ORI.W #PIXSEL1,D1 ; set PIXSEL1 line to start Endeavor
|
||
MOVE.L D1,(A2)
|
||
|
||
@InitDelay MOVE.W #ShortDelay,D1 ; setup delay loop count
|
||
@delayLoop
|
||
DBRA D1,@delayLoop ; wait for stable clock from Endeavor
|
||
|
||
MOVE.L (A2),D1
|
||
ANDI.W #MaskSenseLine,D1 ; Ensure sense lines will be written out as 000
|
||
ORI.W #VRSTB,D1 ; set VRSTB to start JMFB
|
||
MOVE.L D1,(A2)
|
||
|
||
MOVE.L A3,A1 ; get back to the slot base addr
|
||
ADD.L #Stopwatch,A1 ; point to the base of the Stopwatch Registers
|
||
MOVE.W #14,D1 ; setup next 15 registers (Stopwatch)
|
||
|
||
CLR.L D0 ; to ensure that the upper 2 bytes are 0
|
||
@part3 MOVE.W (A0)+,D0 ; do it (data table field is word sized)
|
||
MOVE.L D0,(A1)+ ; make a long write to hw always for this card
|
||
DBRA D1,@part3
|
||
|
||
MOVE.L #$04,(A1) ; Always do a stopwatch soft reset
|
||
MOVE.L #$05,(A1) ; Line interrupts off, Vertical Interrupts enabled and no soft reset
|
||
|
||
MOVE.L (A2),D1
|
||
ANDI.W #MaskSenseLine,D1 ; Ensure sense lines will be written out as 000
|
||
ORI.W #REFEN,D1 ; set REFEN line to start VRAM refresh
|
||
MOVE.L D1,(A2)
|
||
|
||
MOVE.L A4,A3 ; restore A3 prior to calling WaitVSync
|
||
BSR WaitVSync ; wait for one vertical blanking interval
|
||
|
||
MOVE.L (A2),D1
|
||
ANDI.W #MaskSenseLine,D1 ; Ensure sense lines will be written out as 000
|
||
ORI.W #VIDGO,D1 ; set VRSTB line to start video transfer cycle
|
||
MOVE.L D1,(A2)
|
||
|
||
MOVE.W (SP)+,SR ; restore the interrupt level
|
||
MOVE (SP)+,D0 ; restore past addr mode in D0
|
||
_SwapMMUMode
|
||
|
||
NoDepth MOVEM.L (SP)+,D0-D2/A0-A4 ; restore all regs
|
||
RTS ; return
|
||
|
||
|
||
|
||
*******************************************************************
|
||
*
|
||
* JMFBSetPage calculates the display base address from the mode and
|
||
* page number.
|
||
*
|
||
* The base of a page is at saveHardBase(A3) + defmBaseOffset + (page * RowBytes * height)
|
||
*
|
||
* See the Miscellaneous section for special convolution and interlaced processing.
|
||
*
|
||
* JMFBSetPage is broken up into 6 main steps:
|
||
*
|
||
* 1. Get the rowbytes and screenrows from the misc. param. table
|
||
* 2. Calculate base address (page num * rowbytes * screenrows)
|
||
* 3. Call GetBaseOffset to get additional offset if any and add.
|
||
* 4. If convolution blacken the phantom line (n-1)
|
||
* 5. Fix the base address if we're a 24 bit sRsrc.
|
||
* 6. Write to JMFB base address register.
|
||
*
|
||
* Called by:
|
||
*
|
||
* VidReset, SetVidMode
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* SwapMMUMode
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* D1 - mode number
|
||
* D4 - page number (zero based)
|
||
* A1 - pointer to the AuxDCE
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Locally used:
|
||
* D2 - used to save rowbytes for mode
|
||
* D3 - scratch
|
||
* D4 - used to form the hardware base address for the JMFB CSR
|
||
* D5 - used to hold the screen base address to go into privates
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* There are three cases that require special consideration in the interlaced
|
||
* modes. The first is when we are convolving and are in the underscan mode
|
||
* (512x384). In this case we don't want to display the first active half
|
||
* line in the active area. To do this we must place the qd base address
|
||
* farther into the active area of the frame buffer as defined by the JMFB
|
||
* base address. Specifically, we put the qd base address at $2000 (rowbytes
|
||
* in interlaced mode always = $400), so the qd base address is 8 lines in
|
||
* from the card base. Also, the JMFB base address must always be located
|
||
* at the third row of a 4 row block due to hw design constraints for convolution
|
||
* to work correctly (That means it can be a $c00, $1c00, $2c00, etc.). By
|
||
* placing the qd base address at $2000 and the JMFB base addr at $c00, we
|
||
* can eliminate the top half line artifact displayed in the active area of
|
||
* the underscan mode.... confused yet...I almost am again and I wrote it!
|
||
* Anyway, one last twist is that we'll blacken the entire frame buffer up
|
||
* to the start of the screen base so we won't get any undesired artifacts
|
||
* due to the 1:2:1 convolution kernal, at least not any unexpected artifacts!
|
||
* The second case is a little more subtle since it is really done from the
|
||
* GetBaseOffset utility. In 24 bpp we also want to get rid of the half line at
|
||
* the top. There is a special base offset for 24 bpp ntsc that is #2560 (one
|
||
* line into the frame buffer). By offseting qd 1 line past the JMFB base, se
|
||
* should get rid of the half line in 24 bpp too!. The third case is similar
|
||
* tho the 24 bpp case, but applies to indexed modes when there is only one
|
||
* bank of vram and we are not convolving. In that case, the JMFB base addr
|
||
* will be exactly 1 line (1024 bytes) behind qd. In this case and all indexed
|
||
* cases, black is $FF. In 24 bpp (direct mode) black is $00.
|
||
*
|
||
*******************************************************************
|
||
JMFBSetPage
|
||
|
||
MOVEM.L D0-D5/A0,-(SP) ; save all registers
|
||
|
||
MOVE D4,savePage(A3) ; save the page
|
||
MOVE saveMode(A3),D1 ; get the current "real" mode
|
||
SUB #FirstVidMode,D1 ; make it 0 based
|
||
MOVE.L saveVidParms(A3),A0 ; point to data table
|
||
MOVE.W (D_RowBytes,A0,D1*2),D2 ; get and save rowBytes
|
||
MULU D2,D4 ; calc page * rowBytes
|
||
MULU D_Height(A0),D4 ; calc page * rowBytes * height
|
||
|
||
BSR GetBaseOffset ; returns base offset in D0
|
||
ADD.L D0,D4 ; add the base offset to the page base
|
||
MOVE.L D4,D5 ; save screen base offset for later to save in savebaseaddr
|
||
|
||
MOVEQ #true32b,D0 ; change to 32 bit addressing to get
|
||
_SwapMMUMode ; at hardware
|
||
|
||
; the following section gets pretty messy for ntsc modes to blacken the top of the fb and calc the JMFB baddr
|
||
; - case1 : indexed mode and convolving > qdBAddr = $2000, JMFB BAddr = $0C00, black = $FF
|
||
; - case2 : indexed mode and noConvolve > qdBAddr = $2000, JMFB BAddr = $1C00, black = $FF
|
||
; - case3 : 24 bpp > qdBAddr = #2560, JMFB BAddr = $0000, black = $00
|
||
;
|
||
; what a mess!
|
||
|
||
BTST #Interlaced,gFlags(A3) ; check for interlaced mode (1) for special processing
|
||
BEQ.S @Continue ; use normal noninterlaced base offset value
|
||
BTST #RAM512KFlag,gFlags(A3) ; check for 2nd bank of memory (0)
|
||
BEQ.S @ConvOn ; can't do convolution w/o the 2nd bank
|
||
SUB.L #OBM12CRB,D4 ; we're indexed and we can do this since all rowbytes are the same!
|
||
BRA.S @BlackTop ; do the common blacktop stuff for indexed modes
|
||
|
||
@ConvOn CMP.B #Mode8BPP,D1 ; test if mode is > 8 BPP
|
||
BGT.S @ntsc24 ; can't do convolution in 24 BPP mode
|
||
SUB.L #convBOfix,D4 ; form the magic JMFB base address (always $1400 less than screen base)
|
||
|
||
@BlackTop MOVE.L saveHardBase(A3),A0 ; add the card base so we are now pointing to the line
|
||
ADD.W #defmBaseOffset12,D2 ; get the number of bytes to blacken (from start of frame buffer to
|
||
; start of screen.
|
||
LSR #2,D2 ; convert rowbytes to rowlongs
|
||
SUBQ #1,D2 ; make it 0 based for the DBRA
|
||
@NxtLong MOVE.L #$FFFFFFFF,(A0)+ ; write black for the entire phantom line
|
||
DBF D2,@NxtLong
|
||
BRA.S @Continue
|
||
|
||
@ntsc24
|
||
SUB.L #TFBM12CRB,D4 ; JMFB base address is 1 line behind qd for 24 bpp
|
||
MOVE.L saveHardBase(A3),A0
|
||
ADD.W #specBaseOffset12,D2
|
||
LSR #2,D2
|
||
SUBQ #1,D2
|
||
@aNxtLong MOVE.L #$00000000,(A0)+ ; write black for the entire phantom line ($00 for 24 bpp, $FF for indexed)
|
||
DBF D2,@aNxtLong
|
||
|
||
|
||
@Continue
|
||
ADD.L saveHardBase(A3),D5 ; add base address for card
|
||
|
||
BTST #sRsrc32Bit,GFlags(A3) ; check for 32 bit sRsrc (base address = Fsxx xxxx)
|
||
BNE.S @saveIt ; if it is 32 bit sRsrc page base address is setup right
|
||
BFEXTU D5{4,4},D3 ; else it's 24 bit (Fssx xxxx) so get slot number
|
||
BFINS D3,D5{8,4} ; and insert it into D5 to form Fssx xxxx
|
||
|
||
@saveit MOVE.L D5,saveBaseAddr(A3) ; return the base address
|
||
|
||
; Now set the hardware by writing the offset in longs to the proper registers.
|
||
|
||
MOVE.L saveHardBase(A3),A0 ; get the card base addr
|
||
ADD.L #JMFB,A0 ; point to JMFB Control Space
|
||
ADD.L #JMFBVideoBase,A0 ; point to the Video Base register
|
||
CMP.B #Mode8BPP,D1 ; test if mode is > 8 BPP.
|
||
BLE.S @indexMode ; if 1,2,4, or 8 bpp we're all done so skip next instruction
|
||
ASR.L #2,D4 ; it's 24 bpp, first /4 for pixel twist
|
||
MULU.L #3,D4 ; multiply by 3 to finish the 3/4 pixel twist
|
||
LSR.L #1,D4 ; one more /2 for interleaving
|
||
|
||
@indexMode
|
||
LSR.L #5,D4 ; strip lower 5 bits (bits 0:4 are implied 0)
|
||
MOVE.L D4,(A0) ; base offset is the first register
|
||
|
||
_SwapMMUMode
|
||
|
||
MOVEM.L (SP)+,D0-D5/A0 ; restore all registers
|
||
RTS ; and return
|
||
|
||
*******************************************************************
|
||
*
|
||
* GetBaseOffset returns the appropriate base address as a function of monitor and mode. There
|
||
* are currently three alternatives:
|
||
*
|
||
* - defmBaseOffset - used for standard, and Rubik
|
||
* - defmBaseOffsetBS - used for the Big Screens (Kong and Portrait) due to VRAM bank crossing
|
||
* - defmBaseOffset12 - used for all overscan interlaced and convolved NTSC modes except 24 bpp.
|
||
* - specBaseOffset12 - used in ntsc 24 bpp modes.
|
||
*
|
||
* GetBaseOffset is broken up into 3 main steps:
|
||
*
|
||
* 1. If small screen use defmBaseOffset
|
||
* 2. If big screen use defmBaseOffsetBS
|
||
* 3. If Interlaced use defmBaseOffset12
|
||
*
|
||
* Called by:
|
||
*
|
||
* GetPageBase, JMFBSetPage
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* None.
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A3 - dCtlStorage pointer used to get at SaveMode, BigScreen, and Interlaced
|
||
*
|
||
* Output:
|
||
; D0 - returns the base offset value
|
||
*
|
||
* Locally used:
|
||
; None.
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GetBaseOffset
|
||
|
||
BTST #Interlaced,gFlags(A3) ; determine if it's NTSC or not
|
||
BNE.S @Interlaced ; if it is branch and do the Interlaced modes
|
||
|
||
BTST #BigScreen,gFlags(A3) ; determine if it's a Big Screen (Kong or Portrait)
|
||
BEQ.S @SmallScreen ; if it is not then get the small screen base offset
|
||
MOVE.L #defmBaseOffsetBS,D0 ; it's the Big Screen, so use defBaseOffsetBS
|
||
BRA.S GBODone ; all done so get out
|
||
|
||
@SmallScreen
|
||
MOVE.L #defmBaseOffset,D0 ; it's the Small Screen, so use defBaseOffset
|
||
BRA.S GBODone ; all done so get out
|
||
|
||
@Interlaced
|
||
CMP.W #FourthVidMode,saveMode(A3) ; check to see if we're greater than 8 bpp
|
||
BGT.S @ntsc24bpp ; if > 8 bpp, we must be 24 so branch
|
||
MOVE.L #defmBaseOffset12,D0 ; use the overscan NTSC base offset
|
||
BRA.S GBODone ; all done so get out
|
||
|
||
@ntsc24bpp
|
||
MOVE.L #specBaseOffset12,D0 ; use a base offset that works for 24 bpp modes
|
||
|
||
GBODone
|
||
RTS
|
||
|
||
*******************************************************************
|
||
*
|
||
* GrayScreen writes a 50% gray dither pattern to the frame buffer.
|
||
* The pattern used and the memory that is grayed is a f(mode).
|
||
*
|
||
* GrayScreen is broken up into 3 main steps:
|
||
*
|
||
* 1. Get the mode, the pattern, and the page size
|
||
* 2. Form a 32 bit address in the fb pointer.
|
||
* 3. Draw the screen (different code is used for 24 bpp than for indexed modes).
|
||
*
|
||
* Called by:
|
||
*
|
||
* VidReset, GrayPage
|
||
*
|
||
* Traps and Utilities called:
|
||
*
|
||
* _SwapMMUMode
|
||
*
|
||
* Register usage:
|
||
*
|
||
* Input:
|
||
* A3 - pointer to the private storage
|
||
*
|
||
* Output:
|
||
* None.
|
||
*
|
||
* Locally used:
|
||
* D1 - scratch
|
||
* D2 - used to hold rowlongs-1
|
||
* D3 - used to hold screenrows
|
||
* D4 - used to hold rowbytes
|
||
* D5 - 50% gray dither pattern (it's a f(mode))
|
||
*
|
||
* A0 - points to the fb during writes
|
||
* A1 - points to hw misc params
|
||
* - later points to fb row starting addresses
|
||
*
|
||
* Miscellaneous:
|
||
*
|
||
* None.
|
||
*
|
||
*******************************************************************
|
||
GrayScreen
|
||
|
||
MOVEM.L D0-D6/A0-A1,-(SP) ; save all registers
|
||
MOVE saveMode(A3),D1 ; get the mode
|
||
SUB #FirstVidMode,D1 ; make it 0 based
|
||
MOVE.W D1,D3 ; make a copy of it
|
||
LEA Pats,A1 ; get a pointer to the pattern table
|
||
MOVE.L (A1,D3*4),D5 ; D5 = the proper pattern
|
||
MOVE.L saveVidParms(A3),A1 ; point to data table
|
||
MOVE (D_RowBytes,A1,D1*2),D4 ; D4 = rowbytes for the screen
|
||
MOVE D_Height(A1),D3 ; D3 = screen height
|
||
SUBQ #1,D3 ; make it 0 based
|
||
|
||
|
||
MOVE.L saveBaseAddr(A3),A1 ; point to the current page
|
||
BTST #sRsrc32Bit,GFlags(A3) ; Check to see if
|
||
BNE.S @NoMask ; 32 bit address=1, 24 bit address=0
|
||
MOVE.L A1,D0 ; move into data register so we can and it
|
||
ANDI.L #$FF0FFFFF,D0 ; Fssxxxxx -> Fs0xxxxx (since we always write in 32 bit addressing)
|
||
MOVE.L D0,A1 ; move it back
|
||
@NoMask
|
||
|
||
MOVEQ #true32b,D0 ; draw in 32 bit mode
|
||
_SwapMMUMode
|
||
|
||
CMP.B #Mode24BPP,D1 ; check for 24 BPP mode
|
||
BEQ.S gScrn24 ; do 24 bit gray screen in 24 BPP
|
||
|
||
|
||
; 1,2,4, and 8 BPP gray screen code
|
||
|
||
NxtRow1 MOVE.L A1,A0 ; get next row
|
||
MOVE.W D4,D2 ; get bytes per row
|
||
LSR #2,D2 ; get longs per row
|
||
MOVE.W D2,D7 ; save longs per row for later
|
||
SUBQ #1,D2 ; make count 0 based
|
||
NxtLong1 MOVE.L D5,(A0)+ ; write gray
|
||
DBF D2,NxtLong1 ; for entire width of row
|
||
NOT.L D5 ; get inverse gray for next row
|
||
ADD.W D4,A1 ; bump to next row
|
||
DBF D3,NxtRow1 ; until no more rows
|
||
|
||
BTST #Interlaced,GFlags(A3) ; check to see if we're doing interlaced
|
||
BEQ.S GSDone ; if we're not then all done
|
||
BTST #UnderScanFlag,moreGFlags(A3) ; since we're doing interlaced, check for uScan
|
||
BEQ.S GSDone ; if we're not uScan, then we're oScan and all done
|
||
|
||
MOVE.W D7,D2 ; get longs per row
|
||
BTST #PALFlag,moreGFlags(A3)
|
||
BNE.S @PAL
|
||
MULU.W #50,D2 ; multiply by scan lines +1
|
||
BRA.S @continue
|
||
@PAL MULU.W #58,D2
|
||
@continue SUBQ #1,D2 ; make D2 0 based for dbra
|
||
|
||
@BlackBot MOVE.L #-1,(A0)+ ; black out the bottom section
|
||
DBRA D2,@BlackBot
|
||
|
||
BRA.S GSDone
|
||
|
||
; 24 BPP gray screen code
|
||
|
||
gScrn24
|
||
|
||
NxtRow24
|
||
MOVE.L A1,A0 ; get next row
|
||
MOVE.W D4,D2 ; get bytes per row
|
||
LSR #2,D2 ; get longs per row
|
||
MOVE.W D2,D7 ; save longs per row for later
|
||
SUBQ #1,D2 ; make count 0 based
|
||
NxtLong24 MOVE.L D5,(A0)+ ; write gray
|
||
NOT.L D5 ; invert next pixel for 24 BPP
|
||
DBF D2,NxtLong24 ; for entire width of row
|
||
NOT.L D5 ; invert for next row
|
||
ADD.W D4,A1 ; bump to next row
|
||
DBF D3,NxtRow24 ; until no more rows
|
||
|
||
BTST #Interlaced,GFlags(A3) ; check to see if we're doing interlaced
|
||
BEQ.S GSDone ; if we're not then all done
|
||
BTST #UnderScanFlag,moreGFlags(A3) ; since we're doing interlaced, check for uScan
|
||
BEQ.S GSDone ; if we're not uScan, then we're oScan and all done
|
||
|
||
MOVE.W D7,D2 ; get longs per row
|
||
BTST #PALFlag,moreGFlags(A3)
|
||
BNE.S @PAL
|
||
MULU.W #50,D2 ; multiply by scan lines +1
|
||
BRA.S @continue
|
||
@PAL MULU.W #58,D2
|
||
@continue SUBQ #1,D2 ; make D2 0 based for dbra
|
||
|
||
@BotBlack CLR.L (A0)+ ; black out the bottom section
|
||
DBRA D2,@BotBlack
|
||
GSDone
|
||
_SwapMMUMode ; swap back to previous addr mode (do is still valid)
|
||
MOVEM.L (SP)+,D0-D6/A0-A1 ; restore registers
|
||
RTS ; and return
|
||
|
||
Pats DC.L OneBitGray,TwoBitGray,FourBitGray,EightBitGray,TwentyFourBitGray
|
||
|
||
;-------------------------------------------------------------
|
||
; The Interrupt handler for Trident card
|
||
;-------------------------------------------------------------
|
||
; The interrupt Handler
|
||
; On entry A1 contains the pointer to the vsync clear register
|
||
; Note that the interrupt handler preserves D0-D3 and A0-A3.
|
||
|
||
BeginIH
|
||
|
||
MOVEM.L D1-D2/A0-A1,-(SP) ; save registers myself
|
||
|
||
MOVEQ #true32b,D0 ; force to 32 bit addressing mode
|
||
|
||
MOVE.L JSwapMMU,A0 ; call SwapMMUMode
|
||
JSR (A0)
|
||
MOVEM.L (SP)+,D1-D2/A0-A1 ; restore all registers
|
||
|
||
MOVE.L D1,-(SP) ; save working register
|
||
@waitNoVFP
|
||
MOVE.L SWStatusReg-SWICReg(A1),D1 ; read the Stopwatch Status Register
|
||
ANDI #$8,D1 ; wait for the Front Porch state to exit
|
||
BNE.S @waitNoVFP ; continue to poll until we exit VFP (~90 usec)
|
||
|
||
MOVE.L (SP)+,D1
|
||
|
||
MOVE.L #1,(A1) ; clear interrupt from card
|
||
|
||
MOVEM.L D1-D2/A0-A1,-(SP) ; save registers
|
||
MOVE.L JSwapMMU,A0 ; call SwapMMUMode
|
||
JSR (A0)
|
||
MOVEM.L (SP)+,D1-D2/A0-A1 ; restore all registers
|
||
|
||
MOVE.L A1,D0 ; copy base addr into data register
|
||
|
||
; D0 = $Fssxxxxx
|
||
ROL.L #8,D0 ; D0 <- $sxxxxxFs Convert the address into
|
||
AND #$0F,D0 ; D0 <- $sxxx000s the slot number.
|
||
|
||
MOVE.L JVBLTask,A0 ; call the VBL task manager
|
||
JSR (A0) ; with slot # in D0
|
||
|
||
MOVEQ #1,D0 ; signal that int was serviced
|
||
RTS ; and return to caller
|
||
|
||
;-------------------------------------------------------------
|
||
; TERROR ROM Support (for loading at GetDriver time)
|
||
;-------------------------------------------------------------
|
||
If ForRom Then
|
||
Export JMFBDrvrSize
|
||
JMFBDrvrEnd
|
||
JMFBDrvrSize
|
||
Dc.l JMFBDrvrEnd-JMFBDrvr
|
||
EndP
|
||
Endif
|
||
End |