mirror of
https://github.com/elliotnunn/supermario.git
synced 2025-02-20 10:28:57 +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
|