mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-20 12:30:40 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
3399 lines
129 KiB
Plaintext
3399 lines
129 KiB
Plaintext
;
|
|
; File: DAFBDriver.a
|
|
;
|
|
; Contains: This file contains the video driver for use by the Macintosh
|
|
; OS for the DAFB hardware.
|
|
;
|
|
; Written by: David Fung/Mike Puckett
|
|
;
|
|
; Copyright: © 1990-1993 by Apple Computer, Inc. All rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM7> 08-03-93 jmp Changed the reference names of the multiscan display constants
|
|
; to their new names.
|
|
; <SM6> 11/5/92 SWC Changed VideoEqu.a->Video.a and ShutdownEqu.a->Shutdown.a.
|
|
; <SM5> 11/2/92 kc Don't include SonicEqu.a.
|
|
; <SM4> 10-29-92 jmp (jmp,H26) Fixed a branching problem in the PageMode
|
|
; enabling/disabling code in VidOpen.
|
|
; <SM3> 10-17-92 jmp (jmp,H25) Fixed a subtle bug that would only occur when the CPU
|
|
; was set up to be in 24-bit mode -- the problem had to do with my
|
|
; putting the machine in 32-bit mode and calling a slot manager
|
|
; trap (_sGetBlock) that ended up allocating 32-bit memory in a
|
|
; 24-bit System heap. OoopsÉ.
|
|
; <SM2> 10-13-92 jmp (jmp,H24) Fixed a problem in SetDepth where I was clearing the
|
|
; ClkSel bit in the DAFBClkCfg register. For the NSC-8534 this
|
|
; bit must be a one, and for the NSC-8531 it must be a zero.
|
|
; Also, added a line of code that got ÒlostÓ from the Zydeco
|
|
; sources.
|
|
; <SM1> 10/6/92 GDW New location for ROMLink tool.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; Pre-ROMLink comments begin here.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; <SM9> 09-29-92 jmp (jmp,H23) Added about a 1-µSec delay between SetEntries R-G-B
|
|
; writes to the Antelope CLUT/DAC (i.e., unlike the Brooktree and
|
|
; AMD CLUT/DACs, the Antelope parts donÕt use dual-ported RAM
|
|
; internally).
|
|
; (jmp,H22) The TimingAdj register wasnÕt being set up properly in
|
|
; PAL 16bpp FF/ST with Antelope parts. Fixed this.
|
|
; (jmp,H21) Added more support for the Antelope (AT&T/Sierra)
|
|
; CLUT/DAC used on Wombat/WLCD.
|
|
; <SM8> 09-03-92 jmp (jmp,H20) Added initial support for the AT&T CLUT/DAC to be used
|
|
; in Wombat/WLCD systems.
|
|
; <SM7> 07-14-92 jmp (jmp,H18) Fixed a minor bug in ChkMode where I was allowing
|
|
; 32bpp to be set on Rubik for a WombatDAFB.
|
|
; (jmp,H17) Added in support to make the DAFBDriver function
|
|
; correctly among Spike, Eclipse, Zydeco, and all Wombat/WLCD
|
|
; CPUs.
|
|
; (jmp,H16) Added more Wombat support as well as continued with
|
|
; general optimizations.
|
|
; (jmp,H15) Tightened up the Wombat TimingAdj adjustment table
|
|
; (used bytes instead of words).
|
|
; (jmp,H14) Added first-pass support for the Wombat version of
|
|
; DAFB.
|
|
; <SM6> 6/18/92 KW (jmp,H13) Eliminated yet even more of the old DAFBVidParams
|
|
; fields, so I adjusted the code accordingly.
|
|
; <SM5> 6/4/92 KW (jmp,H12) Fixed a problem where I wasnÕt setting up the timing
|
|
; adjust register in the Brooktree DAC case. Oops! (jmp,H11) Made
|
|
; the code that deals with the DAFB vidParams ÒsmarterÓ due my
|
|
; compacting vidParams tables. This kind of work will continue
|
|
; throughout Wombat development. (jmp,H10) Cleaned up the
|
|
; interrupt handler a little, cleaned up WaitVSync a little, fixed
|
|
; the Òlittle table of countsÓ problem from Zydeco, etcÉ.
|
|
; <SM4> 5/16/92 kc Roll in Horror Changes. Comments follow:
|
|
; <H9> 02/20/92 jmp (jmp,Z51) Fixed a problem in the SetDepth where I wasnÕt always
|
|
; selecting the correct clock. This problem surfaced due to a
|
|
; change in the AC824A (aka AC823).
|
|
; <H8> 01/22/92 jmp (jmp,Z50) Updated the original ÒNo ConnectÓ code to take full
|
|
; advantage of the newly-defined extended sense codes. Changed
|
|
; the name from ÒNoConnectÓ to ÒAltSense.Ó
|
|
; <H7> 01/11/92 jmp Added rudimentary support for the newly-defined extended sense
|
|
; codes.
|
|
; <H6> 12/17/91 jmp Eliminated some code in GrayScreen that handled base addresses
|
|
; that moved across depths, as it is no longer needed.
|
|
; <H5> 11/25/91 jmp The vidParams moved from the functional to the board sRsrc to
|
|
; save space -- updated the driver accordingly.
|
|
; <H4> 11/12/91 jmp Quit forcing the bitdepth back to 1bpp in SetDefaultMode.
|
|
; <H3> 11/05/91 jmp Added support for 19Ó Displays.
|
|
; <3> 3/31/92 JSM Rolled this file into Reality.
|
|
; <2> 2/14/92 kc Fix "Label defined on next word boundary" assembler warning.
|
|
; <50> 01/20/92 jmp Updated the original ÒNo ConnectÓ code to take full advantage of
|
|
; the newly-defined extended sense codes. Changed the name from
|
|
; ÒNoConnectÓ to ÒAltSense.Ó
|
|
; <49> 01/09/92 jmp Added rudimentary support for the newly-defined extended sense
|
|
; codes.
|
|
; <48> 12/17/91 jmp Eliminated some code in GrayScreen that handled base addresses
|
|
; that moved across depths, as it is no longer needed.
|
|
; <47> 11/08/91 jmp Quit forcing the bitdepth back to 1bpp in SetDefaultMode.
|
|
; <46> 11/05/91 jmp Added preliminary support for 19Ó Displays.
|
|
; <45> 10/16/91 jmp Added a check in the video open routine that determines whether
|
|
; video (i.e., sync) is currently on or not. If itÕs off, then we
|
|
; now turn it back on. This was added to support turning video
|
|
; back on immediately in the event that the video driver is closed
|
|
; and needs to be opened again during ÒnormalÓ operation of the
|
|
; CPU.
|
|
; <44> 09/17/91 jmp Needed to ensure that the 100 Mhz clock was being shut off when
|
|
; Ògrounding outÓ the ECL clock signals.
|
|
; <43> 09/17/91 jmp Added support for Ògrounding outÓ the ECL clock signals in
|
|
; software using the AMD-ACDC for Zydeco/Spike33 CPUs.
|
|
; <42> 09/13/91 jmp Added support for 16pp on Rubik displays when only 512K of vRAM
|
|
; is around in preparation for Spike33s.
|
|
; <41> 8/9/91 jmp Just cleaned up some comments and line-spacings.
|
|
; <40> 8/9/91 jmp When I removed the NeedsGoodBye control call, I didnÕt remove
|
|
; the extra check. So, I removed that now.
|
|
; <39> 8/9/91 jmp Fixed a VERY minor bug in VidOpen where I was using D0 instead
|
|
; of D2 to get the monID.
|
|
; <38> 8/9/91 jmp Added support to fix a problem with NTSC & PAL family modes
|
|
; where changing the amount of vRAM didnÕt cause PrimaryInit to
|
|
; re-validate the SP_LastConfig pRAM byte. Also, enabled/disabled
|
|
; PageMode in VidOpen depending on the state of pageMode pRAM bit.
|
|
; <37> 8/7/91 jmp Added 16bpp support for all displays.
|
|
; <36> 7/30/91 jmp Removed the support for the NeedsGoodBye control call.
|
|
; <35> 7/29/91 jmp Started validating the mode passed into the SetDefaultMode call;
|
|
; none of our previous video drivers have done this. Also, fixed
|
|
; the gamma-correction code used on depth switches so that
|
|
; mono-only devices are only corrected on the blue channel (as
|
|
; they should be).
|
|
; <34> 7/13/91 jmp Added routines to extend the factory burn-in no-connect
|
|
; detection routines so that ANY display supported by DAFB could
|
|
; be used.
|
|
; <33> 7/11/91 jmp God, I hate last minute code changes!
|
|
; <32> 7/11/91 jmp Yet even more intelligent page-mode handling coded was added.
|
|
; <31> 7/11/91 jmp Added even more intelligent code for enabling & disabling page
|
|
; mode.
|
|
; <30> 7/11/91 jmp Added code to more intelligently handle the enabling & disabling
|
|
; of page mode.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; Pre-Zydeco ROM comments begin here.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; <29> 6/29/91 jmp Added support for the alternate AC842A-compatible timing adjust,
|
|
; horizontal active line, and horizontal front porch DAFB
|
|
; parameters.
|
|
; <28> 6/27/91 jmp Fixed the Set16bpp call so that it now supports the case where
|
|
; 16bpp mode is always non-blocked.
|
|
; <27> 6/26/91 jmp Rewrote the ACDC-whacking code to be more AC842A (AMD) friendly.
|
|
; <26> 6/25/91 jmp Fixed a problem in 16bpp DirectSetEntries and fixed the problem
|
|
; with 16bpp not sticking.
|
|
; <25> 6/24/91 jmp Added support for 16bpp Vesuvio & RGB Portrait displays.
|
|
; <24> 6/17/91 jmp Fixed a type in the Òmemory leakÓ fix in SetGamma that I ÒfixedÓ
|
|
; last time.
|
|
; <23> 6/10/91 jmp Fixed a Òmemory leakÓ bug in SetGamma when changing the size of
|
|
; the current gamma table (i.e., from size 3 to 1, or vice-versa).
|
|
; This caused programs like MacroMind Director 2.0 to get
|
|
; out-of-memory errors after playing movies that cycled gamma
|
|
; (e.g., for screen fades).
|
|
; <22> 6/7/91 jmp Fixed a bug in SetEntries where I had the sense of my
|
|
; error-checking backwards. This caused programs like Color
|
|
; Studio 1.11 & QuarkXPress 3.0 to hose the System Palette when
|
|
; setting a single entry.
|
|
; <21> 5/25/91 jmp The close routine was NOT 32-bit clean, and bus-errored when
|
|
; called. So, I fixed it.
|
|
; <20> 5/24/91 jmp Added support for enabling/disabling sync-on-green.
|
|
; <19> 5/22/91 jmp Went back to the more forgiving gamma correction strategy so
|
|
; that the gamma tables can be shared among the various built-in
|
|
; videos. This is okay, for now, since all the built-in videos
|
|
; have similar DACs.
|
|
; <18> 5/15/91 jmp WasnÕt cleaning up the stack on exit from GetEntries input
|
|
; errors. VidReset wanÕt passing the right value to DAFBSetDepth
|
|
; (i.e., indexed mode value vs. bpp value). And GetPage wasnÕt
|
|
; range-checking the input mode properly.
|
|
; <17> 5/10/91 jmp Due to the fact that interrupt status registers are NOT inverted
|
|
; as originally assumed, the WaitVSync code could have hung
|
|
; forever in some cases; fixed that problem. In Get/SetEntries
|
|
; fixed the fact that some apps are NOT 32-bit clean; i.e., they
|
|
; pass in a 24-bit CTabHandleÕs MasterPointer as a Pointer.
|
|
; Optimizations: Tightened up the WaitVSync code; changed several
|
|
; Move.bÕs and Move.wÕs to MoveqÕs where applicable. Used scaling
|
|
; in the VidStatus jumptable (i.e., like the VidCtl jumptable).
|
|
; Added SuperVGA support. Now check for 25 vs. 33 MHz CPU
|
|
; operation the new, better way. Code reveiw changes: Cleaned up
|
|
; the error-handling code in VidOpen; tightened up the code in
|
|
; VidOpen that builds a linear gamma table; cleaned up the
|
|
; ST-corrected screen baseAddr code; and swapped to 32-bit
|
|
; addressing mode in VidClose in order to idle DAFB.
|
|
; <16> 4/23/91 jmp Fixed a bug in SetVidMode where I was trashing A0. Also, quit
|
|
; jumping thru jSwapMMU and started using _SwapMMUMode, except in
|
|
; the interrupt handler. Started using monIDs instead of spIDs
|
|
; where possible for config testing -- less compares. Fixed a bug
|
|
; in ChkMode where I was using Cmp.wÕs instead of Cmp.bÕs.
|
|
; <15> 4/19/91 jmp The gamma correction code was doing very bad things. First, it
|
|
; was always allowing TFB-style tables (i.e., non-hardware
|
|
; specific tables) to pass through. Second, it was building
|
|
; linear ramps backwards. In SetVidMode, I added 3-channel gamma
|
|
; correction code due to the 6500¡K simulation for Vesuvio &
|
|
; GoldFish. I also fixed a bug in SetGamm where we were not
|
|
; setting the new gamma table when in direct mode. Finally, I now
|
|
; synthesize a linear gamma table on the fly in VidOpen if a gamma
|
|
; directory doesnÕt exist (i.e., for NTSC, PAL, and VGA).
|
|
; <14> 4/3/91 jmp Moved the Bsr to WaitVSync to just before the DAFBReset sequence
|
|
; in DAFBSetDepth. This reduces the problem with the display
|
|
; ÒjumpingÓ when switching bit-depths. The most notable offender
|
|
; is MacsBug when stepping.
|
|
; <13> 4/1/91 jmp Removed support for DAFB 1.
|
|
; <12> 3/25/91 jmp I was not saving the monitor ID at open time for
|
|
; gamma-correction checking. I was also not writing to the
|
|
; correct guns on mono-only displays (i.e., I was clearing red,
|
|
; setting green, and not touching blue; should have been clearing
|
|
; red & green, and setting blue). Fixed a bug in three-channel
|
|
; direct CLUTs (wasnÕt actually pointing to blue). Fixed a bug in
|
|
; indexed SetEntries where I was jumping into the RBV video driver
|
|
; due to a common label.
|
|
; <11> 3/18/91 jmp Fixed ÒfalseÓ tops and bottoms in the convolved screen-clearing
|
|
; code. Fixed a problem in SetEntries where A0 was potentially
|
|
; being trashed.
|
|
; <10> 3/4/91 jmp Fixed 1bpp Rubik Display problem (i.e., first line of vRam not
|
|
; being cleared).
|
|
; <9> 2/25/91 jmp Changed the interrupt handling code to use CrsrLine instead of
|
|
; VBL because CrsrLine is programmable. Added a Bsr to
|
|
; DAFBWaitVSync in DAFBDirectClutSet. SetEntries was not 32-bit
|
|
; clear as we were not StripAddressÕing the csTable pointer.
|
|
; <8> 2/15/91 jmp Fixed bug in SetEntries where an input error would have
|
|
; corrupted the stack (i.e., not popping saved register off
|
|
; stack). Fixed screen graying code to work properly with the
|
|
; convolved modes only supporting 4/8bpp. Conditionalized so that
|
|
; when new DAFBs are around, the coding effort will be minimal.
|
|
; Added check for 33 vs. 25 Mhz operation.
|
|
; <7> 2/10/91 jmp Fixed screen base address calculations (for ST modes). Fixed
|
|
; the mode validation (ChkMode) code.
|
|
; <6> 2/3/91 jmp Updated GrayScreen for NTSC and PAL ST modes (including blacking
|
|
; around the sides).
|
|
; <5> 1/30/91 jmp Just replaced the in-line reset instructions with the DAFBReset
|
|
; macro defined in RBVDepVideoEqu.a.
|
|
; <4> 1/24/91 jmp Finished a first stab at DAFBGetEntries.
|
|
; <3> 1/21/91 jmp Incremental change -- fixed/added the IsMono code.
|
|
; <2> 1/14/91 DAF Added file for first time, but needed to adjust the comment!
|
|
; <1> 1/14/91 DAF First checked in.
|
|
;
|
|
|
|
STRING C
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
|
|
INCLUDE 'DockingEqu.a'
|
|
INCLUDE 'EgretEqu.a'
|
|
INCLUDE 'GestaltEqu.a'
|
|
INCLUDE 'GestaltPrivateEqu.a'
|
|
INCLUDE 'HardwarePrivateEqu.a'
|
|
INCLUDE 'IOPrimitiveEqu.a'
|
|
INCLUDE 'PowerPrivEqu.a'
|
|
INCLUDE 'ROMEqu.a'
|
|
INCLUDE 'Video.a'
|
|
INCLUDE 'SlotMgrEqu.a'
|
|
INCLUDE 'ShutDown.a'
|
|
; INCLUDE 'SonicEqu.a'
|
|
INCLUDE 'UniversalEqu.a'
|
|
|
|
INCLUDE 'DepVideoEqu.a'
|
|
PRINT ON
|
|
|
|
SEG '_sDAFBDriver'
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
MACHINE MC68020
|
|
|
|
; This is device storage which is stored in the dCtlStorage field of the AuxDCE.
|
|
|
|
DAFBVidPrivates RECORD 0
|
|
saveBaseAddr DS.L 1 ; the screen base address (NOT ST corrected!)
|
|
saveScreenBase DS.L 1 ; ST corrected version of saveBaseAddr.
|
|
saveSQElPtr DS.L 1 ; the SQ element pointer (for _SIntRemove)
|
|
saveGammaPtr DS.L 1 ; the pointer to the Gamma correction table
|
|
saveGamDispPtr DS.L 1 ; the pointer to the Gamma block
|
|
saveVDACBase DS.L 1 ; the base addr of the VDAC
|
|
saveDAFBBase DS.L 1 ; the base addr of the DAFB
|
|
saveVidPtr DS.L 1 ; pointer to a big block of DAFB video parameters
|
|
GFlags DS.B 1 ; flags word (in hi-byte)
|
|
wombatFlag Ds.b 1 ; (hidden WombatDAFB flag)
|
|
has16bppACDC Ds.b 1 ; true if AC842A is around
|
|
pageModeSet Ds.b 1 ; true if the pRam PageMode enable bit is set
|
|
saveMode DS.W 1 ; the current mode setting (in lo-byte)
|
|
saveMonID DS.W 1 ; monitor type ID (in lo-byte)
|
|
saveSlotId DS.B 1 ; spID of video sRsrc
|
|
hasLin16bppCLUT Ds.b 1 ; true if AC842A is Antelope
|
|
DAFBVidPrivSize EQU *
|
|
ENDR
|
|
|
|
LDAFBDriver MAIN EXPORT
|
|
;-------------------------------------------------------------------
|
|
; Video Driver Header
|
|
;-------------------------------------------------------------------
|
|
;
|
|
DAFBDrvr
|
|
DC.W $4C00 ; ctl,status,needsLock
|
|
DC.W 0,0,0 ; not an ornament
|
|
|
|
; Entry point offset table
|
|
|
|
DC.W DAFBVidOpen-DAFBDrvr ; open routine
|
|
DC.W DAFBDrvr-DAFBDrvr ; no prime in normal video drivers
|
|
DC.W DAFBVidCtl-DAFBDrvr ; control
|
|
DC.W DAFBVidStatus-DAFBDrvr ; status
|
|
DC.W DAFBVidClose-DAFBDrvr ; close
|
|
|
|
STRING Pascal
|
|
DAFBVidTitle
|
|
DC.B '.Display_Video_Apple_DAFB'
|
|
|
|
ALIGN 2 ; make sure we're aligned
|
|
DC.W CurDAFBDrvrVersion ; current version
|
|
|
|
STRING ASIS
|
|
|
|
;
|
|
; This table simply contains the zero-based maximum index value for each of the depths. It is
|
|
; set up to be indexed via the modeID. The DAFBXClutTbl is for supporting 16bpp-capable
|
|
; sResources.
|
|
;
|
|
|
|
DAFBClutTbl Dc.b $01,$03,$0F,$FF,$FF
|
|
DAFBXClutTbl Dc.b $01,$03,$0F,$FF,$1F,$FF
|
|
|
|
;
|
|
; These are the bit patterns for grays in each depth, except the last one which is the black
|
|
; Òhalf-patternÓ in 32-bit/pixel mode. The DAFBXPats are for supporting 16bpp-capable
|
|
; sResources.
|
|
|
|
DAFBPats Dc.l OneBitGray,TwoBitGray,FourBitGray,EightBitGray,ThirtyTwoBitGray
|
|
DAFBXPats Dc.l OneBitGray,TwoBitGray,FourBitGray,EightBitGray,SixteenBitGray,ThirtyTwoBitGray
|
|
|
|
;
|
|
; Normally, if no monitor is detected on boot, PrimaryInit just shuts video down. However,
|
|
; if the no-connect pRam code is valid, then we things up as if the monitor code
|
|
; specified in pRam were actually connected. The DAFBMonIDs table (below) is composed
|
|
; of the valid monitor IDs supported by DAFB.
|
|
;
|
|
|
|
DAFBMonIDs Dc.w MonIDSEnd-MonIDsBegin-2
|
|
|
|
MonIDsBegin
|
|
Dc.b indexedSenseRGB2P,indexedSenseFP,indexedSenseRubik,indexedSense2P
|
|
Dc.b indexedSenseNTSC,indexedSenseRGBFP,indexedSenseHR
|
|
Dc.b extendedSensePALBox,extendedSenseNTSC,extendedSenseVGA
|
|
Dc.b extendedSenseLP,extendedSensePAL,extendedSense19
|
|
Dc.b 0
|
|
MonIDSEnd
|
|
|
|
;
|
|
; Because Wombat uses a different clock chip, the TimingAdj value for Spike/Eclipse/Zydeco
|
|
; doesnÕt work on Wombat. However, the TimingAdj adjustment value is simple to compute
|
|
; based on the pixel depth and the clock divider. So, the table represents the value to
|
|
; to add to TimingAdj per pixel depth per clock divider. The zeros in the table are
|
|
; unused place holders.
|
|
;
|
|
DAFBWombatTimingAdjTbl
|
|
Dc.w 32,16,8,4,2,1 ; PixClk/1
|
|
DAFBWombatTimingEntry
|
|
Dc.w 16, 8,4,2,1,0 ; PixClk/2
|
|
Dc.w 8, 4,2,1,0,0 ; PixClk/4
|
|
|
|
DAFBWombatTSize Equ DAFBWombatTimingEntry-DAFBWombatTimingAdjTbl
|
|
|
|
DAFBAntelopeTbl Dc.w 5,2,1 ; PixClk/1,PixClk/2,PixClk/4 TimingAdj,HAL,HFP adjustments.
|
|
|
|
**********************************************************************
|
|
*
|
|
* DAFBVidOpen allocates private storage for the device in the AuxDCE and locks
|
|
* it down for perpetuity. Also, install the interrupt handler and enable
|
|
* the interrupts.
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
*
|
|
* Locals: A3 = pointer to private storage
|
|
*
|
|
* A4/D2/D3 used as scratch
|
|
*
|
|
**********************************************************************
|
|
|
|
WITH VDPageInfo,SlotIntQElement,DAFBVidPrivates
|
|
|
|
DAFBVidOpen
|
|
;
|
|
; Allocate private storage (since block is CLEAR, GFlags are zeroed) and get
|
|
; a pointer to it in A3
|
|
;
|
|
|
|
MOVEQ #DAFBVidPrivSize,D0 ; get size of parameters
|
|
_ResrvMem ,SYS ; make room as low as possible
|
|
MOVEQ #DAFBVidPrivSize,D0 ; get size of parameters
|
|
_NewHandle ,SYS,CLEAR ; get some memory for private storage
|
|
BNE @OpError1 ; => return an error in open
|
|
MOVE.L A0,dCtlStorage(A1) ; save returned handle in AuxDCE
|
|
_HLock ; and lock it down forever
|
|
|
|
MOVE.L (A0),D0 ; get a pointer to it
|
|
_StripAddress ; clean it up
|
|
MOVE.L D0,A3 ; get pointer to privates in A3
|
|
|
|
;
|
|
; Remember the VDAC and DAFB base addresses since they're hard to look up.
|
|
;
|
|
|
|
WITH ProductInfo,DecoderInfo,VideoInfo
|
|
|
|
MOVE.L UnivInfoPtr,A0 ; get a pointer to universal data
|
|
ADD.L DecoderInfoPtr(A0),A0 ; point to the base address table
|
|
MOVE.L VDACAddr(A0),saveVDACBase(A3) ; save pointer
|
|
MOVE.L DAFBAddr(A0),saveDAFBBase(A3) ; save DAFB's base too
|
|
|
|
;
|
|
; Remember the frame buffer base as well. The Open call doesn't set the video mode
|
|
; or page, but SetMode will based on this value (a little later).
|
|
;
|
|
MOVE.L UnivInfoPtr,A0
|
|
ADDA.L VideoInfoPtr(A0),A0 ; point to the VideoInfo record
|
|
MOVE.L VRAMLogAddr32(A0),saveBaseAddr(A3) ; save base address too
|
|
|
|
ENDWITH
|
|
|
|
;
|
|
; Get and install the interrupt handler. Call the EnableVGuts 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 @OpError2 ; if not allocated, return bad
|
|
MOVE.L A0,saveSQElPtr(A3) ; save the SQ element pointer.
|
|
|
|
Moveq #true32b,D0 ; Say we want to be in 32-bit mode.
|
|
_SwapMMUMode ; Do swap.
|
|
Move.l saveDAFBBase(A3),A2 ; Get DAFBÕs base address into A2.
|
|
DAFBUnIdle ; Make sure DAFB is not idle.
|
|
_SwapMMUMode ; Swap back.
|
|
|
|
BSR DAFBEnableVGuts ; Enable VBL interrupts.
|
|
BNE @OpError2 ;
|
|
|
|
;
|
|
; Load the default gamma table from the slot resource list.
|
|
;
|
|
|
|
WITH spBlock
|
|
|
|
SUBA #spBlockSize,SP ; make a slot parameter block
|
|
MOVE.L SP,A0 ; get pointer to block in A0
|
|
MOVE.B dCtlSlot(A1),spSlot(A0) ; copy the slot number
|
|
MOVE.B dCtlSlotId(A1),spID(A0) ; copy the spID of the video sRsrc
|
|
CLR.B spExtDev(A0) ;
|
|
_sRsrcInfo ; get the spsPointer
|
|
BNE @OpError3 ; if failed, then quit.
|
|
|
|
MOVE.B #sGammaDir,spID(A0) ; look for the gamma directory
|
|
_sFindStruct ; get that baby
|
|
BNE.S @DoLinear ; if failed, then do linear
|
|
|
|
MOVE.B #128,spID(A0) ; get the default gamma table, (always 128)
|
|
_sGetBlock ; we can use this since we want it on the sys heap
|
|
BNE.S @DoLinear ; if failed, then do linear
|
|
|
|
; Skip over gamma header.
|
|
|
|
MOVE.L spResult(A0),A0 ; point to head of the block
|
|
MOVE.L A0,saveGamDispPtr(A3) ; save the ptr to the gamma block
|
|
ADDA #2,A0 ; skip resID
|
|
@Name TST.B (A0)+ ; skip over gamma name
|
|
BNE.S @Name ;
|
|
MOVE.L A0,D0 ; get in d-reg
|
|
ADDQ #1,D0 ; word align pointer
|
|
BCLR #0,D0 ; round it off
|
|
|
|
MOVE.L D0,saveGammaPtr(A3) ; put it in private storage
|
|
Bra.s @VidParams ; Jump around linear code.
|
|
|
|
;
|
|
; Build a linear default gamma table if necessary.
|
|
;
|
|
|
|
@DoLinear
|
|
Moveq #gFormulaData,D0 ; Get gamma table header size.
|
|
Add #256,D0 ; Add in one-byte per entry.
|
|
_NewPtr ,SYS,CLEAR ; Clear it.
|
|
Bne @OpError3 ; If failed, quit.
|
|
|
|
Move.l A0,saveGamDispPtr(A3) ; Save head of gamma table for disposal.
|
|
Move.l A0,saveGammaPtr(A3) ; Head and top are same here.
|
|
Move.w #drHwDAFB,gType(A0) ; Set up gType.
|
|
Move.w #1,gChanCnt(A0) ; Set up gChanCnt.
|
|
Move.w #256,gDataCnt(A0) ; Set up gDataCnt.
|
|
Move.w #8,gDataWidth(A0) ; Set up gDataWidth.
|
|
Adda #gFormulaData+256,A0 ; Point to end of data table.
|
|
Move.w #255,D0 ; Set up loop counter.
|
|
@Loop Move.b D0,-(A0) ; Write out value.
|
|
Dbra D0,@Loop ; Loop.
|
|
|
|
;
|
|
; Get a pointer to the video hardware setup parameter block. Use this functional spID's spsPointer
|
|
; found above in the gamma section.
|
|
;
|
|
|
|
With DAFBVidParams
|
|
|
|
@VidParams
|
|
|
|
Move.l Sp,A0 ; Point to the spBlock on the stack.
|
|
Clr.w spID(A0) ; Start looking at spID 0, no external devices.
|
|
Clr.b spTBMask(A0) ; Only look for the board sRsrc.
|
|
Move.w #catBoard,spCategory(A0) ; Look for: catBoard,
|
|
Move.w #typBoard,spCType(A0) ; typBoard,
|
|
Clr.w spDrvrSW(A0) ; 0,
|
|
Clr.w spDrvrHW(A0) ; 0.
|
|
Clr.l spParamData(A0) ; (The board sRsrc must be enabled.)
|
|
Bset #foneslot,spParamData+3(A0) ; Limit search to slot $0.
|
|
_GetTypeSRsrc ; Get the spsPointer.
|
|
Bne @OpError4 ; If failed, quit.
|
|
|
|
MOVE.B #sVidParmDir,spID(A0) ; look for the video parameters dir
|
|
_sFindStruct ; Try to load it.
|
|
Bne @OpError4 ; If failed, quit.
|
|
|
|
Move.l saveDAFBBase(A3),A4 ; Get DAFBBase into A4.
|
|
Move.b dCtlSlotId(A1),D1 ; Get the appropriate sRsrcID into D1.
|
|
|
|
Moveq #true32b,D0 ; Set up to flip into 32-bit addressing mode.
|
|
_SwapMMUMode ; Do flip.
|
|
Move.b D0,-(Sp) ; Save previous addressing mode.
|
|
|
|
Move.l DAFBFlags(A4),D0 ; Get the DAFBFlags into D0.
|
|
Btst #RadiusTPDBit,D0 ; If we donÕt have a RadiusTPD,
|
|
Beq.s @GetParams ; then just go on.
|
|
Btst #RadiusDevType,D0 ; If we have a Radius MonoTPD,
|
|
Beq.s @SetMonoTPD ; then say so.
|
|
Move.b #pSRsrc_Vid_DAFB_2PRdRGB,D1 ; Otherwise, say weÕve gotÉ
|
|
Bra.s @GetParams ; Éa ColorTPD.
|
|
@SetMonoTPD Move.b #pSRsrc_Vid_DAFB_2PRdMono,D1 ;
|
|
|
|
@GetParams Move.b (Sp)+,D0 ; Set up to restore previous addressing mode.
|
|
_SwapMMUMode ; Do flip.
|
|
|
|
MOVE.B D1,spID(A0) ; look in the directory for this config's parameters
|
|
_sGetBlock ; Try to load it.
|
|
Bne @OpError4 ; If failed, quit.
|
|
|
|
MOVE.L spResult(A0),saveVidPtr(A3) ; get pointer to it
|
|
|
|
Move.b dCtlSlotId(A1),spID(A0) ; Set up to find the functional sRsrc.
|
|
_sRsrcInfo ; Get the spsPointer.
|
|
Bne @OpError5 ; If failed, quit.
|
|
|
|
Move.b #MinorBaseOS,spID(A0) ; Set up to get the video base offset value.
|
|
_sReadLong ; Get it.
|
|
Bne @OpError5 ; If failed, quit.
|
|
|
|
Move.l spResult(A0),D0 ; Load the vRAM base offset into D0.
|
|
Add.l D0,saveBaseAddr(A3) ; Add it to the vRAM base address.
|
|
|
|
Endwith
|
|
|
|
;
|
|
; At PrimaryInit time, we used the sense lines to determine the type of attached display. For extended
|
|
; sense displays, we just mapped them to the end of indexed-sense displays. Since the gamma-correction
|
|
; code uses the monitor ID to determine if the passed-in table is applicable, we need to know the ÒrealÓ
|
|
; monitor ID. At PrimaryInit time, we store the real monitor ID in slot pRAM. So, we extract that
|
|
; information out here. Also, it should be noted that it would actually be inappropriate for us
|
|
; to re-read the sense-lines now, in that someone could potentially change/unplug the attached
|
|
; display between PrimaryInit and VidOpen, and that would cause us all sorts of havoc.
|
|
;
|
|
With SP_Params
|
|
|
|
Move.l Sp,A0 ; Point to spBlock on the stack.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Put slot into spBlock.
|
|
|
|
Suba #sizeSPRamRec,Sp ; Allocate an SPRam block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_SReadPRAMRec ; Read Slot PRam.
|
|
Bne @OpError6 ; If failed quit.
|
|
|
|
Moveq #0,D3 ; Clear D3.w.
|
|
Moveq #0,D2 ; Clear D2.w.
|
|
Move.b SP_Depth(Sp),D3 ; Get the mode (itÕs byte sized).
|
|
Move.b SP_MonID(Sp),D2 ; Get the monID (itÕs byte sized).
|
|
Move.b SP_Flags(Sp),D1 ; Get the flags.
|
|
|
|
Adda #sizeSPRamRec+spBlockSize,Sp ; Clean up the stack.
|
|
|
|
EndWith
|
|
|
|
;
|
|
; Do a little bookkeepingÉ
|
|
;
|
|
Move.w D3,saveMode(A3) ; Save the mode for later.
|
|
Move.w D2,saveMonID(A3) ; Save the monID for later.
|
|
Move.b dCtlSlotId(A1),saveSlotId(A3) ; Also save the spID.
|
|
|
|
Btst #spSyncOnGreen,D1 ; If weÕre not supposed to put sync on green,
|
|
Beq.s @CheckAC842A ; then just go on.
|
|
Bset #syncOnGreen,GFlags(A3) ; Otherwise, set the flag.
|
|
|
|
@CheckAC842A Btst #spHas16bppACDC,D1 ; If we donÕt have an AC842A,
|
|
Beq.s @CheckPageMode ; then go on.
|
|
Move.b #1,has16bppACDC(A3) ; Otherwise, say we do.
|
|
|
|
Btst #spHas16bppSRsrc,D1 ; If we donÕt have a 16bpp-capable sRsrc,
|
|
Beq.s @CheckPageMode ; then just go on.
|
|
Bset #has16bppSRsrc,GFlags(A3) ; Otherwise, set the flag.
|
|
|
|
@CheckPageMode Move.l saveDAFBBase(A3),A4 ; Get DAFBBase into A4 for below.
|
|
Btst #spPageMode,D1 ; If PageMode is supposed to be enabled,
|
|
Bne.s @EnablePageMode ; then say so.
|
|
Move.b #0,pageModeSet(A3) ; Otherwise, say page mode is disaabled.
|
|
Bra.s @PageModeDisabled ;
|
|
|
|
@EnablePageMode Move.b #1,pageModeSet(A3) ; Say page mode is enabled.
|
|
@PageModeDisabled
|
|
Move.b #true32b,D0 ; Set up to swap into 32-bit addressing mode.
|
|
_SwapMMuMode ; Do swap, and
|
|
Move.b D0,-(Sp) ; save the previous mode.
|
|
|
|
Move.l DAFB_Config(A4),D0 ; Read the DAFBConfig register.
|
|
Bfextu D0{dafbWrdIntBit:1},D0 ; If word-interleave is on
|
|
Bne.s @DisablePageMode ; then ALWAYS disable page mode.
|
|
Tst.b pageModeSet(A3) ; If weÕre not supposed to enable page mode,
|
|
Beq.s @DisablePageMode ; then disable it.
|
|
Moveq #1,D0 ; Otherwise, set up to enable page mode,
|
|
Bra.s @HitPageMode ; and do it.
|
|
@DisablePageMode
|
|
Moveq #0,D0 ; Set up to disable page mode, and
|
|
@HitPageMode Move.l D0,DAFB_PgMdEn(A4) ; and do it.
|
|
|
|
Move.l DAFBFlags(A4),D0 ; Get the DAFBFlags.
|
|
Btst #isWombat,D0 ; If weÕre not on a Wombat,
|
|
Beq.s @ChkCLUTType ; then just go on.
|
|
Move.b #1,wombatFlag(A3) ; Otherwise, say weÕre on a Wombat.
|
|
|
|
@ChkCLUTType Btst #wLin16Bpp,D0 ; If we donÕt have an Antelope,
|
|
Beq.s @ChkVidEnb ; then just go on.
|
|
Move.b #1,hasLin16BppCLUT(A3) ; Otherwise, say weÕve got one.
|
|
|
|
@ChkVidEnb Move.w D0,D1 ; Copy the DAFBFlags.
|
|
Move.b (Sp)+,D0 ; Set up to switch back into previous mode,
|
|
_SwapMMUMode ; and do it.
|
|
|
|
Btst #videoEnabled,D1 ; If video is still enabled,
|
|
Bne.s @CalcScrnBase ; then just go on.
|
|
|
|
Move.w saveMode(A3),D1 ; Otherwise, get the mode into D1.
|
|
Sub.w #firstVidMode,D1 ; Make it an index.
|
|
Bsr DAFBSetDepth ; Set the depth.
|
|
Bsr DAFBCalcScreenBaseAddr ; Calculate the new ST-corrected screen baseAddr.
|
|
Bsr DAFBGrayScreen ; Paint the screen gray.
|
|
Bra.s @SkipIt ; Go on.
|
|
|
|
@CalcScrnBase
|
|
Move.w #firstVidMode,saveMode(A3) ; From PrimaryInit, weÕre still at 1bpp.
|
|
Bsr DAFBCalcScreenBaseAddr ; Save the ST-corrected screen baseAddr.
|
|
|
|
@SkipIt
|
|
|
|
;
|
|
; Set GFlags to reflect monochrome-only displays.
|
|
;
|
|
|
|
Cmp.w #indexedSenseFP,saveMonID(A3) ; If this is a Mono-Only Full Page,
|
|
Beq.s @SetMonoFlags ; then say so.
|
|
Cmp.w #indexedSense2P,saveMonID(A3) ; If this is a Mono-Only Two-Page,
|
|
Beq.s @SetMonoFlags ; then say so.
|
|
Bra.s @EndMonoCheck ; Otherwise, skip.
|
|
|
|
@SetMonoFlags Bset #IsMono,GFlags(A3) ; Turn on the IsMono and
|
|
Bset #GrayFlag,GFlags(A3) ; GrayFlag flags.
|
|
|
|
@EndMonoCheck
|
|
|
|
;
|
|
; Determine the clock speed and save it. The act of reading VIAs can cause pending interrupts
|
|
; to be lost, so we want only want to do this once.
|
|
;
|
|
|
|
Tst.b wombatFlag(A3) ; If weÕre on a Wombat, then
|
|
Bne.s @WombatSpeed ; skip the Spike/Eclipse/Zydeco stuff.
|
|
|
|
Move.l VIA2,A0 ; Point to VIA2.
|
|
Btst #v2Speed,vBufB(A0) ; Test the speed register (25 vs. 33 MHz).
|
|
Bra.s @EndSpeedChk
|
|
|
|
@WombatSpeed Move.l VIA,A0 ; Point to VIA1.
|
|
Btst #vCpuId2,vBufA(A0) ; Test CPUID reg 2 (20/25 vs. 33/40 MHz).
|
|
|
|
@EndSpeedChk Bne.s @AllDone ; Leave flag clear if weÕre not going slow.
|
|
Bset #IsSlow,GFlags(A3) ; Otherwise, set it.
|
|
|
|
;
|
|
; All done!
|
|
;
|
|
|
|
@AllDone MOVEQ #noErr,D0 ; no error
|
|
@EndOpen RTS ; return
|
|
|
|
@OpError6 Adda #sizeSPRamRec,Sp ; Release the SPRam block.
|
|
@OpError5 Move.l saveVidPtr(A3),A0 ; Set up to dispose of vidParams table.
|
|
_DisposPtr ; Dispose it.
|
|
@OpError4 Move.l saveGamDispPtr(A3),A0 ; Set up to dispose of gamma table.
|
|
_DisposPtr ; Dispose it.
|
|
@OpError3 ADDA #spBlockSize,SP ; release the spBlock
|
|
@OpError2 MOVE.L dCtlStorage(A1),A0 ; get the private storage back
|
|
_DisposHandle ; release the driver private storage
|
|
@OpError1 MOVE.L #OpenErr,D0 ; say can't open driver
|
|
BRA.S @EndOpen
|
|
|
|
ENDWITH
|
|
|
|
**********************************************************************
|
|
*
|
|
* Video Driver Control Call Handler. There are 10 standard calls:
|
|
*
|
|
* ($00) Reset (VAR mode, page: INTEGER; VAR BaseAddr: Ptr);
|
|
* ($01) KillIO
|
|
* ($02) SetMode(mode, page: INTEGER; VAR BaseAddr: Ptr);
|
|
* ($03) SetEntries (Table: Ptr; Start,Count : integer );
|
|
* ($04) SetGamma (Table : Ptr );
|
|
* ($05) GrayPage (page);
|
|
* ($06) SetGray (csMode = 0 for color, 1 for gray)
|
|
* ($07) SetInterrupt (csMode = 0 for enable, non-zero for disable);
|
|
* ($08) DirectSetEntries (Table: Ptr; Start,Count : integer );
|
|
* ($09) SetDefaultMode (csMode = mode to set);
|
|
*
|
|
* The following calls are DAFB-specific:
|
|
*
|
|
* ($80) SetSyncOnGreen(csMode = 0 for enable, non-zero for disable);
|
|
* ($81) Set16bpp(csMode = 0 for enable, non-zero for disable);
|
|
* ($82) SetPageMode(csMode = 0 for enable, non-zero for disable);
|
|
* ($83) SetAltSense(csMode = byte 0 is sense code, byte 1 is type);
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
* Uses: A2 = cs parameters (ie. A2 <- csParam(A0)) (must be preserved)
|
|
* A3 = ptr to our privates/scrarch (doesnÕt need to be preserved)
|
|
* A4 = scratch (must be preserved)
|
|
* D0-D3 = scratch (don't need to be preserved)
|
|
*
|
|
* Exit: D0 = error code
|
|
*
|
|
**********************************************************************
|
|
|
|
;
|
|
; Decode the callÉ
|
|
;
|
|
|
|
DAFBVidCtl
|
|
|
|
MOVEM.L A0/A1,-(SP) ; Save exit registers.
|
|
|
|
MOVE.L csParam(A0),A2 ; A2 <- Ptr to control parameters
|
|
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
MOVE.W csCode(A0),D0 ; get routine selector
|
|
|
|
Cmp.w #cscSyncOnGreen,D0 ; If we got the SetSyncOnGreen call,
|
|
Beq DAFBSetSyncOnGreen ; hop to it.
|
|
Cmp.w #csc16bpp,D0 ; If we got the 16bpp call,
|
|
Beq DAFBSet16bpp ; hop to it.
|
|
Cmp.w #cscPageMode,D0 ; If we got the PageMode call,
|
|
Beq DAFBSetPageMode ; hop to it.
|
|
Cmp.w #cscAltSense,D0 ; If we got the alternate senseID call,
|
|
Beq DAFBSetAltSense ; hop to it.
|
|
|
|
CMP.W #9,D0 ; IF csCode NOT IN [0..9] THEN
|
|
BHI.S DAFBCtlBad ; Error, csCode out of bounds.
|
|
MOVE.W DAFBCtlJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine.
|
|
JMP DAFBCtlJumpTbl(PC,D0.W) ; GOTO the proper routine.
|
|
|
|
DAFBCtlJumpTbl
|
|
DC.W DAFBVidReset-DAFBCtlJumpTbl ; $00 => VidReset
|
|
DC.W DAFBCtlGood-DAFBCtlJumpTbl ; $01 => CtlGood (no async routines here)
|
|
DC.W DAFBSetVidMode-DAFBCtlJumpTbl ; $02 => SetVidMode
|
|
DC.W DAFBSetEntries-DAFBCtlJumpTbl ; $03 => SetEntries
|
|
DC.W DAFBSetGamma-DAFBCtlJumpTbl ; $04 => SetGamma
|
|
DC.W DAFBGrayPage-DAFBCtlJumpTbl ; $05 => GrayPage
|
|
DC.W DAFBSetGray-DAFBCtlJumpTbl ; $06 => SetGray
|
|
DC.W DAFBSetInterrupt-DAFBCtlJumpTbl ; $07 => SetInterrupt
|
|
DC.W DAFBDirectSetEntries-DAFBCtlJumpTbl ; $08 => DirectSetEntries
|
|
DC.W DAFBSetDefaultMode-DAFBCtlJumpTbl ; $09 => SetDefaultMode
|
|
|
|
DAFBCtlBad MOVEQ #controlErr,D0 ; else say we don't do this one
|
|
BRA.S DAFBCtlDone ; and return
|
|
|
|
DAFBCtlGood MOVEQ #noErr,D0 ; return no error
|
|
|
|
DAFBCtlDone MOVEM.L (SP)+,A0/A1 ; Restore Exit registers.
|
|
BRA DAFBExitDrvr
|
|
|
|
DAFBVidReset
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Reset the card to its default
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE #FirstVidMode,csMode(A2) ; return default mode
|
|
MOVE #FirstVidMode,saveMode(A3) ; remember FirstVidMode as the requested mode
|
|
MOVEQ #0,D1 ; get default depth in D1 (#firstVidMode-#firstVidMode)
|
|
MOVEQ #0,D0 ; get page in D0
|
|
MOVE D0,csPage(A2) ; return the page
|
|
BSR DAFBSetDepth ; set the depth from D1
|
|
|
|
Bsr DAFBCalcScreenBaseAddr ; Calculate the new ST-corrected screen baseAddr,
|
|
Move.l saveScreenBase(A3),csBaseAddr(A2) ; and return it.
|
|
|
|
BSR DAFBGrayScreen ; paint the screen gray
|
|
BRA.S DAFBCtlGood ; => no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetVidMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Set the card to the specified mode. Only page zero is possible,
|
|
; so we need to check that the request was OK.
|
|
;
|
|
; If the card is already set to the specified mode, then do nothing.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE.W csMode(A2),D1 ; D1 = mode
|
|
BSR DAFBChkMode ; check mode and convert
|
|
BNE.S DAFBCtlBad ; => not a valid mode
|
|
|
|
TST.W csPage(A2) ; only page zero is valid
|
|
BNE.S DAFBCtlBad ; => not a valid page
|
|
|
|
; Only set if mode has changed.
|
|
|
|
MOVE.W csMode(A2),D2 ; get the mode spID (D1 has the zero-based mode)
|
|
CMP saveMode(A3),D2 ; has the mode changed?
|
|
BEQ @ModeOK1 ; if not, then skip graying
|
|
|
|
; Remember the newly requested mode.
|
|
|
|
MOVE.W D2,saveMode(A3) ; remember requested mode
|
|
|
|
; Set the entire color table to gray before switching to avoid screen anomalies.
|
|
|
|
Movem.l A4-A6/D5-D6,-(Sp) ; Save work registers.
|
|
|
|
Move.l saveGammaPtr(A3),A0 ; Get pointer to gamma data structure.
|
|
Lea gFormulaData(A0),A4 ; Point to first gamma table.
|
|
Adda.w gFormulaSize(A0),A4 ;
|
|
Move.l A4,A5 ; Point to green data (assuming gChanCnt = 1).
|
|
Move.l A4,A6 ; Point to red data (assuming gChanCnt = 1).
|
|
|
|
Cmp.w #1,gChanCnt(A0) ; If thereÕs only one table,
|
|
Beq.s @OnlyOneTable ; then weÕre set.
|
|
|
|
Move.w gDataWidth(A0),D2 ; Get width of each entry (in bits).
|
|
Move.w gDataCnt(A0),D0 ; Get # of entries in table.
|
|
Addq #7,D2 ; Round to nearest byte.
|
|
Lsr.w #3,D2 ; Get bytes per entry.
|
|
Mulu D2,D0 ; Get size of table in bytes.
|
|
|
|
Adda.w D0,A5 ; Calc base of green (red base + D0).
|
|
Adda.w D0,A6 ; Calc baseÉ
|
|
Adda.w D0,A6 ; Éof blue (red base + D0 + D0).
|
|
|
|
@OnlyOneTable
|
|
|
|
Move.w gDataCnt(A0),D3 ; Save number of gamma entries.
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit addressing mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,-(SP) ; save current addressing mode
|
|
|
|
Move.w GFlags(A3),D5 ; Get the GFlags into a convient register.
|
|
Moveq #0,D6 ; Setup the alternate GFlags register.
|
|
Btst #IsMono,D5 ; If this is not a mono-only display,
|
|
Beq.s @GetVDAC ; then just go on.
|
|
Move.l saveDAFBBase(A3),A0 ; Otherwise, get the DAFBBase into A0.
|
|
Move.l DAFBFlags(A0),D0 ; Get the DAFBFlags into D0.
|
|
Btst #RadiusTPDBit,D0 ; If this is not a RadiusTPD,
|
|
Beq.s @GetVDAC ; then just go on.
|
|
Btst #RadiusDevType,D0 ; It this is not a MonoTPD,
|
|
Bne.s @GetVDAC ; then just go on.
|
|
Bset #IsMono,D6 ; Otherwise, remember to swap green & blue.
|
|
|
|
@GetVDAC MOVE.L saveVDACBase(A3),A0 ; get the VDAC base addr
|
|
Clr.l ACDC_AddrReg(A0) ; Start at position zero in the CLUT.
|
|
ADDA #(ACDC_DataReg+3),A0 ; point to data register
|
|
|
|
MOVE.W SR,-(SP) ; preserve the status register
|
|
BSR DAFBWaitVSync ; wait for next blanking period (preserves A0)
|
|
|
|
; Write out gamma-corrected gray CLUTÉ
|
|
;
|
|
Move.w D3,D0 ; Init loop counter.
|
|
Subq #1,D0 ; Zero base it.
|
|
|
|
Lsr.w #1,D3 ; Get midpoint of table(s).
|
|
|
|
@Repeat Btst #IsMono,D6 ; If this is not a Radius MonoTPD,
|
|
Beq.s @NotRadius ; then go on.
|
|
|
|
Clr.b (A0) ; Write red,
|
|
Move.b (A4,D3),(A0) ; green,
|
|
Clr.b (A0) ; blue.
|
|
Dbra D0,@Repeat ; Loop until done.
|
|
Bra.s @EndLoop ; Go on.
|
|
|
|
@NotRadius Btst #IsMono,D5 ; If this is not a mono-only display
|
|
Beq.s @DoRGB ; then just do the standard RGB stuff.
|
|
Clr.b (A0) ; Otherwise, just write black out
|
|
Clr.b (A0) ; to the red & green channels.
|
|
Bra.s @DoMono ;
|
|
|
|
@DoRGB Move.b (A4,D3),(A0) ; Write red,
|
|
Move.b (A5,D3),(A0) ; green,
|
|
@DoMono Move.b (A6,D3),(A0) ; blue.
|
|
Dbra D0,@Repeat
|
|
|
|
@EndLoop MOVE (SP)+,SR ; restore the status reg
|
|
MOVE.B (SP)+,D0 ; get the MMU mode back
|
|
_SwapMMUMode ;
|
|
|
|
Movem.l (Sp)+,A4-A6/D5-D6 ; Restore work registers.
|
|
BSR DAFBSetDepth ; set the depth from D1
|
|
|
|
; Finish up the bookkeeping.
|
|
|
|
MOVE.W csMode(A2),saveMode(A3) ; save mode number
|
|
CMP.W #FifthVidMode,saveMode(A3) ; was it a direct mode?
|
|
BLT.S @BitOff ; no, so turn flag off
|
|
|
|
BSET #IsDirect,GFlags(A3) ; turn on bit
|
|
BRA.S @ModeOK1 ;
|
|
@BitOff
|
|
BCLR #IsDirect,GFlags(A3) ; turn off bit
|
|
|
|
@ModeOK1
|
|
Bsr DAFBCalcScreenBaseAddr ; Calculate the new ST-corrected screen baseAddr,
|
|
Move.l saveScreenBase(A3),csBaseAddr(A2) ; and return it.
|
|
|
|
BRA DAFBCtlGood ; return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetEntries
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Input :
|
|
; csParam -> datablock
|
|
; datablock = csTable -> table of colorSpecs (not colortable)
|
|
; csStart -> where to start setting, or -1
|
|
; csCount -> # of entries to change
|
|
;
|
|
; This 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).
|
|
;
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Set the CLUT
|
|
; A0 = Ptr to the table
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private data, later to CLUT constants table
|
|
; A4 = Ptr to gamma red table
|
|
; A5 = Ptr to gamma green table
|
|
; A6 = Ptr to gamma blue table
|
|
;
|
|
; D0-D3 = Scratch
|
|
; D4 = Size of stack color table buffer
|
|
; D5 = GFlags word
|
|
; D6 = Index range [0..n]
|
|
; D7 = gamma channel size in bits
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
; Initialize loop.
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
|
|
BNE DAFBCtlBad ; error if so
|
|
|
|
DAFBSEGuts
|
|
TST.L csTable(A2) ; Check for a nil pointer
|
|
BEQ DAFBCtlBad ;
|
|
|
|
MOVEM.L A1/A4-A6/D4-D7,-(SP) ; save registers for gamma
|
|
|
|
MOVE.W GFlags(A3),D5 ; get GFlags word in D5
|
|
|
|
CMP.W #indexEntries,csStart(A2) ; was it indexed mode?
|
|
BEQ.S @SkipSeq ; if so, then leave bit off (it's never turned on in GFlags)
|
|
BSET #UseSeq,D5 ; if not, turn on sequential mode bit
|
|
@SkipSeq
|
|
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma data structure
|
|
MOVE.W gFormulaSize(A0),D0 ; get the size of formula data
|
|
LEA gFormulaData(A0,D0),A4 ; red correction table starts here
|
|
MOVE.L A4,A5 ; get default pointer to green data
|
|
MOVE.L A4,A6 ; get default pointer to blue data
|
|
MOVE gDataWidth(A0),D7 ; get width of each entry in bits
|
|
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
|
|
ADDQ #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
|
|
ADDA D0,A6 ; calc base of blue
|
|
ADDA D0,A6 ; calc base of blue
|
|
|
|
@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
|
|
|
|
Btst #has16bppSRsrc,D5 ; If we have a 16bpp-capable sRsrc,
|
|
Bne.s @GetXTable ; then use the extended table.
|
|
Bra.s @NormTable ; Otherwise, just use the normal table.
|
|
|
|
@GetXTable Lea DAFBXClutTbl,A0 ; Point to extended table of counts.
|
|
Bra.s @ChkRange
|
|
|
|
@NormTable LEA DAFBClutTbl,A0 ; point to little table of counts
|
|
|
|
@ChkRange MOVEQ #0,D6 ; clear all of D6
|
|
MOVE.B (A0,D1),D6 ; get entry from table for this mode
|
|
|
|
;
|
|
; 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),D4 ; get the number of entries to change
|
|
CMP.W D6,D4 ; is it in the allowable range
|
|
BHI DAFBSEBadExit ; if out of range, then exit w/bad result
|
|
|
|
Move.w csStart(A2),D0 ; Get the start number to range check.
|
|
Addq.w #1,D0 ; If csStart < -1, then itÕs out of
|
|
Bmi DAFBSEBadExit ; range.
|
|
|
|
;
|
|
; In order to support Vesuvio & the RGB PortraitÕs 16bpp modes, we ALWAYS use indexed mode
|
|
; for SetEntries, since the real entries must be translated from a 5-bit value into an
|
|
; 8-bit index. Note: The UseTrans & UseSeq are actually the same bit so that the
|
|
; indexed write routine works correctly.
|
|
;
|
|
|
|
MOVE.L csTable(A2),D0 ; Some (bad) people pass in an offset
|
|
_StripAddress ; CTabHandleÕs MasterPointer here,
|
|
Move.l D0,A1 ; so we clean them up. Ugh!
|
|
|
|
Move.w D4,D1 ; Make a copy of the number of entries, and
|
|
Addq #1,D4 ; make it counting for now.
|
|
|
|
Moveq #0,D6 ; Assume that we arenÕt doing 16bpp translations.
|
|
; (i.e., #UseTrans in D6 is clear).
|
|
|
|
Btst #has16bppSRsrc,D5 ; If we have a 16bpp-capable sRsrc,
|
|
Bne.s @Chk16bpp ; then check for 16bpp.
|
|
Bra.s @IndexTest ; Otherwise, just do the normal stuff.
|
|
|
|
@Chk16bpp Move.w saveMode(A3),D0 ; Get the current mode.
|
|
Cmp.w #FifthVidMode,D0 ; If weÕre not doing 16bpp,
|
|
Bne.s @IndexTest ; then just go on.
|
|
Tst.b hasLin16bppCLUT(A3) ; If 16bpp is linear (i.e., we have an Antelope),
|
|
Bne.s @IndexTest ; then just on.
|
|
Bset #UseTrans,D6 ; Otherwise, remember that weÕre translating.
|
|
|
|
Bclr #UseSeq,D5 ; If weÕre already indexed,
|
|
Beq.s @isIndex ; then just go on.
|
|
|
|
Move.w D1,D2 ; Otherwise, sequence thru table from
|
|
Add.w csStart(A2),D2 ; csStart thru csCount entries.
|
|
|
|
; The following code is BAD, BAD, BAD! We should build our own table here so
|
|
; as to NOT mess up the userÕs data. But all the previous Apple video drivers
|
|
; have done the same thing here, so weÕll continue the trend for now.
|
|
|
|
@TableLoop Move.w D2,value(A1,D1*colorSpecSize) ; Write the index into the table.
|
|
Subq #1,D2 ; Decrement index.
|
|
Dbra D1,@TableLoop ;
|
|
Bra.s @isIndex
|
|
|
|
@IndexTest ADDQ #1,D4 ; make number of entries a counting number
|
|
BTST #UseSeq,D5 ; are we in sequential mode?
|
|
BEQ.S @isIndex ; if equal, we're indexed
|
|
@isSeq MULU #3,D4 ; room for R,G,B in sequential mode
|
|
BRA.S @allocIt ; and continue
|
|
@isIndex ASL #2,D4 ; multiply times 4 for index,R,G,B
|
|
@allocIt SUB.W D4,SP ; allocate the buffer and save size in D4
|
|
|
|
Btst #IsMono,D5 ; If this is not a mono-only display,
|
|
Beq.s @EndRdChk ; then just go on.
|
|
|
|
Moveq #true32b,D0 ; Set up to flip into 32-bit addressing mode.
|
|
_SwapMMUMode ; Do flip.
|
|
Move.b D0,-(Sp) ; Save previous addressing mode.
|
|
|
|
Move.l saveDAFBBase(A3),A0 ; Get the DAFBBase into A0.
|
|
Move.l DAFBFlags(A0),D0 ; Get the DAFBFlags into D0.
|
|
Btst #RadiusTPDBit,D0 ; If this is not a Radius TPD,
|
|
Beq.s @SwapBack ; then just go on.
|
|
Btst #RadiusDevType,D0 ; If this not a MonoTPD,
|
|
Bne.s @SwapBack ; then just go on.
|
|
Bset #IsMono,D6 ; Otherwise, remember to swap green & blue channels.
|
|
|
|
@SwapBack Move.b (Sp)+,D0 ; Set up to restore previous addressing mode.
|
|
_SwapMMUMode ; Do restore.
|
|
|
|
@EndRdChk
|
|
|
|
;
|
|
; Construct the stack version of the color table. It looks like a color table, but each of the
|
|
; components is only eight bits (rather than 16). These will be expanded to longs when they
|
|
; are written to the hardware
|
|
;
|
|
MOVE.L SP,A0 ; copy the stack buffer pointer
|
|
MOVE.W csCount(A2),D3 ; get the number of entries again
|
|
|
|
;
|
|
; Write the index if in indexed mode. If in sequential mode, blow it off completely,
|
|
; since it won't be needed.
|
|
|
|
@SetupLoop
|
|
MOVE.W (A1)+,D1 ; get index
|
|
|
|
BTST #UseSeq,D5 ; is it sequence mode?
|
|
BNE.S @SLSeq ; yup, so go there
|
|
|
|
Btst #UseTrans,D6 ; If weÕre not supposed to do the 5-to-8 translations,
|
|
Beq.s @WriteIndex ; then just write out the index to the stack.
|
|
Bsr DAFBTrans5to8 ; Otherwise, do the translation.
|
|
|
|
@WriteIndex MOVE.B D1,(A0)+ ; Write out index to stack table.
|
|
|
|
@SLSeq
|
|
MOVE.W (A1)+,D0 ; get red
|
|
MOVE.W (A1)+,D1 ; get green
|
|
MOVE.W (A1)+,D2 ; get blue
|
|
|
|
TST D5 ; test hi bit of the flags
|
|
BPL.S @NoGray ; if not set, don't luminence map
|
|
|
|
BTST #IsDirect,D5 ; test for direct mode as well
|
|
BNE.S @NoGray ; don't allow luminence mapping in direct mode
|
|
|
|
|
|
; We're luminence mapping here.
|
|
|
|
MULU #$4CCC,D0 ; multiply by red weight (0.30)
|
|
MULU #$970A,D1 ; multiply by green weight (0.59)
|
|
MULU #$1C29,D2 ; multiply by blue weight (0.11)
|
|
ADD.L D1,D0 ; sum red and green
|
|
ADD.L D2,D0 ; blue also
|
|
BFEXTU D0{0:D7},D0 ; get gChanWidth bits for gamma table lookup
|
|
MOVE.W D0,D1 ; copy into green register
|
|
MOVE.W D0,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
|
|
Btst #IsMono,D6 ; If this is not a Radius MonoTPD,
|
|
Beq.s @NotRadius ; then just go on.
|
|
|
|
Clr.b (A0)+ ; Write black for red.
|
|
Move.b (A4,D0),(A0)+ ; Write gamma corrected ÒgreenÓ.
|
|
Clr.b (A0)+ ; Write black for blue.
|
|
|
|
Dbra D3,@SetupLoop ; Loop until done.
|
|
Bra.s @EndSetup ; Go on.
|
|
|
|
@NotRadius
|
|
BTST #IsMono,D5 ; if monochrome display, write black to red & green
|
|
BEQ.S @Brighter ; if not, then set all three channels
|
|
CLR.B (A0)+ ; write black for red
|
|
CLR.B (A0)+ ; and green
|
|
BRA.S @Looper ; write out normal blue
|
|
|
|
@Brighter
|
|
MOVE.B (A4,D0),(A0)+ ; write gamma corrected red
|
|
MOVE.B (A5,D1),(A0)+ ; write gamma corrected green
|
|
|
|
@Looper
|
|
MOVE.B (A6,D2),(A0)+ ; write gamma corrected blue
|
|
DBRA D3,@SetupLoop ; and loop for each entry
|
|
|
|
@EndSetup
|
|
|
|
;
|
|
; OK, the stack table is set up. Now let's load the hardware.
|
|
;
|
|
|
|
MOVE.W csCount(A2),D3 ; get the count again
|
|
MOVE.L saveVDACBase(A3),A4 ; get VDAC base
|
|
LEA ACDC_DataReg(A4),A4 ; point to VDAC data register
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit addressing mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,-(SP) ; save current addressing mode
|
|
|
|
LEA 2(SP),A0 ; point to the stack buffer again
|
|
CLR.L D1 ; get the high 3 bytes of D1 clear
|
|
|
|
MOVE.W SR,-(SP) ; preserve the status register
|
|
BSR DAFBWaitVSync ; wait for next blanking period (preserves A0/D0)
|
|
|
|
BTST #UseSeq,D5 ; is it sequence mode?
|
|
BNE.S DAFBSeqWrite ; yup, sequence mode, so go
|
|
|
|
;
|
|
; Here's the loop that actually writes to the hardware when in indexed mode.
|
|
;
|
|
|
|
DAFBIndexWrite
|
|
MOVE.B (A0)+,D1 ; get the index
|
|
MOVE.L D1,ACDC_AddrReg-ACDC_DataReg(A4) ; write the index value to the CLUT address
|
|
|
|
MOVE.B (A0)+,3(A4) ; write red
|
|
MOVE.B (A0)+,3(A4) ; write green
|
|
MOVE.B (A0)+,3(A4) ; write blue
|
|
Tst.b hasLin16BppCLUT(A3) ; If we donÕt have an Antelope part,
|
|
Beq.s @Next ; then just go on.
|
|
Tst.b ([VIA]) ; Otherwise, wait a µSec.
|
|
@Next DBRA D3,DAFBIndexWrite ; and loop
|
|
BRA.S DAFBSEDone ;
|
|
|
|
;
|
|
; Write the translated starting position for sequence mode.
|
|
;
|
|
|
|
DAFBSeqWrite
|
|
MOVE.W csStart(A2),D1 ; get sequence start address
|
|
MOVE.L D1,ACDC_AddrReg-ACDC_DataReg(A4) ; write the sequence start position
|
|
|
|
;
|
|
; Here's the loop that actually writes to the hardware when in sequence mode.
|
|
;
|
|
|
|
@SeqLoop
|
|
MOVE.B (A0)+,3(A4) ; write red
|
|
MOVE.B (A0)+,3(A4) ; write green
|
|
MOVE.B (A0)+,3(A4) ; write blue
|
|
Tst.b hasLin16BppCLUT(A3) ; If we donÕt have an Antelope part,
|
|
Beq.s @Next ; then just go on.
|
|
Tst.b ([VIA]) ; Otherwise, wait a µSec.
|
|
@Next DBRA D3,@SeqLoop ; and loop
|
|
|
|
;
|
|
; Clean up and go home.
|
|
;
|
|
|
|
DAFBSEDone
|
|
MOVE (SP)+,SR ; restore status register
|
|
MOVE.B (SP)+,D0 ; get the previous mode back
|
|
_SwapMMUMode ;
|
|
|
|
ADD D4,SP ; release stack buffer
|
|
MOVEM.L (SP)+,A1/A4-A6/D4-D7 ; restore registers
|
|
BRA DAFBCtlGood ; return O-Tay!
|
|
|
|
DAFBSEBadExit
|
|
MOVEM.L (SP)+,A1/A4-A6/D4-D7 ; restore registers
|
|
BRA DAFBCtlBad ; return an error code
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetGamma
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Set 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. If supplied gamma table ptr is NIL, then
|
|
; it loads a linear gamma table into the private table
|
|
;
|
|
; A0 = Ptr to private storage
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
; 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 up a linear gamma table
|
|
MOVE.L D0,A2 ; get pointer to new gamma table
|
|
|
|
TST.W gVersion(A2) ; version = 0?
|
|
BNE DAFBCtlBad ; => no, return error
|
|
Tst.w gType(A2) ; Test the hardwareID.
|
|
Beq.s @ChangeTable ; If 0, then accept a TFB-style gamma table.
|
|
CMP.W #drHwDAFB,gType(A2) ; type = DAFB?
|
|
BNE DAFBCtlBad ; => no, return error
|
|
TST.W gFormulaSize(A2) ; if gType=DAFB, 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 saveMonID(A3),D0 ; is this the monitor?
|
|
BEQ.S @ChangeTable ; yes, so do it
|
|
ADDQ #1,D0 ; was it -1?
|
|
BNE DAFBCtlBad ; nope, so must be wrong monitor
|
|
|
|
; If new table is a 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 saveGamDispPtr(A3),A0 ; if new one is smaller,
|
|
_DisposPtr ; dispose old one
|
|
CLR.L saveGamDispPtr(A3) ; flag it's been disposed
|
|
|
|
@GetNew Moveq #0,D0 ; (_NewPtr takes a long, so clear D0 for later.)
|
|
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 DAFBCtlBad ; => unable to allocate storage
|
|
|
|
MOVE.L saveGamDispPtr(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,saveGamDispPtr(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
|
|
Move.w gDataCnt(A0),D3 ; get the number of entries
|
|
Subq #1,D3 ; zero base
|
|
ADDA #gFormulaData,A0 ; point to tables
|
|
ADDA D0,A0 ; point past monID, if present
|
|
@ChanLoop MOVE.W D3,D0 ; loop count within each channel
|
|
@entryLoop MOVE.B D0,(A0) ; write this value out
|
|
Not.b (A0)+ ; invert to make table ramp properly
|
|
DBRA D0,@entryLoop ; for each entry in channel
|
|
DBRA D2,@ChanLoop ; and each channel
|
|
|
|
@GammaDone
|
|
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
|
|
BEQ.S @Out ; if not, then we're done
|
|
BSR DAFBDirectCLUTSet ; if so, then set up direct CLUT ramps
|
|
|
|
@Out
|
|
BRA DAFBCtlGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBGrayPage
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Clear the specified page in the current mode to gray
|
|
;
|
|
; A0 = Ptr to private storage
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to driver privates
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE saveMode(A3),D1 ; D1 = mode
|
|
BSR DAFBChkMode ; convert mode to depth in D1
|
|
BNE DAFBCtlBad ; => not a valid depth
|
|
|
|
MOVE csPage(A2),D0 ; D0 = page
|
|
BNE DAFBCtlBad ; => not a valid page
|
|
|
|
BSR DAFBGrayScreen ; paint the screen gray
|
|
|
|
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
|
|
BEQ.S @Out ; if not, then we're done
|
|
BSR DAFBDirectCLUTSet ; if so, then set up direct CLUT ramps
|
|
@Out
|
|
BRA DAFBCtlGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetGray
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Set 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.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
BTST #IsMono,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 #0,D1 ; set up for BFEXTU to point to GrayFlag
|
|
BSR.S DAFBSetIntCom ; call common code
|
|
BRA DAFBCtlGood ; 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.
|
|
;
|
|
|
|
DAFBSetIntCom
|
|
MOVE.B csMode(A2),D0 ; get boolean
|
|
BFINS D0,GFlags(A3){D1:1} ; set flag bit
|
|
RTS ; and return
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetInterrupt
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Enable (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.
|
|
;
|
|
; The slot interrupt queue element is always allocated by the Open call.
|
|
; This routine just inserts and removes it from the slot interrupt task queue.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH VDPageInfo,SlotIntQElement,DAFBVidPrivates
|
|
|
|
MOVEQ #1,D1 ; set up for BFEXTU to point to IntDisFlag
|
|
BSR.S DAFBSetIntCom ; call common code
|
|
BNE.S @DAFBDisableThem ; if zero, then enable
|
|
|
|
; This code enables interrupts and installs the interrupt handler.
|
|
;
|
|
BSR.S DAFBEnableVGuts ; call common code
|
|
BNE DAFBCtlBad ; error, flag problem
|
|
BRA DAFBCtlGood ; and go home
|
|
|
|
; This code disables VBL interrupts, then removes the interrupt handler.
|
|
;
|
|
@DAFBDisableThem
|
|
BSR.S DAFBDisableVGuts ; jump to the disabling utility
|
|
BRA DAFBCtlGood ; all done
|
|
|
|
; The following two routines are common code shared between the Open/Close calls
|
|
; and the SetInterrupt control call.
|
|
;
|
|
DAFBDisableVGuts
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit addressing mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,-(SP) ; save current addressing mode
|
|
|
|
MOVE.W SR,-(SP) ; preserve the status register
|
|
BSR DAFBWaitVSync ; to be safe, wait for the next VBL
|
|
|
|
MOVE.L saveDAFBBase(A3),A0 ; point to the DAFB base
|
|
CLR.L Swatch_IntMsk(A0) ; set slot 0 interrupt disabled
|
|
MOVE (SP)+,SR ; re-enable cursor interrupts
|
|
|
|
MOVE.B (SP)+,D0 ; get back addressing mode
|
|
_SwapMMUMode ;
|
|
|
|
CLR D0 ; setup slot # for _SIntRemove (slot zero!)
|
|
MOVE.L saveSQElPtr(A3),A0 ; get the SQ element pointer
|
|
_SIntRemove ; remove the interrupt handler
|
|
RTS
|
|
|
|
DAFBEnableVGuts ;
|
|
|
|
MOVE.L saveSQElPtr(A3),A0 ; get the queue element
|
|
LEA DAFBBeginIH,A2 ; save Pointer to interrupt handler
|
|
MOVE.W #SIQType,SQType(A0) ; setup queue ID
|
|
MOVE.L A2,SQAddr(A0) ; setup int routine address
|
|
MOVE.L A3,SQParm(A0) ; pass pointer to privates as the parameter
|
|
CLR.W D0 ; setup slot zero
|
|
_SIntInstall ; and do install
|
|
BNE.S @IntBad
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit addressing mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,-(SP) ; save current addressing mode
|
|
|
|
MOVE.L saveDAFBBase(A3),A0 ; point to the DAFB base
|
|
|
|
; DAFBÕs vertical timing generator is driven from a clock which is only half the frequency of the horizontal
|
|
; timing generator clock. Therefore, all the vertical timing registers are double-sized. However, the
|
|
; CrsrLine register is specified in whole lines. So, in order to get VBL happening at just the right
|
|
; time, we must divide VFP by 2.
|
|
;
|
|
Move.l Swatch_VFP(A0),D0 ; Get current VFP.
|
|
Andi.l #$FFF,D0 ; Strip off junk.
|
|
Lsr.l #1,D0 ; Divide by 2.
|
|
Addq #1,D0 ; Add 1.
|
|
Move.l D0,Swatch_CrsrLine(A0) ; Set interrupt to occur AFTER VFP, and
|
|
Move.l #dafbEnableVInts,Swatch_IntMsk(A0) ; turn on interrupt.
|
|
|
|
MOVE.B (SP)+,D0 ; get addressing mode back
|
|
_SwapMMUMode ;
|
|
|
|
CMP D0,D0 ; clear z-bit for good result
|
|
@IntBad RTS ; return home (if bad, z-bit is set above, so just leave) <8>
|
|
|
|
ENDWITH
|
|
|
|
DAFBDirectSetEntries
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Change the CLUT in a direct mode.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
; This routine allows knowledgeable programs modify the contents
|
|
; of the CLUT in direct modes (usually for limited color previewing).
|
|
; It takes the same parameter block as SetEntries, but SetEntries
|
|
; intentionally does not operate when the card is in a direct pixMode.
|
|
; This routine takes the same data and operates ONLY when in direct
|
|
; modes. It calls the same SetEntries guts as the regular routine.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
|
|
BEQ DAFBCtlBad ; error if not
|
|
BRA DAFBSEGuts ; jump to SetEntries internals if it's OK
|
|
|
|
DAFBSetDefaultMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Write the card default mode into slot pRAM.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
; This routine is called by Monitors when somebody selects an alternate
|
|
; video mode family in the Options dialog.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; 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 screen depth. Built-in video keeps the video
|
|
; sRsrc spID in VendorUse2.
|
|
;
|
|
|
|
SUBA #SizesPRAMRec,SP ; allocate block for pRAM record
|
|
MOVE.L SP,spResult(A0) ; point to it
|
|
_sReadPRAMRec ; read it
|
|
|
|
;
|
|
; Since PrimaryInit relies on the default mode being set correctly, we check to see that
|
|
; the mode to be set is actually valid. Monitors can only see valid sRsrcIDs, so
|
|
; it probably wonÕt cause a problem. But we should check it anyway for unsavory
|
|
; applications.
|
|
;
|
|
|
|
Move.b csMode(A2),spID(A0) ; Look for the passed in spID.
|
|
Clr.l spParamData(A0) ; Clear the fNext flag; we want THIS sRsrc.
|
|
Ori.b #(1<<fall)|\ ; Search for both enabled/disabled sRsrcÕs
|
|
(1<<foneslot),spParamData+3(A0) ; Only search in our slot.
|
|
_GetsRsrc ; Do it.
|
|
Bne.s @BadExit ; If failed, quit.
|
|
|
|
Move.w spCategory(A0),D0 ; Get the category.
|
|
Cmp.w #catDisplay,D0 ; If itÕs not catDisplay,
|
|
Bne.s @BadExit ; then quit.
|
|
Move.w spCType(A0),D0 ; Get the type.
|
|
Cmp.w #typVideo,D0 ; If itÕs not typVideo,
|
|
Bne.s @BadExit ; then quit.
|
|
Move.w spDrvrSw(A0),D0 ; Get the software kind.
|
|
Cmp.w #drSwApple,D0 ; If itÕs not drSwApple,
|
|
Bne.s @BadExit ; then quit.
|
|
Move.w spDrvrHw(A0),D0 ; Get the hardware ID.
|
|
Cmp.w #drHwDAFB,D0 ; If itÕs not drHwDAFB,
|
|
Bne.s @BadExit ; then quit.
|
|
|
|
;
|
|
; It is very important that Monitors (or someone) invalidate and setup the screen resource
|
|
; if this call is exercised. Monitors needs to verify (and potentially re-write to pRAM)
|
|
; the proper screen depth in the new world.
|
|
;
|
|
|
|
Btst #IsDirect,GFlags(A3) ; If weÕre not in a direct mode,
|
|
Beq.s @WriteIt ; just go on.
|
|
|
|
Move.b csMode(A2),D0 ; Get the mode weÕre going to.
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvSTx,D0 ; If weÕre not going to a convolved mode,
|
|
Blt.s @WriteIt ; just go on.
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvFF,D0 ;
|
|
Bgt.s @WriteIt ;
|
|
Move.b #FourthVidMode,SP_Depth(Sp) ; Otherwise, reset the depth to indexed.
|
|
|
|
@WriteIt MOVE.B csMode(A2),SP_LastConfig(SP) ; write the mode into pRAM buffer
|
|
MOVE.L SP,spsPointer(A0) ; set up parameter block
|
|
_sPutPRAMRec ; write the new record out
|
|
|
|
@GoodExit ADDA #SizesPRAMRec+spBlockSize,SP ; Deallocate buffer and
|
|
BRA DAFBCtlGood ; return good result.
|
|
|
|
@BadExit Adda #SizesPRAMRec+spBlockSize,SP ; Deallocate buffer and
|
|
Bra DAFBCtlBad ; return bad result.
|
|
|
|
ENDWITH
|
|
|
|
DAFBSetSyncOnGreen
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Enable (csMode = 0) or disable (csMode = non-zero) the sync on green.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make a SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam record so that we can write it back if necessary.
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
;
|
|
; See what we need to doÉ
|
|
;
|
|
|
|
Tst.b csMode(A2) ; If csMode = 0, then we are
|
|
Beq.s @EnableSyncOnGreen ; enabling sync on green.
|
|
|
|
Btst #syncOnGreen,GFlags(A3) ; If weÕre already NOT putting sync on green,
|
|
Beq.s @Done ; then thereÕs nothing left to do.
|
|
Bclr #syncOnGreen,GFlags(A3) ; Otherwise, set up the GFlags field,
|
|
Bclr #spSyncOnGreen,SP_Flags(Sp) ; the pRam record, and
|
|
Moveq #0,D1 ; the toggle bit.
|
|
Bra.s @SyncCommon ;
|
|
|
|
@EnableSyncOnGreen
|
|
Btst #syncOnGreen,GFlags(A3) ; If weÕre already putting sync on green,
|
|
Bne.s @Done ; then thereÕs nothing left to do.
|
|
Bset #syncOnGreen,GFlags(A3) ; Otherwise, set up the GFlags field
|
|
Bset #spSyncOnGreen,SP_Flags(Sp) ; the pRam record, and
|
|
Moveq #1,D1 ; the toggle bit.
|
|
|
|
@SyncCommon
|
|
Move.l Sp,spsPointer(A0) ; Set up to whack pRam.
|
|
_sPutPRAMRec ; Whack it.
|
|
|
|
Moveq #true32b,D0 ; Set up to flip into 32-bit addressing mode.
|
|
_SwapMMUMode ; Do flip.
|
|
Move.b D0,-(Sp) ; Save previous mode for later.
|
|
|
|
Move.w Sr,-(Sp) ; Save the current interrupt level.
|
|
Bsr DAFBWaitVSync ; Wait for VBL at level 2.
|
|
Move.w (Sp)+,Sr ; Restore interrupt level.
|
|
|
|
Tst.b wombatFlag(A3) ; If weÕre not on a Wombat,
|
|
Beq.s @VIASOG ; then use the VIA SOG.
|
|
|
|
Move.l saveDAFBBase(A3),A0 ; Get DAFBBase into A0.
|
|
Move.l DAFB_ClkCfg(A0),D0 ; Get the current clock config value.
|
|
Bfins D1,D0{dafbSyncOnGreen:1} ; Toggle the sync-on-green bit appropriately,
|
|
Move.l D0,DAFB_ClkCfg(A0) ; apply it.
|
|
Bra.s @EndSOG ;
|
|
|
|
@VIASOG Move.l VIA2,A0 ; Point to VIA2.
|
|
Btst #0,D1 ; If weÕre supposed to put sync on green,
|
|
Bne.s @SyncOnGreen ; then hop to it.
|
|
Bclr #v2SyncOnGreen,vBufA(A0) ; Otherwise, disable sync on green.
|
|
Bra.s @EndSOG
|
|
@SyncOnGreen
|
|
Bset #v2SyncOnGreen,vBufA(A0) ; Enable sync on green.
|
|
|
|
@EndSOG Move.b (Sp)+,D0 ; Set up to switch back to prev mode,
|
|
_SwapMMUMode ; and do it.
|
|
|
|
@Done Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBCtlGood ; go home.
|
|
|
|
EndWith
|
|
|
|
DAFBSet16bpp
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Enable (csMode = 0) or disable (csMode = non-zero) the 16bpp mode
|
|
; if AC842A is around.
|
|
;
|
|
; Notes: To determine if 16bpp is possible, one should call
|
|
; Get16bpp. If it returns noErr, then 16bpp is
|
|
; possible, otherwise it isnÕt.
|
|
;
|
|
; To determine if 16bpp is ALWAYS non-blocked, one should
|
|
; attempt to disable 16bpp mode. If noErr is returned,
|
|
; but Get16bpp returns the enabled state, then the
|
|
; 16bpp is always non-blocked.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage/ptr to DAFBBase addr (not restored)
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make an SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam so that we can tell whether an AC842A is actually
|
|
; intalled.
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
Btst #spHas16bppACDC,SP_Flags(Sp) ; If we donÕt have an AC842A,
|
|
Beq.s @BadExit ; then just blow this off.
|
|
|
|
Moveq #true32b,D0 ; Set up to switch into 32-bit mode,
|
|
_SwapMMUMode ; do switch, and
|
|
Move.b D0,D1 ; save previous mode.
|
|
|
|
Btst #IsSlow,GFlags(A3) ; If CPU is running at 25MHz,
|
|
Bne.s @DoSet ; then do things as normal.
|
|
Move.l saveDAFBBase(A3),A3 ; Get DAFBBase into A3.
|
|
Move.l DAFB_Test(A3),D0 ; Get the DAFBTest register.
|
|
Andi.w #$0FFF,D0 ; Strip off the junk.
|
|
Moveq #9,D2 ; Get the amount to shift.
|
|
Lsr.w D2,D0 ; Shift in the version number.
|
|
Cmp.b #DAFB3Vers,D0 ; If we donÕt have a DAFB 3,
|
|
Blt.s @DoSet ; then do things as normal.
|
|
Bra.s @GoodExit ; Otherwise, 16bpp is always set.
|
|
|
|
;
|
|
; See what we need to doÉ
|
|
;
|
|
|
|
@DoSet Tst.b csMode(A2) ; If csMode = 0, then we are
|
|
Beq.s @Allow16bpp ; allowing 16bpp.
|
|
|
|
Bclr #spAllow16bpp,SP_Flags(Sp) ; If we are already blocking 16bpp
|
|
Beq.s @GoodExit ; then no need to whack pRam again.
|
|
Bra.s @16BppCommon ; Otherwise, whack it.
|
|
|
|
@Allow16bpp Bset #spAllow16bpp,SP_Flags(Sp) ; If we are already allowing 16bpp,
|
|
Bne.s @GoodExit ; then no need to whack pRam again.
|
|
|
|
@16bppCommon Move.l Sp,spsPointer(A0) ; Set up to whack pRam.
|
|
_sPutPRAMRec ; Whack it.
|
|
|
|
@GoodExit Move.b D1,D0 ; Set up to switch back into previous mode,
|
|
_SwapMMUMode ; do switch, and
|
|
|
|
Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBCtlGood ; go home.
|
|
|
|
@BadExit Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBCtlBad ; return error.
|
|
|
|
EndWith
|
|
|
|
DAFBSetPageMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Enable (csMode = 0) or disable (csMode = non-zero) Page Mode.
|
|
;
|
|
; A1 = Ptr to AuxDCE/ptr to DAFBBase addr (not restored)
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make an SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam so that we can set it appropriatelyÉ
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
Moveq #true32b,D0 ; Set up to switch into 32-bit mode,
|
|
_SwapMMUMode ; do switch, and
|
|
Move.b D0,D1 ; save previous mode.
|
|
|
|
Move.l saveDAFBBase(A3),A1 ; Get DAFBBase into A1 for below.
|
|
|
|
;
|
|
; See what we need to doÉ
|
|
;
|
|
|
|
Tst.b csMode(A2) ; If csMode = 0, then we are
|
|
Beq.s @EnablePageMode ; enabling page mode.
|
|
|
|
Move.b #0,pageModeSet(A3) ; Say page mode is disaabled.
|
|
Bclr #spPageMode,SP_Flags(Sp) ; Flip pRam bit.
|
|
Bra.s @EndPageMode ;
|
|
|
|
@EnablePageMode Move.b #1,pageModeSet(A3) ; Say page mode is enabled.
|
|
Bset #spPageMode,SP_Flags(Sp) ; Flip pRam bit.
|
|
|
|
@EndPageMode Move.l Sp,spsPointer(A0) ; Set up to whack pRam.
|
|
_sPutPRAMRec ; Whack it.
|
|
|
|
Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack.
|
|
|
|
Move.l DAFB_Config(A1),D0 ; Read the DAFBConfig register.
|
|
Bfextu D0{dafbWrdIntBit:1},D0 ; If word-interleave is on
|
|
Bne.s @DisablePageMode ; then ALWAYS disable page mode.
|
|
Tst.b pageModeSet(A3) ; If weÕre not supposed to enable page mode,
|
|
Beq.s @DisablePageMode ; then disable it.
|
|
Moveq #1,D0 ; Otherwise, set up to enable page mode,
|
|
Bra.s @HitPageMode ; and do it.
|
|
@DisablePageMode
|
|
Moveq #0,D0 ; Set up to disable page mode, and
|
|
@HitPageMode Move.l D0,DAFB_PgMdEn(A1) ; and do it.
|
|
|
|
@ExitPageMode Move.b D1,D0 ; Set up to switch back into previous mode,
|
|
_SwapMMUMode ; do switch, and
|
|
Bra DAFBCtlGood ; leave.
|
|
|
|
EndWith
|
|
|
|
DAFBSetAltSense
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; SetAltSense sets up the alternate senseID pRam byte to contain
|
|
; a valid ÒindexÓ code if a valid sense code is passed
|
|
; in csMode (byte 0 is the sense code, byte 1 is the type).
|
|
;
|
|
; A1 = Ptr to AuxDCE/Ptr to DAFBMonIDs table (not restored)
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make an SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam so that we can set it appropriatelyÉ
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
;
|
|
; See what we need to doÉ
|
|
;
|
|
|
|
Move.b csMode+1(A2),D0 ; Get the sense-code type.
|
|
Beq.s @NoConnect ; If indexed (0), use type 7.
|
|
Cmp.b #indexedSense2P,D0 ; If we got a type 3,
|
|
Beq.s @2PExtended ; then go there.
|
|
Cmp.b #indexedSenseHR,D0 ; If we got a type 6,
|
|
Beq.s @HRExtended ; then go there.
|
|
Cmp.b #indexedNoConnect,D0 ; If we got a type 7,
|
|
Beq.s @NoConnect ; then go there.
|
|
Bra @MonIDNotValid ; Otherwise, return an error.
|
|
|
|
@2PExtended
|
|
Move.b csMode(A2),D1 ; Get the sense code into D0.
|
|
Cmp.b #extended2PRdRGB,D1 ; If itÕs the Radius ColorTPD,
|
|
Beq @WriteIt ; then write it out.
|
|
Cmp.b #extended2PRdMono,D1 ; If itÕs the Radius MonoTPD,
|
|
Beq.s @WriteIt ; then write it out.
|
|
Bra @MonIDNotValid ; Otherwise, return an error.
|
|
|
|
@HRExtended
|
|
Cmp.b #extendedHR,csMode(A2) ; If itÕs not the MultiSync code,
|
|
Bne @MonIDNotValid ; return an error.
|
|
Move.b #indexedSenseHR,D1 ; Otherwise, default to HR.
|
|
Bra.s @WriteIt
|
|
|
|
@NoConnect
|
|
Move.b csMode(A2),D1 ; Get the monID.
|
|
Cmp.b #indexedNoConnect,D1 ; If itÕs one of the no-connect codes,
|
|
Beq.s @ClearIt ; then zero-out the no-connect pRam byte.
|
|
Cmp.b #extendedNoConnect,D1 ;
|
|
Beq.s @ClearIt ;
|
|
|
|
Lea DAFBMonIDs,A1 ; Get ptr to DAFBMonIDs table.
|
|
Move.w (A1)+,D0 ; Get count of modes.
|
|
|
|
@ValidLoop Move.b (A1)+,D1 ; Get an ID from the table.
|
|
Cmp.b csMode(A2),D1 ; If we have a match,
|
|
Beq.s @FoundMatch ; say so.
|
|
Dbra D0,@ValidLoop ; Otherwise, keep looping thru
|
|
Bra.s @MonIDNotValid ; table until no match is found.
|
|
|
|
@FoundMatch Tst.b csMode+1(A2) ; If this is not an extended code,
|
|
Beq.s @WriteIt ; then just do write.
|
|
|
|
Cmp.b #extendedSenseVGA,D1 ; Is it the VGA code?
|
|
Bne.s @TryPal ; Nope, try PAL.
|
|
Move.b #indexedSenseVGA,D1
|
|
Bra.s @WriteIt
|
|
|
|
@TryPal Cmp.b #extendedSensePAL,D1 ; Is it the PAL code?
|
|
Bne.s @TryPALBox ; Nope, try PAL encoder box.
|
|
Move.b #indexedSensePAL,D1
|
|
Bra.s @WriteIt
|
|
|
|
@TryPALBox Cmp.b #extendedSensePALBox,D1 ; Is it the PAL encoder box code?
|
|
Bne.s @TryNTSC ; Nope, try NTSC encoder box.
|
|
Move.b #indexedSensePAL,D1
|
|
Bra.s @WriteIt
|
|
|
|
@TryNTSC Cmp.b #extendedSenseNTSC,D1 ; Is it the NTSC encoder box code?
|
|
Bne.s @TryLP ; Nope, try GoldFish.
|
|
Move.b #indexedSenseNTSC,D1
|
|
Bra.s @WriteIt
|
|
|
|
@TryLP Cmp.b #extendedSenseLP,D1 ; Is it the GoldFish?
|
|
Bne.s @Try19 ; Nope, try 19Ó.
|
|
Move.b #indexedSenseLP,D1 ;
|
|
Bra.s @WriteIt
|
|
|
|
@Try19 Cmp.b #extendedSense19,D1 ; Is it a 19Ó?
|
|
Bne.s @WriteIt ; Nope, must be indexed.
|
|
Move.b #indexedSense19,D1
|
|
|
|
@WriteIt Move.b D1,SP_AltSense(Sp) ; Write out ÒindexÓ to pRam record.
|
|
Ori.b #spAltSenseValidMask,SP_AltSense(Sp) ; Validate it.
|
|
Bra.s @WritePRam
|
|
|
|
@ClearIt Clr.b SP_AltSense(Sp) ; Invalidate no-connect byte.
|
|
|
|
@WritePRam Move.l Sp,spsPointer(A0) ; Set up to whack pRam.
|
|
_sPutPRAMRec ; Whack it.
|
|
|
|
Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack.
|
|
Bra DAFBCtlGood ; leave.
|
|
|
|
@MonIDNotValid Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack.
|
|
Bra DAFBCtlBad ; leave with error.
|
|
|
|
Endwith
|
|
|
|
**********************************************************************
|
|
*
|
|
* VideoClose releases the device's private storage and removes the
|
|
* interrupt handler.
|
|
*
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
*
|
|
* Other: A2 = temporary AuxDCE pointer copy
|
|
*
|
|
**********************************************************************
|
|
|
|
DAFBVidClose
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
BSR DAFBDisableVGuts ; call utility to deactivate interrupts
|
|
|
|
Moveq #true32b,D0 ; Set up to flip into 32-bit addressing.
|
|
_SwapMMUMode ; Flip.
|
|
Move.l saveDAFBBase(A3),A2 ; (Get DAFBBase into A2 for DAFBIdle macro.)
|
|
DAFBIdle ; Put DAFB into an idle state.
|
|
_SwapMMUMode ; Restore previous addressing mode.
|
|
|
|
MOVE.L saveSQElPtr(A3),A0 ; get the slot interrupt queue element ptr
|
|
_DisposPtr
|
|
|
|
MOVE.L saveGamDispPtr(A3),A0 ; get pointer to gamma table block
|
|
_DisposPtr ; and dispose it
|
|
|
|
Move.l saveVidPtr(A3),A0 ; Get pointer to video parameters block,
|
|
_DisposPtr ; and dispose of it.
|
|
|
|
MOVE.L dCtlStorage(A1),A0 ; dispose of the private storage
|
|
_DisposHandle ;
|
|
|
|
MOVEQ #noErr,D0 ; no error
|
|
RTS ; and return
|
|
|
|
ENDWITH
|
|
|
|
**********************************************************************
|
|
*
|
|
* Video Driver Status Call Handler. There are ten standard calls:
|
|
*
|
|
* ($00) Error
|
|
* ($01) Error
|
|
* ($02) GetMode
|
|
* ($03) GetEntries
|
|
* ($04) GetPage
|
|
* ($05) GetPageBase
|
|
* ($06) GetGray
|
|
* ($07) GetInterrupt
|
|
* ($08) GetGamma
|
|
* ($09) GetDefaultMode
|
|
*
|
|
* The following calls are DAFB-specific:
|
|
*
|
|
* ($80) GetSyncOnGreen
|
|
* ($81) Get16bpp
|
|
* ($82) GetPageMode
|
|
* ($83) GetAltSense
|
|
*
|
|
* Entry: A0 = paramblock pointer
|
|
* A1 = AuxDCE pointer
|
|
* Uses: A2 = cs parameters
|
|
* A3 = pointer to private storage
|
|
* D0-D3 = scratch (don't need to be preserved)
|
|
*
|
|
* Exit: D0 = error code
|
|
*
|
|
**********************************************************************
|
|
|
|
DAFBVidStatus
|
|
|
|
MOVEM.L A0/A1,-(SP) ; Save exit registers.
|
|
|
|
MOVE.L csParam(A0),A2 ; A2 <- Ptr to control parameters
|
|
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
MOVE.W csCode(A0),D0 ; get routine selector
|
|
|
|
Cmp.w #cscSyncOnGreen,D0 ; If we got the GetSyncOnGreen call,
|
|
Beq DAFBGetSyncOnGreen ; hop to it.
|
|
Cmp.w #csc16bpp,D0 ; If we got the Get16bpp call,
|
|
Beq DAFBGet16bpp ; hop to it.
|
|
Cmp.w #cscPageMode,D0 ; If we got the PageMode call,
|
|
Beq DAFBGetPageMode ; hop to it.
|
|
Cmp.w #cscAltSense,D0 ; If we got the AltSense call,
|
|
Beq DAFBGetAltSense ; hop to it.
|
|
|
|
CMP.W #9,D0 ;IF csCode NOT IN [0..9] THEN
|
|
BHI.S DAFBStatBad ; Error, csCode out of bounds.
|
|
MOVE.W DAFBStatJumpTbl(PC,D0.W*2),D0 ;Get the relative offset to the routine.
|
|
JMP DAFBStatJumpTbl(PC,D0.W) ;GOTO the proper routine.
|
|
|
|
DAFBStatJumpTbl
|
|
DC.W DAFBStatBad-DAFBStatJumpTbl ;$00 => Error
|
|
DC.W DAFBStatBad-DAFBStatJumpTbl ;$01 => Error
|
|
DC.W DAFBGetMode-DAFBStatJumpTbl ;$02 => GetMode
|
|
DC.W DAFBGetEntries-DAFBStatJumpTbl ;$03 => GetEntries
|
|
DC.W DAFBGetPage-DAFBStatJumpTbl ;$04 => GetPage
|
|
DC.W DAFBGetPageBase-DAFBStatJumpTbl ;$05 => GetPageBase
|
|
DC.W DAFBGetGray-DAFBStatJumpTbl ;$06 => GetGray
|
|
DC.W DAFBGetInterrupt-DAFBStatJumpTbl ;$07 => GetInterrupt
|
|
DC.W DAFBGetGamma-DAFBStatJumpTbl ;$08 => GetGamma
|
|
DC.W DAFBGetDefaultMode-DAFBStatJumpTbl ;$09 => GetDefaultMode
|
|
|
|
DAFBStatBad MOVEQ #statusErr,D0 ; else say we don't do this one
|
|
BRA.S DAFBStatDone ; and return
|
|
|
|
DAFBStatGood MOVEQ #noErr,D0 ; return no error
|
|
|
|
DAFBStatDone MOVEM.L (SP)+,A0/A1 ; Restore exit registers.
|
|
BRA DAFBExitDrvr
|
|
|
|
DAFBGetMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the current mode
|
|
;
|
|
; Inputs : A2 = pointer to csParams
|
|
; A3 = pointer to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE.W saveMode(A3),csMode(A2) ; return the mode
|
|
Clr.w csPage(A2) ; return the page number (always 0)
|
|
|
|
Move.l saveScreenBase(A3),csBaseAddr(A2) ; Return the ST-corrected screen baseAddr.
|
|
BRA.S DAFBStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetEntries
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Read the current contents of the CLUT. These values were gamma corrected
|
|
; when they were set (by DAFBSetEntries), so they may not match the source
|
|
; cSpec array.
|
|
;
|
|
; Inputs : A1 = pointer to AuxDCE
|
|
; A2 = pointer to csParams/CLUT read register (not restored to csParams)
|
|
; A3 = pointer to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
Movem.l D4-D6,-(Sp) ; Save work registers.
|
|
Tst.l -(Sp) ; Make some room.
|
|
|
|
Move.l csTable(A2),D0 ; If we were handed a nil pointer,
|
|
Beq @GEErr ; then hike.
|
|
_StripAddress ; Make table pointer 32-bit clean.
|
|
Move.l D0,(Sp) ; And save it.
|
|
|
|
Move.w saveMode(A3),D1 ; Get the current video mode.
|
|
Sub.w #firstVidMode,D1 ; Convert it to an index.
|
|
Move.l D1,D6 ; Save it for later.
|
|
|
|
Move.w GFlags(A3),D5 ; Get the flags for quick access.
|
|
|
|
Btst #has16bppSRsrc,D5 ; If we have a 16bpp-capable sRsrc,
|
|
Bne.s @GetXTable ; then use the extended table.
|
|
Lea DAFBClutTbl,A0 ; Otherwise, just use the normal table.
|
|
Bra.s @ChkRange ;
|
|
|
|
@GetXTable Lea DAFBXClutTbl,A0 ; Point to extended table of counts.
|
|
Cmp.w #FifthVidMode-FirstVidMode,D6 ; If this is not 16bpp mode,
|
|
Bne.s @ChkRange ; then just go on.
|
|
Tst.b hasLin16bppCLUT(A3) ; If 16bpp is linear (i.e., we have Antelope),
|
|
Bne.s @ChkRange ; then just on.
|
|
Bset #UseTrans,D5 ; Otherwise, remember to do translation.
|
|
|
|
@ChkRange Moveq #0,D3 ; Set up to get count.
|
|
Move.b (A0,D1.w),D3 ; Get clut count.
|
|
|
|
Move.w csCount(A2),D4 ; Get the number of entries to fill,
|
|
Bmi.s @GEErr ; and hike if itÕs out of range.
|
|
Cmp.w D3,D4 ; If D4-D3 > 0 (count > entries),
|
|
Bhi.s @GEErr ; then hike.
|
|
Move.w D4,D2 ; Otherwise, copy the count.
|
|
|
|
Cmp.w #indexEntries,csStart(A2) ; If table accesses are to be indexed,
|
|
Beq.s @GECom ; then go on.
|
|
|
|
Move.w D4,D1 ; Otherwise, sequence thru table from
|
|
Add.w csStart(A2),D2 ; csStart thru csCount entries.
|
|
|
|
; The following code is BAD, BAD, BAD! We should build our own table here so
|
|
; as to NOT mess up the userÕs data. But all the previous Apple video drivers
|
|
; have done the same thing here, so weÕll continue the trend for now.
|
|
|
|
Move.l (Sp),A0 ; Get ptr to csTable.
|
|
|
|
@TableLoop Move.w D2,value(A0,D1*colorSpecSize) ; Write the index into the table.
|
|
Subq #1,D2 ; Decrement index.
|
|
Dbra D1,@TableLoop ;
|
|
|
|
@GECom Moveq #true32b,D0 ; Save previous MMU mode and set MMU to
|
|
_SwapMMUMode ; 32-bit addressing when dealing with DAFB.
|
|
|
|
Move.l (Sp)+,A0 ; Get/restore ptr to csTable.
|
|
|
|
Move.l saveVDACBase(A3),A2 ; Get ACDC base address.
|
|
Add.l #ACDC_DataReg,A2 ; Add offset to Clut read register.
|
|
|
|
Move.w Sr,-(Sp) ; Save current interrupt level
|
|
Bsr DAFBWaitVSync ; Wait for VBL.
|
|
|
|
@Repeat Move.w value(A0),D1 ; Get the NEXT Clut position into D1.
|
|
Cmp.w D3,D1 ; If this position is out of range,
|
|
Bhi.s @Until ; then go on.
|
|
|
|
Btst #UseTrans,D5 ; If weÕre not supposed to translate this index,
|
|
Beq.s @Index ; then just go on.
|
|
Bsr DAFBTrans5to8 ; Otherwise, do translation.
|
|
|
|
@Index Move.l D1,ACDC_AddrReg-ACDC_DataReg(A2) ; Tell the Clut where to read from.
|
|
Nop ; (DAFB address space is non-serial.)
|
|
|
|
Move.l (A2),D1 ; Get Red:
|
|
Move.b D1,rgb+red(A0) ; --> $rrXX
|
|
Move.b D1,rgb+red+1(A0) ; --> $rrrr
|
|
|
|
Move.l (A2),D1 ; Get Green:
|
|
Move.b D1,rgb+green(A0) ; --> $ggXX
|
|
Move.b D1,rgb+green+1(A0) ; --> $gggg
|
|
|
|
Move.l (A2),D1 ; Get Blue:
|
|
Move.b D1,rgb+blue(A0) ; --> $bbXX
|
|
Move.b D1,rgb+blue+1(A0) ; --> $bbbb
|
|
|
|
@Until Addq #colorSpecSize,A0 ; Point to next entry ColorTable.
|
|
Dbra D4,@Repeat
|
|
|
|
Move.w (Sp)+,Sr ; Restore previous interrupt level.
|
|
_SwapMMUMode ; Restore previous addressing mode.
|
|
|
|
Movem.l (Sp)+,D4-D6 ; Restore work registers.
|
|
Bra DAFBStatGood ; Return noError.
|
|
|
|
@GEErr Tst.l (Sp)+ ; Clean up stack.
|
|
Movem.l (Sp)+,D4-D6 ; Restore work registers.
|
|
Bra DAFBStatBad ; Return statError.
|
|
|
|
DAFBGetPage
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the number of pages in the specified mode. It's pretty simple;
|
|
; every mode has only one page. We do check if it's valid, however.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE csMode(A2),D1 ; get the mode
|
|
MOVE D1,D2 ; keep a copy
|
|
BSR DAFBChkMode ; is this mode OK?
|
|
BNE DAFBStatBad ; => not a valid mode
|
|
|
|
MOVE.W #1,csPage(A2) ; return page count
|
|
BRA DAFBStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetPageBase
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the base address for the specified page in the current mode
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
TST.W csPage(A2) ; are we returning page zero info?
|
|
BNE DAFBStatBad ; only page 0 is valid
|
|
|
|
Move.l saveScreenBase(A3),csBaseAddr(A2) ; Return the ST-corrected screen baseAddr.
|
|
BRA DAFBStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetGray
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return a boolean, set true if luminance mapping is on
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVEQ #0,D1 ; set up for BFEXTU
|
|
|
|
DAFBGetFlagCom
|
|
|
|
BFEXTU GFlags(A3){D1:1},D0 ; get the state of flag
|
|
MOVE.B D0,csMode(A2) ; return value
|
|
BRA DAFBStatGood ; => and return
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetInterrupt
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return a boolean in csMode, set true if VBL interrupts are disabled
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVEQ #1,D1 ; set up BFEXTU to point at IntDisFlag
|
|
BRA.S DAFBGetFlagCom ; and use common code
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetGamma
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the pointer to the current gamma table
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH DAFBVidPrivates
|
|
|
|
MOVE.L saveGammaPtr(A3),csGTable(A2) ; return the pointer to the structure
|
|
BRA DAFBStatGood ; and return a good result
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetDefaultMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Read the card default mode from slot pRAM.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; 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. Built-in video keeps the last
|
|
; selected video sRsrc spID in VendorUse2.
|
|
;
|
|
|
|
SUBA #SizesPRAMRec,SP ; allocate block for pRAM record
|
|
MOVE.L SP,spResult(A0) ; point to it
|
|
_sReadPRAMRec ; read it
|
|
|
|
MOVE.B SP_LastConfig(SP),csMode(A2) ; return the result
|
|
ADDA #SizesPRAMRec+spBlockSize,SP ; release buffer
|
|
BRA DAFBStatGood ;
|
|
|
|
ENDWITH
|
|
|
|
DAFBGetSyncOnGreen
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return a boolean in csMode, set true if sync-on-green is disabled.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With DAFBVidPrivates
|
|
|
|
Btst #syncOnGreen,GFlags(A3) ; If weÕre putting sync on green,
|
|
Bne.s @IsOn ; then return enabled state.
|
|
Move.b #1,csMode(A2) ; Otherwise, return disabled.
|
|
Bra DAFBStatGood
|
|
|
|
@IsOn
|
|
Clr.b csMode(A2) ; Return enabled state.
|
|
Bra DAFBStatGood
|
|
|
|
EndWith
|
|
|
|
DAFBGet16bpp
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return a boolean in csMode, set true if 16bpp is blocked.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make a SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam so that we can tell whether an AC842A is actually
|
|
; intalled, and then return whether 16bpp is blocked or not.
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
Btst #spHas16bppACDC,SP_Flags(Sp) ; If we donÕt have an AC842A,
|
|
Beq.s @BadExit ; then just blow this off.
|
|
|
|
Btst #spAllow16bpp,SP_Flags(Sp) ; If we allowing 16bpp,
|
|
Bne.s @NotBlocked ; then return non-blocked state.
|
|
Move.b #1,csMode(A2) ; Otherwise, return blocked.
|
|
Bra.s @GoodExit
|
|
@NotBlocked Clr.b csMode(A2) ; Return enabled state.
|
|
|
|
@GoodExit Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBStatGood ; go home.
|
|
|
|
@BadExit Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBStatBad ; return error.
|
|
|
|
EndWith
|
|
|
|
DAFBGetPageMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Returns a boolean in csMode, set true if page mode is disabled.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With DAFBVidPrivates
|
|
|
|
Moveq #true32b,D0 ; Set up to switch into 32-bit mode,
|
|
_SwapMMUMode ; do switch, and
|
|
Move.b D0,-(Sp) ; save previous mode.
|
|
|
|
Move.l saveDAFBBase(A3),A0 ; Get DAFBBase into A0.
|
|
Move.l DAFB_PgMdEn(A0),D0 ; Get page mode.
|
|
Btst #0,D0 ; If page mode is on,
|
|
Bne.s @IsOn ; then return enabled state.
|
|
Move.b #1,csMode(A2) ; Otherwise, return disabled,
|
|
Bra.s @EndPageMode ; and leave.
|
|
|
|
@IsOn Clr.b csMode(A2) ; Return enabled state.
|
|
|
|
@EndPageMode Move.b (Sp)+,D0 ; Set up to switch back into previous mode,
|
|
_SwapMMUMode ; do switch, and
|
|
Bra DAFBCtlGood ; leave.
|
|
|
|
EndWith
|
|
|
|
DAFBGetAltSense
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Returns the alternate senseID code thatÕs in use. It
|
|
; should be noted that we cannot disguish between PAL &
|
|
; NTSC monitors & encoder boxes once DAFBSetAltSense has
|
|
; been called (because both the monitor & box codes are
|
|
; mapped into the same indexedSense code).
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With spBlock,DAFBVidPrivates,SP_Params
|
|
|
|
;
|
|
; First, set up a slot parameter block on the stack.
|
|
;
|
|
|
|
Suba #spBlockSize,Sp ; Make a SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Set it up.
|
|
Clr.b spExtDev(A0)
|
|
|
|
;
|
|
; Next, read the current pRam so that we can determine whether the
|
|
; alternate senseID code is valid or not.
|
|
;
|
|
|
|
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
|
Move.l Sp,spResult(A0) ; Point to it.
|
|
_sReadPRamRec ; Get pRAM.
|
|
|
|
Clr.b csMode+1(A2) ; Assume the code already indexed for now.
|
|
|
|
Move.b SP_AltSense(Sp),D0 ; Get the alternate senseID byte.
|
|
Andi.b #spAltSenseValidMask,D0 ; If it is valid,
|
|
Bne.s @Valid ; return it.
|
|
Move.b #indexedNoConnect,csMode(A2) ; Otherwise, return the indexed no-connect code,
|
|
Bra.s @Exit ; and leave.
|
|
|
|
@Valid Move.b SP_AltSense(Sp),D0 ; Get the no-connect byte again.
|
|
Andi.b #spAltSenseMask,D0 ; Strip the validation code.
|
|
|
|
Cmp.b #indexedSenseVGA,D0 ; Is it the VGA code?
|
|
Bne.s @TryPal ; Nope, try PAL.
|
|
Move.b #extendedSenseVGA,D0
|
|
Bra.s @WriteExtended
|
|
|
|
@TryPal Cmp.b #indexedSensePAL,D0 ; Is it the PAL code?
|
|
Bne.s @TryLP ; Nope, try GoldFish.
|
|
Move.b #extendedSensePAL,D0
|
|
Bra.s @WriteExtended
|
|
|
|
@TryLP Cmp.b #indexedSenseLP,D0 ; Is it the GoldFish code?
|
|
Bne.s @Try19 ; Nope, try 19Ó.
|
|
Move.b #extendedSenseLP,D0
|
|
Bra.s @WriteExtended
|
|
|
|
@Try19 Cmp.b #indexedSense19,D0 ; Is it the 19Ó code?
|
|
Bne.s @TryRdRGB ; No, try the Radius ColorTPD.
|
|
Move.b #extendedSense19,D0
|
|
Bra.s @WriteExtended
|
|
|
|
@TryRdRGB Cmp.b #extended2PRdRGB,D0 ; Is it the ColorTPD.
|
|
Bne.s @TryRDMono ; Nope, try the Mono.
|
|
Bra.s @Write2PExtended
|
|
|
|
@TryRdMono Cmp.b #extended2PRdMono,D0 ; Is it the MonoTPD.
|
|
Bne.s @WriteIt ; Nope, assume indexed.
|
|
|
|
@Write2PExtended
|
|
Move.b #indexedSense2P,csMode+1(A2) ; Say code is type 3.
|
|
Bra.s @WriteIt
|
|
|
|
@WriteExtended Move.b #indexedNoConnect,csMode+1(A2) ; Say code is type 7.
|
|
@WriteIt Move.b D0,csMode(A2) ; Return valid monID.
|
|
|
|
@Exit Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
|
Bra DAFBStatGood ; go home.
|
|
|
|
Endwith
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Exit from Control or Status.
|
|
;
|
|
; A0 = Ptr to param block.
|
|
; A1 = Ptr to AuxDCE.
|
|
; D0 = error code.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
DAFBExitDrvr BTST #NoQueueBit,ioTrap(A0) ; no queue bit set?
|
|
BEQ.S DAFBGoIODone ; => no, not immediate
|
|
RTS ; otherwise, it was an immediate call
|
|
|
|
DAFBGoIODone MOVE.L JIODone,-(Sp) ; Get the IODone address,
|
|
Rts ; and go there.
|
|
|
|
;=====================================================================
|
|
;
|
|
; Utilities
|
|
;
|
|
;=====================================================================
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; CalcScreenBaseAddr
|
|
;
|
|
; Returns the proper screen base address for the current page
|
|
; and mode.
|
|
;
|
|
; -> A3: Pointer to driver privates, saveMode(A3) must be set up!
|
|
;
|
|
|
|
DAFBCalcScreenBaseAddr
|
|
|
|
With DAFBVidPrivates,SpBlock,VPBlock
|
|
|
|
Movem.l A0-A1/D0,-(Sp) ; Save work registers.
|
|
|
|
Suba #spBlockSize,Sp ; Make a SpBlock on the stack.
|
|
Move.l Sp,A0 ; Get a pointer to it into A0.
|
|
Clr.b spSlot(A0) ; Say we want Slot 0.
|
|
Clr.b spID(A0) ; Start looking at spID 0.
|
|
Clr.b spExtDev(A0) ; (No external devices.)
|
|
Clr.b spTBMask(A0) ; Only look for DAFB video sResources.
|
|
Move.w #catDisplay,spCategory(A0) ; Look for: catDisplay,
|
|
Move.w #typVideo,spCType(A0) ; typVideo,
|
|
Move.w #drSwApple,spDrvrSW(A0) ; drSwApple,
|
|
Move.w #drHwDAFB,spDrvrHW(A0) ; drHWDAFB.
|
|
Clr.l spParamData(A0) ; (The video sResource must be enabled.)
|
|
Bset #foneslot,spParamData+3(A0) ; Limit search to slot 0.
|
|
_GetTypeSRsrc ; Get the spsPointer.
|
|
|
|
Move.w saveMode(A3),D0 ; Get the ID of the mode weÕre looking for.
|
|
Move.b D0,spID(A0) ; Look for this modeÕs parameters.
|
|
_sFindStruct ; Get the spsPointer.
|
|
|
|
Move.b #mVidParams,spID(A0) ; Look for the mVidParams.
|
|
_sGetBlock ; Grap Õem
|
|
Move.l spResult(A0),A0 ; Save a pointer the mVidParams.
|
|
|
|
Move.l saveBaseAddr(A3),A1 ; Get the active vRam base address.
|
|
Adda.l vpBaseOffset(A0),A1 ; Point to the base of the screen.
|
|
Move.l A1,saveScreenBase(A3) ; Save it.
|
|
|
|
_DisposPtr ; Dispose the mVidParams.
|
|
|
|
Adda #spBlockSize,Sp ; Restore the stack.
|
|
Movem.l (Sp)+,A0-A1/D0 ; Restore work registers.
|
|
Rts
|
|
|
|
Endwith
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Trans5to8
|
|
;
|
|
; The ACDC that supports 16bpp (AC842A) does so in a somewhat unique
|
|
; fashion. That is, it uses a sparse 8-bit CLUT. The
|
|
; translation forumla is as follows:
|
|
;
|
|
; 5-bits [4..0] -> 8-bits [4..04..2].
|
|
;
|
|
; <-> D1: 5-bit value to be converted into an 8-bit index.
|
|
;
|
|
|
|
DAFBTrans5to8
|
|
|
|
Move.l D0,-(Sp) ; Save D0 as scratch.
|
|
Moveq #0,D0 ; Clear it.
|
|
|
|
Move.w D1,D0 ; D1 = ---43210, D0 = ---43210.
|
|
Lsl.w #3,D1 ; D1 = 43210---, D0 = ---43210.
|
|
Lsr.w #2,D0 ; D1 = 43210---, D0 = -----432.
|
|
Or.w D0,D1 ; D1 = 43210432.
|
|
|
|
Move.l (Sp)+,D0 ; Restore D0.
|
|
Rts
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; ChkMode
|
|
;
|
|
; Verifies the requested mode is legal. Converts spID in D1 into
|
|
; zero-based mode number since lots of people want it that way.
|
|
;
|
|
; <-> D1: Mode
|
|
; -> A3: Pointer to driver privates
|
|
;
|
|
; All registers preserved
|
|
;
|
|
; Returns EQ if mode is valid.
|
|
;
|
|
|
|
With DAFBVidParams
|
|
|
|
DAFBChkMode
|
|
|
|
Movem.l A0/D0/D2,-(Sp) ; Save work registers.
|
|
|
|
Sub.w #FirstVidMode,D1 ; Make mode zero-based.
|
|
Blt.s @ModeBad ; If the passed-in mode is < 0,
|
|
; then punt.
|
|
|
|
Btst #IsMono,GFlags(A3) ; If we donÕt have a mono-only display,
|
|
Beq.s @EndMonoChk ; then just go on.
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If weÕre not trying for a direct mode,
|
|
Blt.s @EndMonoChk ; then just go on.
|
|
Bra.s @ModeBad ; Otherwise, punt.
|
|
|
|
@EndMonoChk
|
|
|
|
; For DAFB, all the ÔaÕ modes are even and all the ÔbÕ modes are odd, except
|
|
; for the convolved modes. So, if weÕre not a convolved mode, we just check
|
|
; the oddness or evenness of the spID to determine whether the passed in
|
|
; mode is OK. If itÕs a convolved mode, we will always be in the ÔbÕ configuration,
|
|
; but we just endcode that information into the vidParams table.
|
|
;
|
|
Move.l saveVidPtr(A3),A0 ; Get pointer to video params.
|
|
Adda.w #DVPMaxModeBase,A0 ; Point to MiscParams.
|
|
|
|
Move.b saveSlotID(A3),D0 ; Get functional sRsrcID of display.
|
|
Btst #0,D0 ; If the display is in ÔaÕ mode,
|
|
Beq.s @MakeA ; then say so.
|
|
Bra.s @MakeB ; Otherwise, make it a ÔbÕ mode.
|
|
|
|
@MakeA Moveq #0,D0 ; Say itÕs an ÔaÕ mode.
|
|
Bra.s @MaxMode
|
|
@MakeB Moveq #1,D0 ; Say itÕs a ÔbÕ mode.
|
|
|
|
@MaxMode Move.b D0,D2 ; Remember which mode we have.
|
|
Move.b (A0,D0),D0 ; Get maximum mode for the current display.
|
|
Cmp.b #FirstVidMode,D0 ; If itÕs already indexed,
|
|
Blt.s @ChkMode ; then just check it now.
|
|
Sub.b #FirstVidMode,D0 ; Otherwise, make max mode indexed.
|
|
|
|
Tst.b wombatFlag(A3) ; If we arenÕt on a Wombat,
|
|
Beq.s @16BppChk ; then just go on.
|
|
Cmp.w #indexedSenseRubik,saveMonID(A3) ; If we donÕt have a Rubik,
|
|
Bne.s @16BppChk ; then just go on.
|
|
Tst.b hasLin16BppCLUT(A3) ; If we donÕt have an Antelope,
|
|
Beq.s @16bppChk ; then just go on.
|
|
Subq #1,D0 ; Otherwise, adjust max-mode value
|
|
Bra.s @ChkMode ;
|
|
|
|
@16BppChk Btst #Has16bppSRsrc,GFlags(A3) ; If we have a 16bpp-capable sRsrc list
|
|
Bne.s @ChkMode ; then just go on.
|
|
Subq #1,D0 ; Otherwise, adjust max-mode value.
|
|
|
|
Tst.b D2 ; If weÕve got a ÔbÕ mode,
|
|
Bne.s @ChkMode ; then just go on.
|
|
Cmp.w #indexedSenseRubik,saveMonID(A3) ; If we donÕt have a Rubik,
|
|
Bne.s @ChkMode ; then just go on.
|
|
Subq #1,D0 ; Otherwise, adjust max-mode value.
|
|
|
|
@ChkMode Cmp.w D0,D1 ; If the passed in mode is > max mode,
|
|
Bgt.s @ModeBad ; then punt.
|
|
|
|
@ModeOK Cmp.w D1,D1 ; Set Eq when OK.
|
|
Bra.s @EndChkMode
|
|
|
|
@ModeBad Moveq #-1,D1 ; Set NEq when bad and invalidate D1.
|
|
@EndChkMode Movem.l (Sp)+,A0/D0/D2 ; Restore work registers.
|
|
Rts
|
|
|
|
Endwith
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Wait for vertical blanking. Interrupts are raised to level-2 around
|
|
; this routine.
|
|
;
|
|
; IMPORTANT! - This routine expects to be called in 32-bit addressing mode!!!!
|
|
;
|
|
; A1 = AuxDCE POINTER
|
|
; A3 = pointer to private storage
|
|
;---------------------------------------------------------------------
|
|
|
|
DAFBWaitVSync
|
|
|
|
MOVE.L A0,-(SP) ; Save work registers.
|
|
MOVE.L D0,-(SP) ; (Two MOVEs are faster than a MOVEM.)
|
|
|
|
MOVE.W SR,-(SP) ; Get the status register on stack.
|
|
MOVEQ #7,D0 ; Get mask into D0.
|
|
AND.B (SP),D0 ; Get the interrupt level.
|
|
SUBQ.B #2,D0 ;
|
|
BGE.S @OK ; If ³, then don't change.
|
|
ORI.W #$0200,SR ; Raise above level-2.
|
|
ANDI.W #$FAFF,SR ; Make it level-2
|
|
@OK
|
|
Tst.w (Sp)+ ; Restore stack.
|
|
|
|
MOVE.L saveDAFBBase(A3),A0 ; Point to DAFB.
|
|
CLR.L Swatch_ClrCrsrInt(A0) ; Otherwise, clear the interrupt, just in case,
|
|
; since the interrupt handler
|
|
; canÕt get called here.
|
|
|
|
@WaitForVBL MOVE.L Swatch_IntStat(A0),D0 ; Get the VBL status.
|
|
BTST #dafbIntStatusBit,D0 ; If VBL has NOT occurred,
|
|
BEQ.S @WaitForVBL ; then just spin.
|
|
|
|
@Done MOVE.L (SP)+,D0 ; Restore work registers.
|
|
MOVE.L (SP)+,A0 ; (Two MOVEs are faster than a MOVEM.)
|
|
RTS
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; SetDepth sets the DAFB frame buffer depth, and returns the
|
|
; frame buffer base in driver privates
|
|
;
|
|
; D1 contains the spID of the depth - $80 (the zero based mode ID)
|
|
; A1 = AuxDCE POINTER
|
|
; A2 = parameter block pointer
|
|
; A3 = dCtlStorage pointer
|
|
;
|
|
; Preserves all registers
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
DAFBSetDepth
|
|
|
|
WITH DAFBVidPrivates,DAFBVidParams,DAFBBppParams,SC_Params
|
|
|
|
MOVEM.L D0-D2/A0-A2,-(SP) ; save regs we are using
|
|
|
|
MOVE.L saveDAFBBase(A3),A2 ; get the DAFB base address
|
|
MOVE.L saveVidPtr(A3),A1 ; get a pointer to the screen depth parameters
|
|
MOVE.W D1,D2 ; copy the index
|
|
|
|
Btst #Has16bppSRsrc,GFlags(A3) ; If we have a 16bpp-capable sRsrc list
|
|
Bne.s @IndexOK ; then just go on.
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D2 ; If weÕre not trying to do 32bpp,
|
|
Bne.s @IndexOK ; then just go on.
|
|
Addq #1,D2 ; Otherwise, skip the 16bpp params.
|
|
|
|
@IndexOk MULU #DBPSize+SC_Size,D2 ; index to the correct parameter group
|
|
LEA DVPHdrSize(A1,D2),A1 ; point to the setup parameters
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,-(SP) ; save previous addressing mode
|
|
|
|
; Setup DAFBÉ
|
|
;
|
|
Tst.b wombatFlag(A3) ; If weÕre on a Wombat,
|
|
Bne.s @SetupDAFB ; then just go on.
|
|
Cmp.w #indexedSenseRubik,saveMonID(A3) ; If donÕt have a Rubik,
|
|
Bne.s @SetupDAFB ; then just go on.
|
|
Cmp.w #FirstVidMode-FirstVidMode,D1 ; If weÕre doing 1bpp,
|
|
Beq.s @Rubik1bpp ; set the weird base address.
|
|
|
|
Move.l #8,DAFB_VidBaseHi(A2) ; 2,4,8,16,32bpp-Rubik are std.
|
|
Bra.s @SetupDAFB
|
|
|
|
@Rubik1bpp
|
|
Move.l #7,DAFB_VidBaseHi(A2) ; 1bpp-Rubik is weird.
|
|
|
|
@SetupDAFB
|
|
DAFBWWrite dbpRowWords,DAFB_RowWords ; Set up the RowWords.
|
|
DAFBWWrite dbpConfig,DAFB_Config ; Set up the controller.
|
|
|
|
Move.l DAFB_ClkCfg(A2),D0 ; Pick up the ClkCfg reg.
|
|
Andi.l #$00000100,D0 ; Clear everything but the ClkSel bit.
|
|
DAFBWWrite dbpClkCfg,DAFB_ClkCfg ; Set up the clocking.
|
|
Or.l D0,DAFB_ClkCfg(A2) ; Make sure ClkSel is correct.
|
|
|
|
DAFBSpeedDR ; Reconfigure DAFB for the right CPU speed.
|
|
|
|
; Setup SwatchÉ
|
|
;
|
|
DAFBWWrite dbpTimingAdj,Swatch_TimeAdj ; Set up timing adjustments.
|
|
DAFBWWrite dbpHSerr,Swatch_HSerr ; Set up horizontal timing.
|
|
DAFBWWrite dbpHlfLn,Swatch_HlfLn ;
|
|
DAFBWWrite dbpHEq,Swatch_HEq ;
|
|
DAFBWWrite dbpHSP,Swatch_HSP ;
|
|
DAFBWWrite dbpHBWay,Swatch_HBWay ;
|
|
DAFBWWrite dbpHBrst,Swatch_HBrst ;
|
|
DAFBWWrite dbpHBP,Swatch_HBP ;
|
|
DAFBWWrite dbpHAL,Swatch_HAL ;
|
|
DAFBWWrite dbpHFP,Swatch_HFP ;
|
|
DAFBWWrite dbpHPix,Swatch_HPix ;
|
|
|
|
; Setup ACDCÉ
|
|
;
|
|
Clr.l ACDC_AddrReg(A2) ; Tell ACDC to use PCBR0.
|
|
DAFBWWrite dbpACDCPCBR,ACDC_ConfigReg ; Set up ADCD config register.
|
|
Nop ; (DAFBÕs address space is non-serial.)
|
|
Tst.l ACDC_AddrReg(A2) ; Read the addr reg to make it stick (AC842A).
|
|
|
|
Btst #has16bppSRsrc,GFlags(A3) ; If we donÕt have a 16bpp-capable sRsrc,
|
|
Beq.s @EndDAFB16bpp ; then skip the 16bpp setup.
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If we arenÕt doing 16bpp, then
|
|
Bne.s @EndDAFB16bpp ; just go on.
|
|
Move.l #1,ACDC_AddrReg(A2) ; Tell ACDC to use PCBR1.
|
|
Move.l #$C0,ACDC_ConfigReg(A2) ; Switch to 16bpp.
|
|
Nop ; (DAFBÕs address space is non-serial.)
|
|
Tst.l ACDC_AddrReg(A2) ; Read the addr reg to make it stick (AC842A).
|
|
Clr.l ACDC_AddrReg(A2) ; Tell ACDC to use PCBR0 again.
|
|
|
|
@EndDAFB16bpp
|
|
|
|
; AC842A adjustments. There are a bunch of NOPs in the code below, and thereÕs a good reason for
|
|
; them. It turns out that DAFBÕs address space on the Quadras is non-serial, which means
|
|
; the order of reads and writes is somewhat non-deterministic. Unfortunately, in order
|
|
; to program the AC842A, certain writes MUST precede certain reads, and vice-versa. So,
|
|
; to get around this problem, I have strategically placed various NOPs below. On Õ040Õs,
|
|
; the NOP actually has a function, which is to force pending writes to occur before
|
|
; reads. Cool, huh!
|
|
;
|
|
Tst.b has16bppACDC(A3) ; If we donÕt have an AC842A,
|
|
Beq @DoReset ; then just go on.
|
|
|
|
Move.l DAFB_ClkCfg(A2),D0 ; Get the current clock configuration.
|
|
Bfextu D0{dafbPixSel1:1},D2 ; Get PIXSEL1 (PIXSEL1 -> ~acdcPCS).
|
|
Not.l D2 ; Invert it.
|
|
|
|
Clr.l ACDC_AddrReg(A2) ; Tell ACDC to use PCBR0.
|
|
Nop ; (DAFBÕs address space is non-serial.)
|
|
Move.l ACDC_ConfigReg(A2),-(Sp) ; Save PCBR0 for later.
|
|
Move.l #6,ACDC_ConfigReg(A2) ; Put ACDC into indirect mode.
|
|
Move.l #1,ACDC_AddrReg(A2) ; Tell ACDC to use PCBR1.
|
|
Nop ; (DAFBÕs address space is non-serial.)
|
|
Move.l ACDC_ConfigReg(A2),D0 ; Save the current configuration.
|
|
Bfins D2,D0{acdcPCS:1} ; Set up to select the right clock.
|
|
Move.l D0,ACDC_ConfigReg(A2) ; Write PCBR1 back out with correct clock set.
|
|
Nop ; (DAFBÕs address space is non-serial.)
|
|
Tst.l ACDC_AddrReg(A2) ; Read the addr reg to make it stick (AC842A).
|
|
Clr.l ACDC_AddrReg(A2) ; Tell ACDC to use PCBR0 again.
|
|
Move.l (Sp)+,ACDC_ConfigReg(A2) ; Restore PCBR0.
|
|
|
|
Tst.b wombatFlag(A3) ; If we have a WombatDAFB, then just
|
|
Bne.s @DoSwatchAdj ; go on (because we ONLY use the programmble clock).
|
|
|
|
Btst #0,D2 ; If PIXSEL1 was NOT zero,
|
|
Beq.s @DoSwatchAdj ; then just go on.
|
|
Move.l DAFB_ClkCfg(A2),D0 ; Get the current clock configuration.
|
|
Bfins D2,D0{dafbPixSel0:1} ; Set up PIXSEL0 so thatÉ
|
|
Move.l D0,DAFB_ClkCfg(A2) ; Éthe programmable clock is used.
|
|
|
|
@DoSwatchAdj
|
|
Tst.b wombatFlag(A3) ; If weÕre on a Wombat,
|
|
Bne.s @StrtAdj1 ; then just go on.
|
|
Move.l saveVidPtr(A3),A0 ; Pick up the vidParams pointer.
|
|
Cmp.b dvpBadDepth(A0),D1 ; If weÕre not switching to a ÒbadÓ depth,
|
|
Bne.s @StrtAdj1 ; then just go on.
|
|
DAFBWWrite dbpTimingAdjAMD,Swatch_TimeAdj ; Adjust TimingAdj.
|
|
Move.l Swatch_TimeAdj(A2),D0 ; Get the adjusted value.
|
|
Add.b dvpFudge(A0),D0 ; Adjust it some more.
|
|
Move.l D0,Swatch_TimeAdj(A2) ; Write it back out.
|
|
Bra.s @StrtAdj2 ; And go on.
|
|
|
|
@StrtAdj1 DAFBWWrite dbpTimingAdjAMD,Swatch_TimeAdj ; Adjust TimingAdj,
|
|
@StrtAdj2 DAFBWWrite dbpHALAMD,Swatch_HAL ; HAL,
|
|
DAFBWWrite dbpHFPAMD,Swatch_HFP ; HFP
|
|
|
|
Tst.b wombatFlag(A3) ; If weÕre not on a Wombat,
|
|
Beq.s @DoReset ; then just go on
|
|
|
|
Moveq #0,D0 ; Clear this reg.
|
|
Move.w dbpACDCPCBR(A1),D0 ; Pick up the PCBR value.
|
|
Bclr #7,D0 ; Strip off the IRE-value.
|
|
Lsr.w #5,D0 ; Keep just the VidClk bits.
|
|
Move.w D0,D2 ; And save them for later.
|
|
Lea DAFBWombatTimingAdjTbl,A0 ; Point to the Wombat TimingAdj table.
|
|
Mulu #DAFBWombatTSize,D0 ; Figure out the offset value.
|
|
Adda.w D0,A0 ; Point to the right entry.
|
|
Move.w (A0,D1*2),D0 ; Pick up the appropriate value.
|
|
Add.l D0,Swatch_TimeAdj(A2) ; Add it in.
|
|
|
|
Tst.b hasLin16BppCLUT(A3) ; If we donÕt have an Antelope,
|
|
Beq.s @EndSwatchAdj ; then just go on.
|
|
|
|
Lea DAFBAntelopeTbl,A0 ; Point to the table of Antelope adjustment values.
|
|
Move.w (A0,D2*2),D0 ; Get the appropriate adjustment value.
|
|
|
|
Add.l D0,Swatch_TimeAdj(A2) ; Adjust TimingAdj,
|
|
Add.l D0,Swatch_HAL(A2) ; HAL,
|
|
Add.l D0,Swatch_HFP(A2) ; HFP.
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If we arenÕt doing 16bpp, then
|
|
Bne.s @EndSwatchAdj ; just go on.
|
|
Cmp.w #indexedSensePAL,saveMonID(A3) ; If we arenÕt doing PAL FF/ST, then
|
|
Bne.s @EndSwatchAdj ; just go on.
|
|
Addi.l #1,Swatch_TimeAdj(A2) ; Otherwise, adjust TimingAdj again.
|
|
|
|
@EndSwatchAdj
|
|
|
|
; Sync On GreenÉ (Wombat only)
|
|
;
|
|
Move.l DAFB_ClkCfg(A2),D0 ; Get the current Clock config value.
|
|
Btst #syncOnGreen,GFlags(A3) ; If weÕre supposed to put sync on green,
|
|
Bne.s @EnableSyncOnGreen ; then hop to it.
|
|
Moveq #0,D1 ; Otherwise, set up for disabling.
|
|
Bra.s @SyncOnGreenCommon
|
|
|
|
@EnableSyncOnGreen
|
|
Moveq #1,D1 ; Set up for enabling.
|
|
|
|
@SyncOnGreenCommon
|
|
Bfins D1,D0{dafbSyncOnGreen:1} ; Toggle the sync-on-green bit appropriately,
|
|
Move.l D0,DAFB_ClkCfg(A2) ; apply it.
|
|
|
|
; Everything's configured, so do the DAFB reset sequence after waiting for vSync to happen.
|
|
;
|
|
@DoReset
|
|
Move.w Sr,-(Sp) ; Save the current interrupt level.
|
|
BSR DAFBWaitVSync ; Wait for the next VBL.
|
|
Move.w (Sp)+,Sr ; Restore the interrupt level.
|
|
DAFBReset ; Reset DAFB.
|
|
|
|
MOVE.B (SP)+,D0 ; get the previous addressing mode back
|
|
_SwapMMUMode ;
|
|
|
|
MOVEM.L (SP)+,D0-D2/A0-A2 ; restore all regs
|
|
RTS ; return
|
|
|
|
ENDWITH
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Fill the screen with a 50% dithered gray pattern. To have gotten here
|
|
; we must have had a valid display connected, so there are not tests
|
|
; for inactive displays here.
|
|
;
|
|
; D1 = spID of screen depth - FirstVidMode
|
|
; A3 = driver private storage
|
|
;
|
|
; All registers are preserved
|
|
;
|
|
|
|
With DAFBVidParams,DAFBBppParams,SC_Params
|
|
|
|
DAFBGrayScreen
|
|
|
|
MOVEM.L A0-A2/D0-D7,-(SP)
|
|
|
|
MOVE.L saveBaseAddr(A3),A2 ; Get the screen base address into A2.
|
|
Move.w D1,D7 ; Save the vidMode for later.
|
|
Move.b saveSlotId(A3),D3 ; Get the functional sRsrcID.
|
|
|
|
Btst #has16bppSRsrc,GFlags(A3) ; If we have a 16bpp sRsrc,
|
|
Bne.s @GetXPats ; then get the extended patterns.
|
|
Bra.s @NormPats ; Otherwise, just use the normal patterns.
|
|
|
|
@GetXPats Lea DAFBXPats,A0 ; Point to the table of patterns,
|
|
Move.l (A0,D1*4),D4 ; and load the right one.
|
|
|
|
Move.l D4,D5 ; Copy the pattern for the double-long stuff.
|
|
MOVEQ #IndexedBlack,D6 ; assume an indexed mode for now
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If this is not a direct mode,
|
|
Blt.s @StartGray ; just go on.
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If this is 16bpp mode, then
|
|
Beq.s @Skip32bpp ; the data fits into one long.
|
|
Not.l D5 ; Otherwise, invert this half for white.
|
|
|
|
@Skip32bpp Moveq #DirectBlack,D6 ; Set black as direct.
|
|
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCSTax,D3 ; If this is an NTSC ST (non-convolved) display,
|
|
Beq.s @StartGray ; then donÕt alter the baseAddr.
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCSTbx,D3 ;
|
|
Beq.s @StartGray ;
|
|
Cmp.b #sRsrc_Vid_DAFB_PALSTax,D3 ; If this is a PAL ST (non-convolved) display,
|
|
Beq.s @StartGray ; then donÕt alter the baseAddr.
|
|
Cmp.b #sRsrc_Vid_DAFB_PALSTbx,D3 ;
|
|
Beq.s @StartGray ;
|
|
|
|
@AdjBase Move.l saveScreenBase(A3),A2 ; Get the (offset, ugh!) screen base address,
|
|
Bra.s @StartGray ; and start graying.
|
|
|
|
@NormPats LEA DAFBPats,A0 ; point to the pattern table
|
|
MOVE.L (A0,D1*4),D4 ; get the graying pattern
|
|
|
|
MOVE.L D4,D5 ; copy it
|
|
MOVEQ #IndexedBlack,D6 ; assume an indexed mode for now
|
|
|
|
CMP.W #FifthVidMode-FirstVidMode,D1 ; is this Millions mode?
|
|
BNE.S @StartGray ; if so, use the special graying routine
|
|
|
|
NOT.L D5 ; invert this half to make white
|
|
MOVEQ #DirectBlack,D6 ; nope, get direct instead
|
|
|
|
@StartGray MOVE.L saveVidPtr(A3),A1 ; point to video parameters
|
|
Move.l A1,A0 ; Make a copy.
|
|
|
|
Btst #has16bppSRsrc,GFlags(A3) ; If we have a 16bpp-capable sRsrc list
|
|
Bne.s @IndexOK ; then just go on.
|
|
|
|
Cmp.w #FifthVidMode-FirstVidMode,D1 ; If weÕre not trying to do 32bpp,
|
|
Bne.s @IndexOK ; then just go on.
|
|
Addq #1,D1 ; Otherwise, skip the 16bpp params.
|
|
|
|
@IndexOK MULU #DBPSize+SC_Size,D1 ; index to the correct parameter group
|
|
LEA DVPHdrSize+DBPSize(A1,D1),A1 ; point to the screen graying parameters
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit mode
|
|
_SwapMMUMode ;
|
|
MOVE.B D0,D2 ; save previous addressing mode
|
|
|
|
; Do top of screenÉ
|
|
;
|
|
; Note that SC_BorderHeight is adjusted to work correctly for both bordered and non-bordered screens.
|
|
; Specifically, this constant is not Ò-1Ó-adjusted for Dbra, so we jump into the tail end of the Dbra
|
|
; loop and therefore have the ÒrightÓ thing happen. My head hurts now, and I hope yours does.
|
|
;
|
|
Cmp.w #indexedSenseRubik,saveMonID(A3) ; If weÕre on a Rubik display, then
|
|
Beq.s @FixRubik1bpp ; see if wee need to do fix.
|
|
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvST,D3 ; If weÕre on an NTSC convolved display,
|
|
Beq.s @FixNTSCPALTop ; then apply fix.
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvFF,D3
|
|
Beq.s @FixNTSCPALTop
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvSTx,D3
|
|
Beq.s @FixNTSCPALTop
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvFFx,D3
|
|
Beq.s @FixNTSCPALTop
|
|
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvST,D3 ; If weÕre on a PAL convolved display,
|
|
Beq.s @FixNTSCPALTop ; then apply fix.
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvFF,D3
|
|
Beq.s @FixNTSCPALTop
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvSTx,D3
|
|
Beq.s @FixNTSCPALTop
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvFFx,D3
|
|
Beq.s @FixNTSCPALTop
|
|
Bra.s @ScreenStart
|
|
|
|
@FixRubik1bpp
|
|
Move.w #DAFB_512_RB,D0 ; Fix first-line problem on Rubik displays.
|
|
Bra.s @FixRow ; (Only really need to this in 1bpp mode, but doesnÕt hurt others.)
|
|
|
|
@FixNTSCPALTop
|
|
Move.w #DAFB_1024_RB,D0 ; Create ÒfalseÓ first line on NTSC/PAL convolved displays.
|
|
|
|
@FixRow Suba D0,A2 ; Point back one full line.
|
|
Lsr.w #2,D0 ; Make loop counter long-word based.
|
|
Subq #1,D0 ; Subtract 1 for Dbra.
|
|
@BlastRow Move.l D6,(A2)+ ; Write black out.
|
|
Dbra D0,@BlastRow
|
|
|
|
@ScreenStart
|
|
Move.w SC_BorderHeight(A1),D1 ; get number of rows (not -1) to blast back on top
|
|
Bra.s @TopSecPrime ;
|
|
|
|
@TopSecFill_V
|
|
Move.w SC_BorderWidth(A1),D0 ; get number of longs (-1) to blast black in row
|
|
@TopSecFill_H
|
|
Move.l D6,(A2)+ ; blast black to screen
|
|
Dbra D0,@TopSecFill_H
|
|
|
|
Adda.w SC_SkipFactor(A1),A2 ; skip to start of next row
|
|
@TopSecPrime
|
|
Dbra D1,@TopSecFill_V
|
|
|
|
|
|
; Do middle of screenÉ
|
|
;
|
|
; Unlike the top part, there is always a Òmiddle.Ó However, there might be a left and right side (when the
|
|
; border is appropriate), so the not Ò-1Ó-adjusted for Dbra comments that are listed above apply horizontally
|
|
; here.
|
|
;
|
|
Move.w dvpNumRows(A0),D1 ; get number of rows (-1) in middle of screen
|
|
|
|
@MidSecFill_V
|
|
Move.w SC_BorderSide(A1),D0 ; get number of longs (not -1) to blast black in row
|
|
Bra.s @MidSecPrime_L
|
|
@MidSecFill_L
|
|
Move.l D6,(A2)+ ; blast black to screen
|
|
@MidSecPrime_L
|
|
Dbra D0,@MidSecFill_L
|
|
|
|
Move.w SC_ActiveWidth(A1),D0 ; get the number of doublelongs (-1) for active middle
|
|
@MidActFill_H
|
|
Move.l D4,(A2)+ ; Fill the active section with gray
|
|
Cmp.b #sRsrc_Vid_DAFB_SVGAa,D3 ; Skip if SuperVGA (800x600 is not an
|
|
Beq.s @ChkMode ; even multiple of 64, but it is an)
|
|
Cmp.b #sRsrc_Vid_DAFB_SVGAb,D3 ; even multiple of 32).
|
|
Beq.s @ChkMode ;
|
|
Cmp.b #sRsrc_Vid_DAFB_SVGAax,D3 ;
|
|
Beq.s @ChkMode ;
|
|
Cmp.b #sRsrc_Vid_DAFB_SVGAbx,D3 ;
|
|
Beq.s @ChkMode ;
|
|
Bra.s @DoDouble ;
|
|
@ChkMode Btst #has16bppSRsrc,GFlags(A3) ; If we have a 16bpp-capable sRsrc,
|
|
Bne.s @16bppSRsrc ; then go there.
|
|
Cmp.w #FifthVidMode-FirstVidMode,D7 ; If weÕre not doing 32bpp,
|
|
Bne.s @SkipDouble ; then really skip.
|
|
Bra.s @DoDouble ; Otherwise, do second half.
|
|
@16bppSRsrc Cmp.w #SixthVidMode-FirstVidMode,D7 ; If weÕre not doing 32bpp,
|
|
Bne.s @SkipDouble ; then really skip.
|
|
@DoDouble Move.l D5,(A2)+ ; Otherwise, do second half where applicable.
|
|
@SkipDouble Dbra D0,@MidActFill_H
|
|
|
|
Not.l D4 ; Invert for next line, and
|
|
Not.l D5 ; second half if applicable.
|
|
|
|
Move.w SC_BorderSide(A1),D0 ; get number of longs (not -1) to blast black in row
|
|
Bra.s @MidSecPrime_R
|
|
@MidSecFill_R
|
|
Move.l D6,(A2)+ ; blast black to screen
|
|
@MidSecPrime_R
|
|
Dbra D0,@MidSecFill_R
|
|
|
|
Add.w SC_SkipFactor(A1),A2 ; move to NEXT line
|
|
Dbra D1,@MidSecFill_V
|
|
|
|
; Do bottom of screenÉ
|
|
;
|
|
Move.w SC_BorderHeight(A1),D1 ; Get number of rows (not -1) to blast back on bottom.
|
|
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvST,D3 ; If weÕre on an NTSC convolved display,
|
|
Beq.s @FixNTSCPALBot ; then apply fix.
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvFF,D3
|
|
Beq.s @FixNTSCPALBot
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvSTx,D3
|
|
Beq.s @FixNTSCPALBot
|
|
Cmp.b #sRsrc_Vid_DAFB_NTSCconvFFx,D3
|
|
Beq.s @FixNTSCPALBot
|
|
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvST,D3 ; If weÕre on a PAL convolved display,
|
|
Beq.s @FixNTSCPALBot ; then apply fix.
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvFF,D3
|
|
Beq.s @FixNTSCPALBot ; then apply fix.
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvSTx,D3
|
|
Beq.s @FixNTSCPALBot
|
|
Cmp.b #sRsrc_Vid_DAFB_PALconvFFx,D3
|
|
Beq.s @FixNTSCPALBot
|
|
Bra.s @BotStart
|
|
|
|
@FixNTSCPALBot
|
|
Addq #1,D1 ; For convolved interlace displays, we need to
|
|
; blacken the ÒfalseÓ bottom.
|
|
@BotStart
|
|
Bra.s @BotSecPrime ;
|
|
@BotSecFill_V
|
|
Move.w SC_BorderWidth(A1),D0 ; get number of longs (-1) to blast black in row
|
|
@BotSecFill_H
|
|
Move.l D6,(A2)+ ; blast black to screen
|
|
Dbra D0,@BotSecFill_H
|
|
|
|
Adda.w SC_SkipFactor(A1),A2 ; skip to start of next row
|
|
@BotSecPrime
|
|
Dbra D1,@BotSecFill_V
|
|
|
|
MOVE.B D2,D0 ; get the previous addressing mode back
|
|
_SwapMMUMode ;
|
|
|
|
@GrayExit
|
|
MOVEM.L (SP)+,A0-A2/D0-D7 ; restore all regs
|
|
RTS ; and return
|
|
|
|
Endwith
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; DAFBDirectCLUTSet writes gamma-corrected ascending grayscale ramps into
|
|
; the CLUT
|
|
;
|
|
; A3 = dCtlStorage pointer
|
|
;
|
|
; Preserves all registers used.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
DAFBDirectCLUTSet
|
|
|
|
MOVEM.L D0-D3/D5/A0/A4-A6,-(SP) ; save registers
|
|
|
|
MOVE.L saveGammaPtr(A3),A0 ; get pointer to gamma data structure
|
|
MOVE.W gFormulaSize(A0),D0 ; get the size of formula data
|
|
LEA gFormulaData(A0),A4 ; point to formula data
|
|
ADD D0,A4 ; red correction table starts here
|
|
MOVE.L A4,A5 ; get default pointer to green data
|
|
MOVE.L A4,A6 ; get default pointer to blue data
|
|
|
|
CMP.W #1,gChanCnt(A0) ; if only only one table, we're set
|
|
BEQ.S @OneTbl ; => just one table
|
|
|
|
MOVE gDataWidth(A0),D1 ; get width of each entry in bits
|
|
ADDQ #7,D1 ; round to nearest byte
|
|
LSR #3,D1 ; get bytes per entry
|
|
MULU gDataCnt(A0),D1 ; get size of table in bytes
|
|
|
|
ADDA D1,A5 ; calc base of green
|
|
ADDA D1,A6 ; calc baseÉ
|
|
ADDA D1,A6 ; Éof blue
|
|
|
|
@OneTbl MOVE.W gDataCnt(A0),D2 ; Get number of entries.
|
|
Subq #1,D2 ; Make it zero based.
|
|
|
|
MOVEQ #true32b,D0 ; flip to 32-bit mode
|
|
_SwapMMUMode ;
|
|
|
|
MOVE.L saveVDACBase(A3),A0 ; point to the hardware
|
|
ADDA #ACDC_DataReg,A0 ; point to data register
|
|
CLR.L ACDC_AddrReg-ACDC_DataReg(A0) ; start at the beginning of CLUT
|
|
|
|
Move.w GFlags(A3),D5 ; Get the flags for quick access.
|
|
|
|
Btst #has16bppSRsrc,D5 ; If we have a 16bpp-capable sRsrc,
|
|
Bne.s @Chk16bpp ; then check for 16bpp.
|
|
Bra.s @Normbpp ; Otherwise, just do the normal stuff.
|
|
|
|
@Chk16bpp Move.w saveMode(A3),D1 ; Get the current mode.
|
|
Cmp.b #FifthVidMode,D1 ; If weÕre not doing 16bpp,
|
|
Bne.s @Normbpp ; then go on.
|
|
|
|
Bset #UseTrans,D5 ; Remember to do 5-to-8 bit translation stuff.
|
|
Move.w #$1F,D2 ; There are only 32 entries to whack in 16bpp mode.
|
|
|
|
@Normbpp MOVE.W SR,-(SP) ; preserve the status register
|
|
BSR DAFBWaitVSync ; wait for next blanking period (preserves A0/D0)
|
|
|
|
; Write an incrementing grayscale ramp.
|
|
|
|
Moveq #0,D3 ; Init ramp start.
|
|
Moveq #0,D1 ; Init trans index (will be used as a long).
|
|
|
|
@Repeat Move.w D3,D1 ; Get the current ramp/index value.
|
|
Btst #UseTrans,D5 ; If we donÕt need to translate this value,
|
|
Beq.s @Index ; then just go on.
|
|
Bsr DAFBTrans5to8 ; Otherwise, translate from 5-bits to 8.
|
|
Tst.b hasLin16BppCLUT(A3) ; If the CLUT/DAC itself doesnÕt need translating,
|
|
Bne.s @Index ; then just go on.
|
|
Move.l D1,ACDC_AddrReg-ACDC_DataReg(A0) ; Otherwise, use the 5-to-8 index for the Clut address.
|
|
|
|
@Index MOVE.B (A4,D1),3(A0) ; Write gamma-corrected red,
|
|
MOVE.B (A5,D1),3(A0) ; green, and
|
|
MOVE.B (A6,D1),3(A0) ; blue.
|
|
ADDQ #1,D3 ; increment ramp/index value
|
|
DBRA D2,@Repeat ;
|
|
|
|
MOVE.W (SP)+,SR ; restore the status reg
|
|
_SwapMMUMode ;
|
|
|
|
MOVEM.L (SP)+,D0-D3/D5/A0/A4-A6 ; restore saved registers
|
|
RTS
|
|
|
|
;-------------------------------------------------------------
|
|
; The Interrupt handler for the DAFB Built-In Video
|
|
;-------------------------------------------------------------
|
|
; On entry A1 contains the pointer to the driver's private storage
|
|
|
|
DAFBBeginIH
|
|
|
|
Move.l A0,-(Sp) ; Save A0/D1 due to direct jump to SwapMMUMode.
|
|
Move.l D1,-(Sp) ; (Two Moves are faster than a Movem.)
|
|
|
|
Moveq #true32b,D0 ; Set up to swap into 32-bit mode.
|
|
Jsr ([jSwapMMU]) ; Do fast swap.
|
|
Move.b D0,-(Sp) ; Save the previous addressing mode.
|
|
|
|
Move.l saveDAFBBase(A1),A0 ; Point to the DAFB baseAddr.
|
|
@WaitForClr Clr.l Swatch_ClrCrsrInt(A0) ; Clear this interrupt.
|
|
Move.l Swatch_IntStat(A0),D0 ; Get its status.
|
|
Btst #dafbIntStatusBit,D0 ; If itÕs not cleared yet,
|
|
Bne.s @WaitForClr ; then just spin.
|
|
|
|
Move.b (Sp)+,D0 ; Set up to swap back into previous addressing mode.
|
|
Jsr ([jSwapMMU]) ; Do fast swap.
|
|
|
|
Moveq #0,D0 ; Set up for Slot $0É
|
|
Jsr ([jVBLTask]) ; Éand call the VBL Task Manager.
|
|
|
|
Moveq #1,D0 ; Signal that the interrupt was serviced
|
|
Move.l (Sp)+,D1 ; Restore A0/D1 registers.
|
|
Move.l (Sp)+,A0 ; (Two Moves are faster than a Movem.)
|
|
Rts ; Return to caller.
|
|
|
|
|
|
END
|