boot3/DeclData/DeclVideo/Civic/CivicDriver.a

5165 lines
204 KiB
Plaintext
Raw Normal View History

;
; File: CivicDriver.a
;
; Contains: This file contains the video driver for use by the Macintosh
; OS for the Civic hardware.
;
; Written by: Mike Puckett/Fernando Urbina, March 2, 1992.
;
; Copyright: <09> 1992-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM18> 8/12/93 BG Changed various Cyclone-related boxflags to their official
; names.
; <SM17> 08-03-93 jmp Changed the reference names of the multiscan display constants
; to their new names.
; <16> 7/2/93 IH #1096920: Slot Manager not correctly updated in set resolution
; call.
; <SM15> 6/14/93 kc Roll in Ludwig.
; <LW19> 6/9/93 fau Fixed two bugs (not in radar): When aborting SetRGBBypass from
; composite to RGB, I was switching the MMC_Bypass bit and not
; restoring it if we aborted. I now don't switch it until after
; we know the switch happenned. This will drive bad timing into
; the composite display for a little bit. Also, in the dynamic
; switch, I was not checking whether the new spID supported
; video-in in 16bpp. If it didn't and the current VidInMode was
; in that depth, we would crash. Now, after checking that the
; current graphics mode is supported, we check that the new spID
; supports 16bpp and if not, if the current vidinmode is 16bpp we
; bail out, returning an 8 as a word in the parameters.
; <LW18> 6/4/93 fau Fixed bug #1089549: Cyclone allos switch to RGB Monitor when
; booted on TV. I was not updating my NTSCTimingON and my
; ConvolutionON flags when first opening the driver.
; <LW17> 5/14/93 fau Fixed bugs: #1083318, #PUMA, #1084366: Problem with VideoReset,
; saveVidInMode.
; <LW16> 5/3/93 fau Fixed a problem in SetDepth (again?) where I was using D1 and
; then calling dWrite_Civic, which uses D1. This was causing D1
; to enable VDC interrupts when they shouldn't have.
; <LW15> 5/1/93 mal Actually (fau): Reverted change in SetVidInModeGuts where I was
; getting #BusSize off the video parameters, but in some cases,
; it's not right. Force it to 0 as it was in <LW13>.
; <LW14> 4/30/93 fau Two Bug Fixes: In video-in grayscale, I was setting the
; big-small bit when the size was > 512. It should never be set
; for grayscale. Also, it shouldn't have been 512 wide for
; changing that bit, it is 496. Also, removed Wait2000ms, which
; is not used. Finally, added a table to translate the multisync
; spID to a monID so that I can determine the video-in sizes that
; are supported by the current spID. That algorithm was monID
; based, so I translate the spID when it's a multisync display.
; <SM14> 4/29/93 fau Synchronized with Ludwig.
; <LW13> 4/14/93 fau Fixed a bug in GetCompCapabilities where I was still looking at
; the 2MegVRAM byte, that doesn't exist anymore.
; <LW12> 4/14/93 fau Changes to fix the video-flashing bugs; re-architected the way
; video-in works in Civic. Now it's always enabled, except when
; you go to a mode that doesn't support it; LOTS of changes due
; to that, in any calls that do video-in. Disabled overlay while
; graying screen. Added support for the new Display Manager.
; <SM13> 4/6/93 fau Another synchro with Ludwig.
; <LW11> 4/5/93 fau Approved by Change Control Board: Moved the video-in calls to
; be in the private area, instead of the public area. They should
; not really be public. Added a Set/GetSync call to support the
; "green" monitors.
; <SM12> 4/5/93 chp Synchronize with Ludwig.
; <LW10> 4/4/93 fau Fixed bug #1074831: Boundary check SetEntries for
; csStart+csCount > ccRange.
; Fixed bug #1056748: GetVidInMode not returning correct
; csBaseAddr: Problem with using the wrong record for the call.
; Fixed bug #1074829: GetVideoIn reports inverted PRAM bit. I
; wasn't inverting the value of what I read from PRAM!
; Fixed bug #1074815: SetRGBBypass does not return -17. True, I
; was returning a good error code when the routine couldn't do
; it!
; Fixed bug #1074849: In SetRGBBypass, when switching back from
; compostie to a mono only device, I was overwriting the gFlags
; where i had set the isMono and Gray bits.
; <LW9> 3/24/93 fau Added a SetVideoCLUT routine to write the current gamma table to
; the video-in CLUT. It is called by SetGamma, as well as by
; SetVideoInMode.
; <LW8> 2/17/93 fau Fixed a trashing of D1 (saved D0 and restored D1) in the VBL
; handler routine.
; <LW7> 2/17/93 fau Reversed the bits in the GetVideoIn call to reflect the original
; intent: Bit 0 says whether video-in is enabled or not. Bit 1
; whether the PRAM bit is set or not.
; <LW6> 2/16/93 fau Fixed lots of bugs: Allow color video-in when in a FullPage
; monitor. Added a new status call GetCompOutCapab to give us
; details about the equivalend video-out spid's for different
; monitors. Added support for Clifton so that we can switch to
; video-out. Changed the bits in GetVideoIn so that it matches
; SetVideoIn. Revamped the RGBBypass call.
; <LW5> 1/28/93 KW (SM11 kc) Rename equate (alpha to xalpha) to avoid name
; collision. (We should use records instead of an equates to avoid
; the problem).
; <SM11> 1/25/93 kc Rename equate (alpha to xalpha) to avoid name collision. (We
; should use records instead of an equates to avoid the problem).
; <LW4> 1/8/93 FU Removed the debugstrings for the A9 build and changed the
; polarity of the check for the VDC interrupt, per new information
; telling us that it is active low.
; <LW3> 1/4/93 fau Lots of cleanup: Removed support for 24-bit MMU support.
; Changed MMC to YMCA references. Moved the VidInPrivates to the
; regular privates. Initialized SetVidInMode to 8bpp in VidOpen.
; Made the dispatch of private selectors be jump-table based.
; Revamped Set/GetVideoIn to fully support dynamic switching and
; non-dynamic switching.
; <LW2> 12/18/92 fau Fixed a bug where I was checking for a nil vidinrect: I was not
; doing correctly (using D0 for 2 sides and D2 for the other
; ones!).
; <SM10> 12/8/92 fau In the DynamicSwitch routine, fixed two bugs, where I was not
; updating the GFlags to indicate that video-in was/wasn't enabled
; and whether the mode was isDirect or not. This fixed a problem
; with the CLUT not being updated when switching dynamically from
; Thousands to 256.
; <SM9> 11/10/92 fau Fixed a bug in ChkMode where we were not generating the right
; offset for the 1/2Meg VRAM check: (a0,d0),d0 is really a word
; offset of a0; the code assumed a byte offset.
; <SM8> 11/6/92 fau Added code to the VBL/VDC interrupt handler to take care of any
; spurious VDC interrupts (VDC interrupts occuring when it is not
; enabled). Also, added a temporary Debugger string in the
; handler for when it gets called an no VBL's or VDC's are
; hapenning.
; <SM7> 11/2/92 kc Don't include SonicEqu.a.
; <SM6> 10/30/92 fau Move the vidinrect in the previous checkin to 2 clocks after
; HFP/VFP
; <SM5> 10/29/92 fau Added support for booting off composite by setting a PRAM bit.
; (A new control/status call). Made sure the vidin rect is out in
; right field when the private's savevidin... are all zero.
; <SM4> 10/28/92 SWC Changed VideoEqu.a->Video.a and ShutdownEqu.a->Shutdown.a.
; <SM3> 10/22/92 fau Changed MMCAddr to DecoderAddr.
; <SM2> 10/8/92 fau Fixed bug in GetGamma where I was moving a byte instead of a
; long into the address increment register for the main loop.
; <1> 10/6/92 GDW New location for ROMLink tool.
; <SM10> 9/30/92 fau Changed the use of VDACAddr to SebastianAddr.
; <SM9> 8/27/92 fau Got rid of support for early Civic Rev's. Added a private call
; at $85 to reprogram Civic with new parameters (this is
; temporary).
; <SM8> 7/28/92 fau Fixed a problem in SetRGBBypass where the interrupt level was
; not being saved/restored before calling CivicWaitForVSync.
; Moved the enable of Casio in that routine to a more proper
; place.
; <SM7> 6/30/92 fau Fixed the setting of the NTSCTimingON flag in SetRGBBypass, and
; the return of that flag in GetRGBBypass.
; <SM6> 6/26/92 fau Fixed the problem that existed when changing monitor depths and
; displaying video-in (the video-in parameters would get trashed).
; Same deal with switching to composite out.
; <SM5> 6/19/92 KW (fau,P13) Lots of stuff. In the interrupt handler routine, I'm
; now checking Civic's VBL_INT register, instead of the VDC_INT.
; Disabled overlay in SetVidMode. Added the Set/GetRGBBypass
; routines. Compacted the new cs codes, getting rid of the ones
; we decided to get rid off. Installed the VBL with a priority of
; 255, instead of 0. Got rid of the baseaddress in the VidParams,
; so now I get it from the s-resource. Check for Civic II and new
; oscillators. Added padding and a couple new parameters to
; CivicVidPrivates. Whew...
; <SM4> 6/18/92 KW (fau, P12) Fixed bug in determining whether to program Civic to
; use a big/small video-in size. (Moved a byte instead of a
; word). Also, added this size check to video-in 8bpp (before I
; only checked on 16bpp). Finally, changed the video-in monitor
; support table to check whether a VGA family mode is SxVGA which
; will not support 16bpp video-in, whereas the other VGA modes do.
; <SM3> 6/4/92 KW (jmp,P11) Slightly optimized & improved the soon-to-obsolete
; Civic vs. Civic2 checking code.
; (fau,P10) Added a new dCivicIIRegTable that has the extra bit
; defined for Rowwords and also the DoubleLine register (1 bit)
; tacked at the end of the table. Modified dGetCivicReg in a
; brute force manner to check which Civic it's running on and load
; the appropriate table.
; (fau,P9) Added a WaitforVBL and extended the reset pulse to
; Civic after changing horizontal display parameters. This was
; needed to make sure Civic was programmed correctly when using
; slow displays (i.e. NTSC).
; (fau,P8) Fixed bug in CivicDirectCLUTSet where D5 wasn't cleared
; before Bset'ing #useTrans.
; (fau,P7) Added alpha channel support for Set/GetEntries and
; SetVidMode, so the alpha channel is not blown away if video-in
; is enabled.
; <SM2> 5/29/92 kc Fix Assembler warnings.
; <P6> 5/1/92 fau Something went wrong in the database for <P5>, so I'm checking
; it in again to fix it.
; <P5> 5/1/92 fau Fixed Bug in SetVidInRect where I was blowing away saveBaseAddr.
; <P4> 5/1/92 fau Lots of stuff for Video-in support: Added CivicVidInPrivates
; table. Added stubs for all the new status calls. Added the
; SetVidInMode, SetVidInRect and SetFieldInterrupt control calls
; and stubs for the others. Added a temporary handling of the
; Field interrupt to CivicBeginIH.
; <P3> 04/13/92 jmp Optimized the SetDepth routine slightly, revised some comments,
; and changed GrayScreen to reflect the current vidParams data.
; <P2> 03/24/92 jmp Optimized the Interrupt Handler and the WaitVSync routines,
; re-ordered the way various parameters get changed in the
; SetDepth code, and fixed a bug where I was not returning the
; correct base address in various Control/Status calls.
; <1> 03/04/92 jmp first checked in
STRING C
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'ROMEqu.a'
INCLUDE 'Video.a'
INCLUDE 'SlotMgrEqu.a'
INCLUDE 'UniversalEqu.a'
INCLUDE 'DepVideoEqu.a' ; <LW14>
PRINT ON ; <LW14>
SEG '_sCivicDriver'
BLANKS ON
STRING ASIS
MACHINE MC68020
; This is device storage which is stored in the dCtlStorage field of the AuxDCE.
CivicVidPrivates RECORD 0
saveBaseAddr DS.L 1 ; the screen base address
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
saveVidPtr Ds.L 1 ; the pointer to the vidParams block
saveVDACBase DS.L 1 ; the base addr of the VDAC
saveCivicBase DS.L 1 ; the base addr of Civic
gFlags DS.W 1 ; flags word (hi-order byte, actually)
scratch Ds.l 1 ; scratch register
saveMode DS.W 1 ; the current mode setting
saveVidInMode DS.W 1 ; the current video-in mode (8 or 16 bpp)
saveMonID DS.W 1 ; monitor type ID
saveSlotId DS.B 1 ; spID of video sRsrc
saveRGBSlotId DS.B 1 ; The screen base address of the 2nd Vid Ptr
saveSizeVRAM DS.B 1 ; amount of vRAM (0=1Meg,1=2Meg)
saveBoxFlag DS.B 1 ; The box flag for the machine we're running on
saveYMCABaseAddr DS.L 1 ; The MMC Base adress
save2ndVidPtr DS.L 1 ; A second vidParams ptr to toggle between RGB / Comp sync
saveVidInSize DS.W 1 ; VidInSize (1 for > 496 pixels in 16bpp <LW14>
saveVinVAL DS.W 1 ; VinVAL for the Video In VRAM
saveVinVFP DS.W 1 ; VinVFP for the Video In VRAM
saveVinHAL DS.W 1 ; VinHAL for the Video In VRAM
saveVinHFP DS.W 1 ; VinHFP for the Video In VRAM
saveVinHFPD DS.W 1 ; VinHFPD for the Video In VRAM
currentTop DS.W 1 ; Top of the current VidInRect
currentLeft DS.W 1 ; Left of the current VidInRect
currentBottom DS.W 1 ; Bottom of the current VidInRect
currentRight DS.W 1 ; Right of the currentVidInRect
saveNewBaseMode Ds.w 1 ; Mode at which the base address changes from a 0 offset to a non-zero offset
saveBaseAddrOffset Ds.l 1 ; The offset to add to the base address when the mode is saveNewBaseMode or higher
VDCCLkState Ds.w 1 ; State of the VDC clock before disabling video-in
VDCEnbState Ds.w 1 ; State of the VDC Interrupt enable bit before disabling video-in
OverlayState Ds.w 1 ; State of the Overlay bit in Sebastian before disabling video-in
CivicVidPrivSize EQU *
ENDR
CivicFrame Record {A6Link},Decrement
Return DS.L 1 ; Return address.
A6Link DS.L 1 ; Saved A6.
spBlk DS SPBlock ; SpBlock for generic use.
sPRAMBlk DS.B SizeSPRAMRec ; sPRAMRec for generic use.
civicBaseAddr DS.L 1 ; Pointer to Civic<69>s base address.
mmcBaseAddr DS.L 1 ; Pointer to MMC<4D>s base address.
vRAMBaseAddr DS.L 1 ; Pointer to base of vRAM.
vidParamsPtr DS.L 1 ; Pointer to video parameters.
configParamsPtr DS.L 1 ; Pointer to config parameters.
savedMMUMode DS.B 1 ; All Civic regs must be 32-bit addressed.
spFlags DS.B 1 ; Local copy of slot pRAM flags byte.
CFSize Equ *
Endr
LCivicDriver MAIN EXPORT
;-------------------------------------------------------------------
; Video Driver Header
;-------------------------------------------------------------------
;
CivicVidDrvr
DC.W $4C00 ; ctl,status,needsLock
DC.W 0,0,0 ; not an ornament
; Entry point offset table
DC.W CivicVidOpen-CivicVidDrvr ; open routine
DC.W CivicVidDrvr-CivicVidDrvr ; no prime in normal video drivers
DC.W CivicVidCtl-CivicVidDrvr ; control
DC.W CivicVidStatus-CivicVidDrvr ; status
DC.W CivicVidClose-CivicVidDrvr ; close
STRING Pascal
CivicVidTitle
DC.B '.Display_Video_Apple_Civic'
ALIGN 2 ; make sure we're aligned
DC.W CurCivicDrvrVersion ; current version
STRING ASIS
;
; CivicCLUTTbl contains information required to write to the CLUT in the different screen depths.
; Each depth's information has three values. The first is the number of entries-1 in this depth
; for range checking. The second is the address of the first active CLUT position for that
; screen depth. The last number is the <20>skip<69> factor. This is required because, in 1-4bpp, the
; entries are distributed throughout the CLUT address space. As a result, we use sequential CLUT mode
; ONLY in 8/16bpp modes. The skip factor is the address difference between adjacent active positions
; in each mode.
;
; Generally, these rules are true for any particular depth:
; #entries = (2^^depth)-1
; startposition = (256 / (2^^depth))-1
; skipfactor = 256 / (2^^depth)
CivicCLUTTbl
DC.B $01,$7F,$00,$80 ; for one-bit mode
DC.B $03,$3F,$00,$40 ; for two-bit mode
DC.B $0F,$0F,$00,$10 ; for four-bit mode
DC.B $FF,$00,$00,$01 ; for eight-bit mode
DC.B $1F,$00,$00,$01 ; for sixteen-bit mode
DC.B $FF,$00,$00,$01 ; for thirty-two-bit mode
CivicCLUTRec RECORD 0 ;
ccRange DS.B 1 ; maximum index value in this depth
ccStart DS.B 1 ; lowest active CLUT address
ccSkip DS.W 1 ; skip value between active addresses
CivicCLUTSize Equ *
ENDR
;
; These are the bit patterns for grays in each depth
;
CivicPats Dc.l OneBitGray,TwoBitGray,FourBitGray,EightBitGray
Dc.l SixteenBitGray,ThirtyTwoBitGray
;
; Normally, if a type-6 is detected on boot, PrimaryInit just sets up for a Hi-Res. However,
; if the alternate-sense pRam code is valid, then we set things up as if the monitor code
; specified in pRam were actually connected. The CivicMonIDs table (below) is composed
; of the valid monitor IDs supported by Civic.
;
CivicMonIDs Dc.w CMonIDsEnd-CMonIDsBegin-1-1 ; -1 for assember warning pad
CMonIDsBegin
Dc.b indexedSenseRGB2P,indexedSenseFP,indexedSenseRubik,indexedSense2P
Dc.b indexedSenseNTSC,indexedSenseRGBFP,indexedSenseHR
Dc.b extendedSensePALBox,extendedSenseNTSC,extendedSenseVGA
Dc.b extendedSenseGF,extendedSensePAL,extendedSense19
DS.B 1 ; assember warning pad
CMonIDsEnd
Align 4
; Civic has a 1-bit wide interface, but many of its registers logically consist of up to 12-bits.
; The following table is the instantiation of the CivicRecord defined in DepVideoEqu.a. Each entry
; consists of two fields. The first field is the offset (from the Civic base address) to
; the least significant bit (long-word aligned) of a particular Civic register. The second
; field is the logical size of the Civic register. This table is used by the GetCivicRegister
; routine defined above. Eventually, this table should probably be moved into a Slot Resource
; for better updating between the PrimaryInit and driver code that must use it.
;
dCivicRegTable
Dc.w $000,01,$004,01,$008,01,$00C,01,$010,01,$014,01,$018,01,$01C,01,$020,03
Dc.w $02C,01,$040,01,$044,02,$04C,01,$050,01,$054,01,$058,01,$05C,01,$060,01
Dc.w $064,01,$068,01,$06C,01,$080,03,$08C,08,$0C0,09,$100,01,$104,01,$108,01
Dc.w $10C,01,$110,01,$114,01,$118,01,$11C,01,$120,01,$124,01,$128,01,$12C,01
Dc.w $140,12,$180,12,$1C0,12,$200,02,$240,12,$280,12,$2C0,08,$300,12,$340,12
Dc.w $380,12,$3C0,12,$400,12,$440,10,$480,12,$4C0,12,$500,12,$540,12,$580,12
Dc.w $5C0,12,$600,12,$640,12,$680,12,$6C0,12,$208,1
Align 4
; This is the Video-In maximum rectangle capabilities for 1Meg and 2Meg VRAM configurations
CVidInBPPRec RECORD 0
cVidInMaxH DS.W 1 ; Maximum Horizontal Value
cVidInMaxV DS.W 1 ; Maximum Vertical Value
CVidInBPPRecSize EQU *
ENDR
With CVidInBPPRec
CVidInVRAMRec RECORD 0
c8bppMax DS.B CVidInBPPRecSize ; MaxH/MaxV for 8bpp
c16bppMax DS.B CVidInBPPRecSize ; MaxH/MaxV for 16bpp
CVidInVRAMRecSize EQU *
ENDR
EndWith
With CVidInVRAMRec
CivicVidInRec RECORD 0
cVidIn1MegVRAM DS.b CVidInVRAMRecSize ; The MaxH/MaxV for 8pbb and 16pbb for a 1 Meg VRAM
cVidIn2MegVRAM DS.b CVidInVRAMRecSize ; The MaxH/MaxV for 8pbb and 16pbb for a 2 Megs VRAM
CivicVidInRecSize EQU *
ENDR
EndWith
Align 4
; The CivicVidInTable is an array of parameters indexed by display type. Each display type has
; 2 sets of parameters: One set for a 1 Meg VRAM configuration, and the other for a 2 Meg VRAM
; configuration. The parameters in each set consist of the maximum allowable width and height
; for 8bpp and 16 bpp. There are two special cases:
;
; 1. If the Maxh/MaxV values are both 0, that bpp depth is not supported on that monitor.
; 2. If the MaxH/MaxV values are both -1, that bpp depth is supported, but not at full PAL size.
; The SetVidInRect will need to calculate the maximum V, given an H. The size is limited by the
; amount of VRAM that is installed.
;
; This table assumes that the maximum video in window to be displayed is FF PAL: 768,576
With CivicVidInRec
CivicVidInTable
; 8bpp 16bpp
CVidInVesuvioTbl Dc.w 768,576, 0,0
Dc.w 768,576, 0,0
CVidInFullPageTbl Dc.w 640,576, -1,-1
Dc.w 640,576, 640,576
CVidInRubikTbl Dc.w 512,384, 512,384
Dc.w 512,384, 512,384
CVidInKongTbl Dc.w 768,576, 0,0
Dc.w 768,576, 0,0
CVidInNTSCTbl Dc.w 640,480, -1,-1
Dc.w 640,480, 640,480
CVidInRGBFullPageTbl Dc.w 640,576, -1,-1
Dc.w 640,576, 640,576
CVidInHiResTbl Dc.w 640,480, -1,-1
Dc.w 640,480, 640,480
CVidInNoConnectTbl Dc.w 0,0, 0,0
Dc.w 0,0, 0,0
CVidInVGATbl Dc.w 768,576, -1,-1 ; Might get clipped if in VGA (640x400) mode.
Dc.w 768,576, 768,576 ; Might get clipped if in VGA (640x400) mode.
CVidInPALTbl Dc.w 768,576, -1,-1
Dc.w 768,576, 768,576
CVidInGoldFishTbl Dc.w 768,576, -1,-1
Dc.w 768,576, 768,576
CVidIn19Tbl Dc.w 768,576, 0,0
Dc.w 768,576, 0,0
EndWith
; The following table is used by the SwitchMode call to determine two things. First,
; it must decide whether the requested mode to switch to is valid or not. If
; the requested mode is not in the SwitchTable, the call will fail. Also, even
; if the requested mode is in table, if the current bit depth is too large
; for the requested mode, SwitchMode must still fail.
;
SwitchTable1Meg
Dc.b sRsrc_Vid_Civic_viHRa,FifthVidMode ; Hi-Res (1 Meg)
Dc.b sRsrc_Vid_Civic_viHRNTSCST,SixthVidMode ; Hi-Res 512x384 (1-2 Meg)
Dc.b sRsrc_Vid_Civic_viHR400, SixthVidMode ; Hi-Res 640x400 (1-2 Meg)
Dc.b sRsrc_Vid_Civic_viGFPALFFa, FifthVidMode ; GoldFish 768x576 (1 Meg)
Dc.b sRsrc_Vid_Civic_viSVGA72a, FifthVidMode ; SuperVGA 800x600 (1 Meg)
Dc.b sRsrc_Vid_Civic_viGFa, FifthVidMode ; GoldFish (1 Meg)
Dc.b sRsrc_Vid_Civic_vi19a, FourthVidMode ; 19" (1024x768) (1 Meg)
Dc.b sRsrc_Vid_Civic_vi2PRGBa, FourthVidMode ; Vesuvio (1 Meg)
Dc.b 0,0
SwitchTable2Meg
Dc.b sRsrc_Vid_Civic_viHRb,SixthVidMode ; Hi-Res (2 Meg)
Dc.b sRsrc_Vid_Civic_viHRNTSCST,SixthVidMode ; Hi-Res 512x384 (1-2 Meg)
Dc.b sRsrc_Vid_Civic_viHR400, SixthVidMode ; Hi-Res 640x400 (1-2 Meg)
Dc.b sRsrc_Vid_Civic_viGFPALFFb, SixthVidMode ; GoldFish 768x576 (2 Meg)
Dc.b sRsrc_Vid_Civic_viSVGA72b, SixthVidMode ; SuperVGA 800x600 (2 Meg)
Dc.b sRsrc_Vid_Civic_viGFb, SixthVidMode ; GoldFish (2 Meg)
Dc.b sRsrc_Vid_Civic_vi19b, FifthVidMode ; 19" (1024x768) (2 Meg)
Dc.b sRsrc_Vid_Civic_vi2PRGBb, FifthVidMode ; Vesuvio (2 Meg)
Dc.b 0,0
; The following table returns what the indexedSese is for a particular spID that is in the <LW14>
; Multisync familymode. <LW14>
; <LW14>
EquivalendMonIDTable ; <LW14>
Dc.b sRsrc_Vid_Civic_viHRa,indexedSenseHR ; Hi-Res (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viHRb,indexedSenseHR ; Hi-Res (2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viHRNTSCST,indexedSenseHR ; Hi-Res 512x384 (1-2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viHR400, indexedSenseHR ; Hi-Res 640x400 (1-2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viGFPALFFb, indexedSenseGF ; GoldFish 768x576 (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viSVGA72b, indexedSenseVGA ; SuperVGA 800x600 (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viGFa, indexedSenseGF ; GoldFish (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_vi19a, indexedSense19 ; 19" (1024x768) (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_vi2PRGBa, indexedSenseRGB2P ; Vesuvio (1 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viGFPALFFb, indexedSenseGF ; GoldFish 768x576 (2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viSVGA72b, indexedSenseVGA ; SuperVGA 800x600 (2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_viGFb, indexedSenseGF ; GoldFish (2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_vi19b, indexedSense19 ; 19" (1024x768) (2 Meg) <LW14>
Dc.b sRsrc_Vid_Civic_vi2PRGBb, indexedSenseRGB2P ; Vesuvio (2 Meg) <LW14>
Dc.b 0,0 ; <LW14>
Align 4
**********************************************************************
*
* VidOpen allocates private storage for the device in the AuxDCE and locks
* it down for perpetuity. Also, it installs the interrupt handler and enables
* the (VBL) interrupts.
*
* Entry: A0 = param block pointer
* A1 = AuxDCE pointer
*
* Locals: A3 = pointer to private storage
*
* D0/D2 used as scratch
*
**********************************************************************
WITH VDPageInfo,SlotIntQElement,CivicVidPrivates
CivicVidOpen
;
; Allocate private storage (since block is CLEAR, GFlags are zeroed) and get
; a pointer to it in A3.
;
Move.l a4,-(Sp) ; save our scratch register
MOVEQ #CivicVidPrivSize,D0 ; get size of parameters
_ResrvMem ,SYS ; make room as low as possible
MOVEQ #CivicVidPrivSize,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),A3 ; get pointer to privates in A3
;
; Remember the VDAC, Civic, and framebuffer base addresses since they're non-trivial to
; look up.
;
WITH ProductInfo,DecoderInfo,VideoInfo
MOVE.L UnivInfoPtr,A0 ; get a pointer to universal data
Move.b ProductKind(A0),saveBoxFlag(A3) ; Save this machine's boxflag
ADDA.L DecoderInfoPtr(A0),A0 ; point to the base address table
MOVE.L SebastianAddr(A0),saveVDACBase(A3) ; save VDAC<41>s base address
Move.l CivicAddr(A0),saveCivicBase(A3) ; save Civic<69>s base address
Move.l DecoderAddr(A0),saveYMCABaseAddr(A3) ; Save YMCA<43>s base address.
MOVE.L UnivInfoPtr,A0 ; get a pointer to universl data
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 the 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.
BSR CivicEnableVGuts ; do it
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 #drHwCivic,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.
;
@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.B dCtlSlotId(A1),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
_sFindDevBase ; Get the base address for this spID
Move.l spResult(A0),D0 ; and save it in.
Move.l D0,saveBaseAddr(A3) ; our privates. This is the base of active video.
; Now, look for the mode at which the vpBaseOffset changes from non-zero to 0, and save it in our privates.
WITH VPBlock
Move.w #SixthVidMode,D1 ; Start at 32bpp
@LookForOffset
Move.b dCtlSlot(A1),spSlot(A0) ; Look at this slot
Clr.b spExtDev(A0) ; and no ExtDev
Move.b dCtlSlotID(A1),spID(A0) ; Put spID into spBlock.
_SRsrcInfo
Bne @OpError4 ; If failed, quit.
Move.b D1,spID(A0) ; Look for this mode
_SFindStruct
Beq.s @ModeExists ; If noErr, then get block
Cmp.w #-330,D0 ; Did we get a smBadRefID
Bne @OpError4 ; No, then quit.
Subi.w #1,D1 ; Look for next lower mode
bra.s @LookForOffset ;
@ModeExists
Move.b #mVidParams,spID(A0) ; Look for the video-parameters block
_SGetBlock
Bne @OpError4 ; If failed, quit.
Move.l spResult(A0),a4 ; save the pointer to the block
Move.L vpBaseOffset(A4),d0 ; Get Offset
Beq.s @GotOffset ; If zero, then we have our offset stored in privates
Move.l d0,saveBaseAddrOffset(A3) ; Store non-zero offset in our privates
DBRA d1,@LookForOffset ; look at next lower mode
@GotOffset
Addi.w #1,d1 ; Adjust mode that has the non-zero offset
move.w d1, saveNewBaseMode(A3) ; and save it in our privates
ENDWITH
;
; At PrimaryInit time, we used the sense lines to determine the type of display attached. 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 <20>real<61>
; 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 @OpError5 ; If failed quit.
Moveq #0,D2 ; Clear D2.w.
Move.b SP_MonID(Sp),D2 ; Get the monID (it<69>s byte sized).
Move.b SP_Flags(Sp),D1 ; Get the flags byte so we can use it later <LW18>
Adda #sizeSPRamRec+spBlockSize,Sp ; Clean up the stack.
EndWith
;
; Say whether video-in is enabled by reading the bus_size register
Move.l saveCivicBase(A3),A0 ; Get Civic's base address
Move.l Civic_BusSize(A0),D0 ; Read the bus size bit
Btst #0,D0 ; (0 = video-in enabled, 1 = video-in disabled)
Bne.s @TestForComposite ; if 1, then leave bit in GFlags off
Bset #videoInEnb,GFlags(A3) ; Say we have video-in enabled
@TestForComposite
; Check to see if we're driving composite out
With CivicRecord,CivicVidParams ; <LW18>
; <LW18>
Move.l Civic_SyncClr(A0),D0 ; Initially If SyncClr == 1, then DB15, else Composite (reads inverted)
Btst #0,D0 ; Bit 0 has the actual data
bne.s @Bookkeeping ; carry on
Move.w gFlags(a3),d0 ; Get the flags _word_
Bset #CompositeSyncOn,d0 ; Say we are driving composite
Move.l saveVidPtr(A3),a0 ; Take a look at our privates <LW18>
Tst.b cvpConvEnb(A0) ; Get our convolution flag <LW18>
Beq.s @NoConvolution ; we are not driving convolution <LW18>
Bset #ConvolutionOn,d0 ; say we are indeed driving convolution <LW18>
@NoConvolution ; <LW18>
Btst #spCompOutPAL,D1 ; Were we driving PAL out <LW18>
Bne.s @DoingPAL ; if 1, then yes, it's PAL <LW18>
Bset #NTSCTimingOn,d0 ; say we are driving NTSC <LW18>
@DoingPAL ; <LW18>
Move.w d0,GFlags(a3) ; and save our GFlags that changed
;
; Do a little bookkeeping, etc<74>
;
@Bookkeeping
Move.w #8,saveVidInMode(A3) ; Initialize the Video-in Mode to say 8bpp
Move.w D2,saveMonID(A3) ; Save the monID for later.
Move.b dCtlSlotId(A1),saveSlotId(A3) ; Also save the spID.
dRead_Civic #VRAMSize,D2 ; Read the vRAM size register.
Move.b D2,saveSizeVRAM(A3) ; Save it for later.
dRead_Civic #VDCClk,D2 ; Get the state of the VDC clock
Move.w D2,VDCCLkState(A3) ; and save it
dRead_Civic #VDCEnb,D2 ; Get the state of the VDC enable bit
Move.w D2,VDCEnbState(A3) ; and save it
Endwith
;
; 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 @AllDone ; Otherwise, skip.
@SetMonoFlags Bset #IsMono,GFlags(A3) ; Turn on the IsMono and
Bset #GrayFlag,GFlags(A3) ; GrayFlag flags.
@AllDone Move.l (SP)+,A4 ; restore our scratch register
MOVEQ #noErr,D0 ; no error
@EndOpen RTS ; return
@OpError5 Adda #sizeSPRamRec,Sp ; Release the SPRam block.
@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
Move.l (SP)+,A4 ; restore our scratch register
BRA.S @EndOpen
ENDWITH
**********************************************************************
*
* Video Driver Control Call Handler. There are 15 standard calls:
*
* ($00) Reset (VAR csMode, csPage: INTEGER; VAR csBaseAddr: Ptr);
* ($01) KillIO
* ($02) SetMode(csMode, csPage: INTEGER; VAR BaseAddr: Ptr);
* ($03) SetEntries (csTable: Ptr; Start,Count : integer );
* ($04) SetGamma (csGTable : Ptr );
* ($05) GrayPage (csPage);
* ($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);
* ($0A) SwitchMode (csPageInfo); <LW14>
* ($09) SetSync (csMode = 0 for enable, non-zero for disable); <LW14>
*
* The following calls are Civic-specific:
*
* ($83) SetAltSense(csMode = byte 0 is sense code, byte 1 is type);
* ($85) CivicSetCompOut (csMode = 0 for enable, non-zero for disable); <LW14>
* ($87) SetRGBByPass(csMode = 0 for enable, non-zero for disable); <LW14>
* ($89) SetVidInMode (csMode,csPage: INTEGER; VAR csBaseAddr: Ptr); <LW14>
* ($8A) SetVidInRect (csRect: RECT; csPage: INTEGER; VAR csBaseAddr: Ptr);<LW14>
*
* 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<73>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<6C>
;
CivicVidCtl
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),A3 ;
MOVE.W csCode(A0),D0 ; get routine selector
Cmp.w #$80,D0 ; Is it a private control call
Bhs.s PrivateCtrlCall ; Go decode it
CMP.W #$0B,D0 ; IF csCode NOT IN [0..$B] THEN
BHI.S CivicCtlBad ; Error, csCode out of bounds.
MOVE.W CivicCtlJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine.
JMP CivicCtlJumpTbl(PC,D0.W) ; GOTO the proper routine.
CivicCtlJumpTbl
DC.W CivicVidReset-CivicCtlJumpTbl ; $00 => VidReset
DC.W CivicCtlGood-CivicCtlJumpTbl ; $01 => CtlGood (no async routines here)
DC.W CivicSetVidMode-CivicCtlJumpTbl ; $02 => SetVidMode
DC.W CivicSetEntries-CivicCtlJumpTbl ; $03 => SetEntries
DC.W CivicSetGamma-CivicCtlJumpTbl ; $04 => SetGamma
DC.W CivicGrayPage-CivicCtlJumpTbl ; $05 => GrayPage
DC.W CivicSetGray-CivicCtlJumpTbl ; $06 => SetGray
DC.W CivicSetInterrupt-CivicCtlJumpTbl ; $07 => SetInterrupt
DC.W CivicDirectSetEntries-CivicCtlJumpTbl ; $08 => DirectSetEntries
DC.W CivicSetDefaultMode-CivicCtlJumpTbl ; $09 => SetDefaultMode
DC.W CivicSwitchMode-CivicCtlJumpTbl ; $0A => SwitchMode
DC.W CivicSetSync-CivicCtlJumpTbl ; $0B => SetSync <LW14>
PrivateCtrlCall
CMP.W #$8B,D0 ; IF csCode NOT IN [$80..$8B] THEN
BHI.S CivicCtlBad ; Error, csCode out of bounds.
Subi.w #$80,D0 ; Normalize the code
MOVE.W PrivCtlJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine.
JMP PrivCtlJumpTbl(PC,D0.W) ; GOTO the proper routine.
PrivCtlJumpTbl
DC.W CivicCtlBad-PrivCtlJumpTbl ; $80 => Unused
DC.W CivicCtlBad-PrivCtlJumpTbl ; $81 => Unused
DC.W CivicCtlBad-PrivCtlJumpTbl ; $82 => Unused
DC.W CivicSetAltSense-PrivCtlJumpTbl ; $83 => CivicSetAltSense
DC.W CivicCtlBad-PrivCtlJumpTbl ; $84 => Unused (cscLowPower)
DC.W CivicSetCompOut-PrivCtlJumpTbl ; $85 => CivicSetCompOut
DC.W CivicCtlBad-PrivCtlJumpTbl ; $86 => Unused
DC.W CivicSetRGBByPass-PrivCtlJumpTbl ; $87 => CivicSetRGBByPass
DC.W CivicCtlBad-PrivCtlJumpTbl ; $88 => Unused
DC.W CivicSetVidInMode-PrivCtlJumpTbl ; $89 => SetVidInMode
DC.W CivicSetVidInRect-PrivCtlJumpTbl ; $8A => SetVidInRect
DC.W CivicCtlBad-PrivCtlJumpTbl ; $8B => Unused
CivicCtlBad MOVEQ #controlErr,D0 ; else say we don't do this one
BRA.S CivicCtlDone ; and return
CivicCtlGood MOVEQ #noErr,D0 ; return no error
CivicCtlDone MOVEM.L (SP)+,A0/A1 ; Restore Exit registers.
BRA CivicExitDrvr
CivicVidReset
;---------------------------------------------------------------------
;
; Reset the built-in video to its default
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVE #FirstVidMode,csMode(A2) ; return default mode
Move.w saveMode(A3),d0 ; Get our current mode <LW17> #1083318
Cmp.w saveNewBaseMode(A3),d0 ; If our current mode is <20> the threshold mode where the base address changes <LW17> #1083318
blo.s @NoOffset ; don't need to subract when it's less than <LW17> #1083318
Move.l saveBaseAddr(a3),d0 ; Get our current base <LW17> #1083318
Sub.l saveBaseAddrOffset(a3),d0 ; subtract the offset <LW17> #1083318
Move.l d0,saveBaseAddr(a3) ; and save it <LW17> #1083318
@NoOffset ; <LW17> #1083318
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 CivicSetDepth ; set the depth from D1
BCLR #IsDirect,GFlags(A3) ; turn off direct mode bit
Move.l saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
BSR CivicGrayScreen ; paint the screen gray
BRA.S CivicCtlGood ; => no error
ENDWITH
CivicSetVidMode
;---------------------------------------------------------------------
;
; Set built-in video to the specified mode. Only page zero is possible,
; so we need to check that the request was OK.
;
; Check to see if we are in one of two situations:
;
; 1. We are in a mode where video-in is enabled but the desired mode
; is only suppported without video-in. (Here, go and disable
; video-in before continuing on.
;
; 2. We are in a mode where video-in is not supported and the desired
; mode IS supported with video-in. In this case, go enable video-in
; before continuing on.
;
; If built-in video is already set to the specified mode, then do nothing.
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVE.W csMode(A2),D1 ; D1 = mode
BSR CivicChkMode ; check mode and convert
BNE.S CivicCtlBad ; => not a valid mode
TST.W csPage(A2) ; only page zero is valid
BNE.S CivicCtlBad ; => not a valid page
; Only set if mode has changed.
CivicSetVidModeGuts
MOVE.W csMode(A2),D2 ; get the mode spID (D1 has the zero-based mode)
Move.w saveMode(A3),scratch(A3) ; save our old mode in case we need to know what it was later on
CMP saveMode(A3),D2 ; has the mode changed?
BEQ @JustReturn ; if not, then skip graying
Bsr CivicSetVidModeGuts2
@JustReturn
Move.l saveBaseAddr(A3),csBaseAddr(A2) ; return the base addr
BRA CivicCtlGood ; return no error
; Remember the newly requested mode.
;---------------------------------------------------------------------
;
; This used to be linear code, but I made it a subroutine so that it can
; be called by SetRGBBypass, which does not return a csBaseAddr.
;
;---------------------------------------------------------------------
CivicSetVidModeGuts2
MOVE.W D2,saveMode(A3) ; remember requested mode
Move.l dCtlDevBase(A1),saveBaseAddr(A3) ; Get the base address
Cmp.w saveNewBaseMode(a3),d2 ; If our desired mode is
blo.s @NoOffset ; less than the offset-threshold mode, don't update the base address
Move.l saveBaseAddrOffset(A3),d0 ; get our new offset
add.l d0,saveBaseAddr(A3) ; and save our new base address
@NoOffset
; Set the entire color table to gray before switching to avoid screen anomalies.
Movem.l A4-A6/D4-D5,-(Sp) ; Save gamma-table 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<72>s only one table,
Beq.s @OnlyOneTable ; then we<77>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<73>
Adda.w D0,A6 ; <09>of blue (red base + D0 + D0).
@OnlyOneTable
Move.w gDataCnt(A0),D3 ; Save number of gamma entries.
MOVE.L saveVDACBase(A3),A0 ; get the VDAC base addr
Move.b SebastPCBR(A0),D0 ; Make sure we're writing to the Graphics CLUT
Bclr #fCivicVidInCLUT,D0 ; by zeroing the CLUT select bit in the PCBR
Move.b D0, SebastPCBR(A0) ; and write it back out.
ADDA.W #SebastDataReg,A0 ; point to data register
Moveq #0,D4 ; D4 contains the beginning of the CLUT
Move.b D4,SebastAddrReg-SebastDataReg(A0) ; start at the beginning of CLUT
MOVE.W SR,-(SP) ; preserve the status register
BSR CivicWaitVSync ; wait for next blanking period (preserves A0)
; Write out gamma-corrected true-gray CLUT<55>
;
Move.w D3,D0 ; Init loop counter.
Subq #1,D0 ; Zero base it.
Move.w GFlags(A3),D2 ; Get the GFlags into a convenient register.
Lsr.w #1,D3 ; Get midpoint of table(s).
Btst #videoInEnb,D2 ; If video-in is enabled, need to read the alpha
Bne @VidInRepeat ; before writing the grey
@Repeat Btst #IsMono,D2 ; If this is not a mono-only display
Beq.s @DoRGB ; then 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,
Clr.b (A0) ; alpha.
Dbra D0,@Repeat
Bra.s @FinishedGray ; Go set depth
@VidInRepeat Move.b (A0),D5 ; Read: red,
Move.b (A0),D5 ; green,
Move.b (A0),D5 ; blue,
Move.b (A0),D5 ; alpha,
Move.b D4,SebastAddrReg-SebastDataReg(A0) ; Reset the CLUT Address register
Btst #IsMono,D2 ; If this is not a mono-only display
Beq.s @VidInDoRGB ; then do the standard RGB stuff.
Clr.b (A0) ; Otherwise, just write black out
Clr.b (A0) ; to the red & green channels.
Bra.s @VidInDoMono ;
@VidInDoRGB Move.b (A4,D3),(A0) ; Write: red,
Move.b (A5,D3),(A0) ; green,
@VidInDoMono Move.b (A6,D3),(A0) ; blue,
Move.b D5,(A0) ; alpha.
Addq #1,D4 ; Increment the CLUT Address Register
Dbra D0,@VidInRepeat
@FinishedGray
MOVE (SP)+,SR ; restore the status reg
Movem.l (Sp)+,A4-A6/D4-D5 ; Restore gamma-table registers.
BSR CivicSetDepth ; set the depth from D1
; Finish up the bookkeeping.
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
Rts
ENDWITH
CivicSetEntries
;---------------------------------------------------------------------
;
; Input :
; csParam -> datablock
; datablock = csTable -> table of colorSpecs (not colortable)
; csStart -> where to start setting, or -1, or -2
; 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 CivicVidPrivates,CivicCLUTRec
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
BNE.S CivicCtlBad ; error if so
CivicSEGuts
TST.L csTable(A2) ; Check for a nil pointer
BEQ CivicCtlBad ;
MOVEM.L A1/A4-A6/D4-D7,-(SP) ; save registers for gamma
MOVE.W GFlags(A3),D5 ; get GFlags word in D5
Cmp.w #alphaEntries,csStart(A2) ; Do we have alpha entries (XColorSpec)
Bne.s @SkipAlpha ; if not, leave bit off
Bset #HasAlpha,D5 ; turn on the bit that denotes that the csTable has alpha entries. This will always use an
Bra.s @SkipSeq ; indexed mode to write to the CLUT, so skip the Sequential stuff.
@SkipAlpha
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 #PsuedoIndex,D5 ; turn on the bit that denotes a seq write that was xlated to indexed
Cmp.w #FourthVidMode,saveMode(A3) ; If it<69>s not 8bbp, 16bpp, or 32bpp,
Blt.s @SkipSeq ; need to use <20>indexed<65>.
BSET #UseSeq,D5 ; otherwise, 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 a index
Moveq #0,D6 ; clear all of D6 for .w compare.
Lea CivicCLUTTbl,A0 ; Point to the table of CLUT data.
Lea (A0,D1*CivicCLUTSize),A0 ; Point to the right entry.
Move.b ccRange(A0),D6 ; Get the range.
;
; Allocate a temporary color table on the stack. We'll pre-process all the entries that will
; change here so we can hit the hardware as quickly as possible.
;
MOVE.W csCount(A2),D3 ; get the number of entries to change
CMP.W D6,D3 ; is it in the allowable range
BHI CivicSEBadExit ; if out of range, then exit w/bad result
Move.w csStart(A2),D0 ; Get the start number to range check.
Addq.w #2,D0 ; If csStart < -2, then it<69>s out of
Bmi CivicSEBadExit ; range.
Move.w csStart(A2),D0 ; Get the start number to range check.
Bmi @SkipUpperRangeCheck ; Only do it if csStart is positive or 0.
Add.w csCount(A2),D0 ; If csStart + ccCount exceeds the allowable range
Cmp.w D6,D0 ; D6 has the max range for the CLUT
BHI CivicSEBadExit ; if out of range, then exit w/bad result
@SkipUpperRangeCheck
Move.l D3,D4 ; Make a copy of the table size (zero-based).
Addq #1,D4 ; Make it a counting number.
Btst #UseSeq,D5 ; If we<77>re not in sequential mode,
Beq.s @IsIndex ; then do the indexed stuff.
Asl.w #2,D4 ; Make room for just R,G,B,alpha in sequential mode.
Bra.s @AllocIt ; And continue.
@IsIndex Mulu #5,D4 ; Make room for i,R,G,B,alpha in indexed mode.
@AllocIt Sub.w D4,Sp ; Allocate the table on the stack.
;
; 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).
;
Move.l A3,D6 ; We<57>re about to torch A3, so save it for later.
Move.l A0,A3 ; Save the CLUT table entry pointer.
MOVE.L SP,A0 ; copy the stack buffer pointer
MOVE.L csTable(A2),A1 ; get colorSpec pointer into A1
; Death! Totally out of registers in this routine, so I'm using the top half of D4 (the temp buffer
; size) as the sequence counter used in most video modes to translate sequential requests into
; the indexed write that the hardware needs.
SWAP D4 ; flip the buffer size to the top half
MOVE.W csStart(A2),D4 ; pick up the sequential start position. It might
; be -1 or -2 on a true indexed write, but we won't
; use it below if it is.
;
; Write the index if in indexed mode. If in sequential (8/16) mode, blow it off completely,
; since it won't be needed.
@SetupLoop
MOVE.W (A1)+,D0 ; get index
BTST #UseSeq,D5 ; is it sequence mode?
BNE.S @SLSeq ; yup, so go there
Btst #PsuedoIndex,D5 ; If we are doing an <20>indexed<65> mode,
Beq.s @IndexPresent ; then go there now.
; This case is a sequential request in a screen depth that does not allow sequential CLUT writes
; (any non-8/16/32 bit mode). In this case, we substitute the sequence counter for D0 on each
; entry.
Move.w D4,D0 ; Copy the sequence counter to D0.
Addq #1,D4 ; Increment it.
@IndexPresent Mulu.w ccSkip(A3),D0 ; Calculate the new position at this depth.
Add.b ccStart(A3),D0 ; Add in the first entry offset.
Move.b D0,(A0)+ ; Write out this index.
@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 luminance 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,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
Btst #HasAlpha,D5 ; test to see if color table has an alpha entry
Beq.s @NoAlpha ; it doesn't, write a zero for that entry
Move.w (A1)+,D0 ; get the 16-bit alpha value
Move.b D0,(A0)+ ; and write it to the table as 8 bits
Bra.s @DoTheLoop ; go loop
@NoAlpha
Clr.b (A0)+ ; Write zero for the alpha entry
@DoTheLoop
DBRA D3,@SetupLoop ; and loop for each entry
Swap D4 ; Put the temp buffer size back in the lo-half.
;
; OK, the stack table is set up. Now let's load the hardware.
;
Move.w Sr,-(Sp) ; Preserve the status register. (Watch out for LEA 2(SP) )
Move.l D6,A3 ; Get our privates pointer back into A3 (for WaitVSync).
BSR CivicWaitVSync ; Wait for next blanking period (preserves A0/D0).
MOVE.W csCount(A2),D3 ; get the count again
MOVE.L saveVDACBase(A3),A3 ; get the VDAC base
Move.b SebastPCBR(A3),D0 ; Make sure we're writing to the Graphics CLUT
Bclr #fCivicVidInCLUT,D0 ; by zeroing the CLUT select bit in the PCBR
Move.b D0, SebastPCBR(A3) ; and write it back out.
LEA SebastDataReg(A3),A3 ; point to VDAC data register
LEA 2(SP),A0 ; point to the stack buffer again
;
; Check to see if video-in is enabled
;
Btst #videoInEnb,D5 ; is video-in enabled
Bne.s CivicVinIndexWrite ; if it is, then go check whether is indexed/sequenced
BTST #UseSeq,D5 ; is it sequence mode?
BNE.S CivicSeqWrite ; yup, sequence mode, so go there
;
; Here's the loop that actually writes to the hardware when in indexed mode.
;
CivicIndexWrite
MOVE.B (A0)+,SebastAddrReg-SebastDataReg(A3) ; write the index value to the CLUT address
MOVE.B (A0)+,(A3) ; write red
MOVE.B (A0)+,(A3) ; write green
MOVE.B (A0)+,(A3) ; write blue
MOVE.B (A0)+,(A3) ; write alpha
DBRA D3,CivicIndexWrite ; and loop
BRA.S CivicSEDone ;
;
; Write out the translated starting position for sequence mode.
;
CivicSeqWrite
MOVE.W csStart(A2),D0 ; get sequence start address
MOVE.B D0,SebastAddrReg-SebastDataReg(A3) ; write the sequence start position
;
; Here's the loop that actually writes to the hardware when in sequence mode.
;
@SeqLoop
MOVE.B (A0)+,(A3) ; write red
MOVE.B (A0)+,(A3) ; write green
MOVE.B (A0)+,(A3) ; write blue
MOVE.B (A0)+,(A3) ; write alpha
DBRA D3,@SeqLoop ; and loop
BRA.S CivicSEDone ;
;
; Video in is enabled here. Need to check if we actually have alpha data in the table we built.
; If so, go back to the CivicIndexWrite (it's always in indexed mode when we have alpha). Also,
; check if there is no real alpha in the table, whether it's a sequence write (Table has: r,g,b,alpha)
; or an index write (Table has index,r,g,b,alpha).
;
CivicVinIndexWrite
Btst #HasAlpha,D5 ; Do we have alpha data?
Bne CivicIndexWrite ;If so, do a regular index write that uses the stack data
BTST #UseSeq,D5 ; is it sequence mode?
BNE.S CivicVinSeqWrite ; yup, sequence mode, so go there
;
; Here's the loop that actually writes to the hardware when in indexed mode and video-in enabled.
; We first read the RGB+alpha for the index value from the CLUT, and use this last alpha when we
; write it back in.
;
CivicVinIndexWriteLoop
Move.b (A0),SebastAddrReg-SebastDataReg(A3) ; write the index value to the CLUT address
Move.b (A3),D7 ; read the red
Move.b (A3),D7 ; read the green
Move.b (A3),D7 ; read the blue
Move.b (A3),D7 ; read the alpha
MOVE.B (A0)+,SebastAddrReg-SebastDataReg(A3) ; re-write the index value to the CLUT address
MOVE.B (A0)+,(A3) ; write red
MOVE.B (A0)+,(A3) ; write green
MOVE.B (A0)+,(A3) ; write blue
Move.b D7,(A3) ; write alpha
Tst.b (A0)+ ; skip past the alpha in the table we built
DBRA D3,CivicVinIndexWriteLoop ; and loop
BRA.S CivicSEDone ;
;
; Write out the translated starting position for sequence mode with video-in enabled.
;
CivicVinSeqWrite
MOVE.W csStart(A2),D0 ; get sequence start address
MOVE.B D0,SebastAddrReg-SebastDataReg(A3) ; write the sequence start position
;
; Here's the loop that actually writes to the hardware when in sequence mode. Again, first
; we read the values in the CLUT, save the alpha (discarding RGB) and write the new values
; with the old alpha. The address register is self-incrementing, so we make use of this
; feature to only write it once. When we're reading the values, the addess register already
; has the "next" address
;
@SeqVinLoop
Move.b (A3),D7 ; read the red
Move.b (A3),D7 ; read the green
Move.b (A3),D7 ; read the blue
Move.b (A3),D7 ; read the alpha
Move.b D0,SebastAddrReg-SebastDataReg(A3) ; write the sequence start position
MOVE.B (A0)+,(A3) ; write red
MOVE.B (A0)+,(A3) ; write green
MOVE.B (A0)+,(A3) ; write blue
Move.b D7,(A3) ; write alpha
Tst.b (A0)+ ; skip past the alpha in the table we built
Addq #1,D0 ; increment the sequence start address
DBRA D3,@SeqVinLoop ; and loop
;
; Clean up and go home.
;
CivicSEDone
MOVE (SP)+,SR ; restore status register
ADD D4,SP ; release stack buffer
MOVEM.L (SP)+,A1/A4-A6/D4-D7 ; restore registers
BRA CivicCtlGood ; return O-Tay!
CivicSEBadExit
MOVEM.L (SP)+,A1/A4-A6/D4-D7 ; restore registers
BRA CivicCtlBad ; return an error code
ENDWITH
CivicSetGamma
;---------------------------------------------------------------------
;
; 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 CivicVidPrivates
; 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 CivicCtlBad ; => no, return error
Tst.w gType(A2) ; Test the hardwareID.
Beq.s @ChangeTable ; If 0, then accept a TFB-style gamma table.
CMP.W #drHwCivic,gType(A2) ; type = Civic?
BNE CivicCtlBad ; => no, return error
TST.W gFormulaSize(A2) ; if gType=Civic, 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 CivicCtlBad ; 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 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 CivicCtlBad ; => 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<69>
MOVE.L (A2)+,(A0)+ ; <09>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<69>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 CivicDirectCLUTSet ; if so, then set up direct CLUT ramps
@Out
BSR CivicVideoCLUTSet ; Set up the VideoCLUT ramps
BRA CivicCtlGood ; => return no error
ENDWITH
CivicGrayPage
;---------------------------------------------------------------------
;
; 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 CivicVidPrivates
Move.l A5,-(SP) ; Save our work register
MOVE saveMode(A3),D1 ; D1 = mode
BSR CivicChkMode ; convert mode to depth in D1
BNE CivicCtlBad ; => not a valid depth
MOVE csPage(A2),D0 ; D0 = page
BNE CivicCtlBad ; => not a valid page
; Disable Overlay if video-in is on and the overlay bit is set
Btst #videoInEnb,GFlags(A3) ; Is it on
Beq.s @GrayIt ; if not, don't do anything
Move.l saveVDACBase(A3), A5 ; Get the a pointer to CLUT/DAC
Move.b SebastPCBR(A5), D0 ; Get the PCBR Value
Btst #fCivicVidInOvly,D0 ; Is it ON
Sne scratch(A3) ; if it is, save a flag
Bclr #fCivicVidInOvly,D0 ; Disable Overlay
Move.b D0,SebastPCBR(A5) ; Write it out
@GrayIt
BSR CivicGrayScreen ; paint the screen gray
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
BEQ.S @Out ; if not, then we're done
BSR CivicDirectCLUTSet ; if so, then set up direct CLUT ramps
@Out
BSR CivicVideoCLUTSet ; Set up the VideoCLUT ramps
Btst #videoInEnb,GFlags(A3) ; Is it on
Beq.s @Exit ; if not, don't do anything
Tst.b scratch(A3) ; Was the overlay bit set?
Beq.s @Exit ; no, so don't retouch it.
Move.b SebastPCBR(A5), D0 ; Get the PCBR Value
Bset #fCivicVidInOvly,D0 ; Enable Overlay
Move.b D0,SebastPCBR(A5) ; Write it out
@Exit
Move.l (Sp)+,A5 ; Restore our work register
BRA CivicCtlGood ; => return no error
ENDWITH
CivicSetGray
;---------------------------------------------------------------------
;
; 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
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
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 CivicSetIntCom ; call common code
BRA CivicCtlGood ; all done
;
; This shared routine sets up a flag in GFlags. It takes a pointer to
; private storage in A3, and the bit field start location in D1.
;
CivicSetIntCom
MOVE.B csMode(A2),D0 ; get boolean
BFINS D0,GFlags(A3){D1:1} ; set flag bit
RTS ; and return
ENDWITH
CivicSetInterrupt
;---------------------------------------------------------------------
;
; 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,CivicVidPrivates,CivicRecord
MOVEQ #1,D1 ; set up for BFEXTU to point to IntDisFlag
BSR.S CivicSetIntCom ; call common code
BNE.S @DisableThem ; if zero, then enable
; This code enables interrupts and installs the interrupt handler.
;
BSR.S CivicEnableVGuts ; call common code
BNE CivicCtlBad ; error, flag problem
BRA CivicCtlGood ; and go home
; This code disables VBL interrupts, then removes the interrupt handler.
;
@DisableThem
BSR.S CivicDisableVGuts ; jump to the disabling utility
BRA CivicCtlGood ; all done
; The following two routines are common code shared between the Open/Close calls
; and the SetInterrupt control call.
;
CivicDisableVGuts
MOVE.W SR,-(SP) ; preserve the status register
BSR CivicWaitVSync ; to be safe, wait for the next VBL
dWrite_Civic #0,#VBLEnb ; Disable Civic VBLs.
dWrite_Civic #0,#VBLClr ; Clear the current VBL.
MOVE (SP)+,SR ; re-enable cursor interrupts
CLR.W D0 ; setup slot 0 for _SIntRemove
MOVE.L saveSQElPtr(A3),A0 ; get the SQ element pointer
_SIntRemove ; remove the interrupt handler
RTS
CivicEnableVGuts
MOVE.L saveSQElPtr(A3),A0 ; get the queue element
LEA CivicBeginIH,A2 ; save Pointer to interrupt handler
MOVE.W #SIQType,SQType(A0) ; setup queue ID
Move.W #255,SQPrio(A0) ; Give the VBL top priority
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
dWrite_Civic #1,#VBLEnb ; Enable Civic VBLs.
dWrite_Civic #1,#VBLClr ; Un-Clear VBLs.
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
CivicDirectSetEntries
;---------------------------------------------------------------------
;
; 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.S CivicCtlBad ; error if not
BRA.S CivicSEGuts ; jump to SetEntries internals if it's OK
CivicSetDefaultMode
;---------------------------------------------------------------------
;
; 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,CivicVidPrivates,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<6F>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<72>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<69>s not catDisplay,
Bne.s @BadExit ; then quit.
Move.w spCType(A0),D0 ; Get the type.
Cmp.w #typVideo,D0 ; If it<69>s not typVideo,
Bne.s @BadExit ; then quit.
Move.w spDrvrSw(A0),D0 ; Get the software kind.
Cmp.w #drSwApple,D0 ; If it<69>s not drSwApple,
Bne.s @BadExit ; then quit.
Move.w spDrvrHw(A0),D0 ; Get the hardware ID.
Cmp.w #drHwCivic,D0 ; If it<69>s not drHwCivic,
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.
;
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 CivicCtlGood ; return good result.
@BadExit Adda #SizesPRAMRec+spBlockSize,SP ; Deallocate buffer and
Bra CivicCtlBad ; return bad result.
ENDWITH
CivicSetVidInMode
;---------------------------------------------------------------------
;
; Set the Video-in parameters in Civic to the values specified in
; the rect passed to the routine.
;
; Entry: A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage (CivicVidPrivates)
;
; Used: A0 = scratch Ptr to CivicVidInTable
; A4 = scratch Ptr to VidParams (restored)
; A5 = scratch Ptr to SebastBase (restored)
;
;---------------------------------------------------------------------
WITH VDPageInfo, CivicVidPrivates, CivicVidParams, CivicBppParams, CivicRecord
Tst.w csPage(A2) ; only page zero is valid
Bne.s CivicCtlBad ; => not a valid page
MOVEM.L A4-A6/D3-D7,-(SP) ; Save scratch registers
; Bail out if video-in is not enabled.
Btst #videoInEnb,GFlags(A3) ; If Video-in is not enabled
Beq VidInCtlBad ; then return error.
Move.w csMode(A2),D2 ; Get the mode
Cmp.w #8,D2 ; 8
Beq CVidInModeOK ;
Cmp.w #16,D2 ; or 16
Beq CVidInModeOK ;
Bra VidInCtlBad ; return error due to incorrect csMode
CVidInModeOK
Move.l #vCivicVidInBase,csBaseAddr(A2) ; Return the static video-in VRAM base address
;
; Check to see if the Overlay Bit in Sebastian is enabled. If not, assume video-in was not turned on
; and if it is, check to see whether the desired video bpp is different than what's already showing. If
; it isn't, we don't need to change anything!
Move.w saveVidInMode(A3),scratch(a3) ; Save our mode in case we need to bail out <LW17> #1084366
Move.w D2,saveVidInMode(a3) ; Save the mode in our privates.
Lsr.w #4,D2 ; Make csMode zero-based (0 = 8bpp, 1 = 16bpp)
Move.l saveVDACBase(A3), A5 ; Get the a pointer to CLUT/DAC
Move.b SebastPCBR(A5), D7 ; Get the PCBR Value
Move.b D7,D0 ; Get a temporary value for it
Btst #fCivicVidInOvly,D7 ; Check to see if overlay is enabled
Beq.s CVidInMonSupport ; ( 0 = not enabled )
Lsr.b #fCivicVidInBpp,D0 ; Overlay was enabled: Move the video-in bpp bit
Andi.b #1,D0 ; and mask it so that it's $01 or $00
Cmp.b D0,D2 ; If equal to our zero-based csMode, then do nothing
Beq CVidInGoHome ; return good status (returning MMU mode to correct state)
CVidInMonSupport
;
; Check to see if the monitor supports the desired bpp depth. D2 contains this depth. 0 = 8 bpp, 1 = 16bpp
;
Move.l saveVidPtr(A3),A4 ; Get the pointer to our video parameters
Move.b cvpMaxVidInMode(A4),D0 ; Get the maximum video-in mode
Sub.b #FourthVidMode,D0 ; Make the vid-in mode zero-based (0=8bpp, 1=16bpp)
Cmp.b d0,d2 ; If desired mode > max mode,
Bhi CVidInBad ; then we don't support it.
WITH CivicVidInRec, CVidInVRAMRec, CVidInBPPRec
; Turn off overlay while we do this stuff, so we don't get video all over the screen when we change parameters
;
Bclr #fCivicVidInOvly,D7 ; Disable overlay
Move.b D7,SebastPCBR(A5) ; and write it out
Bsr CGetVidInMonTable
Move.w cVidInMaxH(A0),D0 ; Get the Maximum Horizontal value
; Check to see if VidInMaxH == -1; If so, call a subroutine to calculate the maximum height given a width, for the monitor/VRAM configuration pair:
Cmp.w #-1, D0 ; is VidInMaxH == 0
Bne CivicVidInGetWidth ; nope
Move.w currentRight(a3),D1 ; Get the current VidInRect's width
Sub.w currentLeft(a3),D1 ; into D1
Bsr CivicCalcMaxHeight ; Uses D1 as the current width, calculates max height and returns it in D0
Tst.w D0 ; Was the width 0
Beq CVidInGetbpp ; If width == 0, then height == 0 and there was no vidinrect so just carry on.
Move.w currentBottom(a3),D1 ; Get the current VidInRect's height
Sub.w currentTop(a3),D1 ; into D1
Cmp.w D0,D1 ; is the current height > than the max allowed
Bgt CVidInBad ; yup
Bra CVidInGetbpp
; Check to see that the current VidInRect's width is less that the max width allowed, and also that the current height is less than the max width allowed.
; Return an error through CVidInBad to tell say that the specified bpp is illegal.
CivicVidInGetWidth
Move.w currentRight(a3),D1 ; Get the current VidInRect's width
Sub.w currentLeft(a3),D1 ; into D1
Cmp.w D0,D1 ; is the current width > than the max allowed
Bgt CVidInBad ; yup
Move.w cVidInMaxV(A0),D0 ; Get the Maximum Vertical value
Move.w currentBottom(a3),D1 ; Get the current VidInRect's height
Sub.w currentTop(a3),D1 ; into D1
Cmp.w D0,D1 ; is the current height > than the max allowed
Bgt CVidInBad ; yup
Bra CVidInGetbpp
ENDWITH
; Now, do separate stuff for video-in 16bpp and video-in 8bpp
;
CVidInGetbpp
Lsl.w #fCivicVidInBpp,D2 ; Get the zero-based vid-in mode and shift it to the correct position
Andi.b #$F7,D7 ; Clear the video-in bpp
Or.b D2,D7 ; and set/clear it depending on the vid-in mode
Jsr CSetVidInModeGuts
Move.l saveVDACBase(A3),A5 ; Get a pointer to the CLUT Base
Bset #fCivicVidInOvly,D7 ; Set the overlay enable
Move.b D7,SebastPCBR(A5) ; and write it out
; Now resize the vid in rect
Move.l saveVidPtr(A3),A4 ; Get a pointer to the video params.
Move.w currentRight(a3),-(SP) ; Get the current video in rect
Move.w currentBottom(a3),-(SP) ;
Move.w currentLeft(a3),-(SP) ;
Move.w currentTop(a3),-(SP) ; in reverse order
Jsr CivicSetVidRectJSR ; Go do the work
Adda #8,SP ; Clean up the stack
BSR CivicVideoCLUTSet ; Set up the VideoCLUT ramps
Bra CVidInGoHome
CGetVidInMonTable
; This subroutine will return A0 pointing to the correct Rect entry in CivicVidInTable, depending
; on the video-in bpp depth and the amount of VRAM. It is used by SetVidInMode to determine if the
; desired mode is supported by the monitor, and by SetVidInRect to determine what the maximum rect
; size is available in the current monitor/vid-in bpp combination.
;
; Needs: A3: Points to CivicVidPrivates
; A4: Points to VidParams
; D2: Zero-based video-in bpp depth: 0 = 8bpp, 1 = 16bpp
;
; Trashes: A0/D0/D1
;
; Returns: A0: Points to the correct video-in monitor entry.
;
; Check to see if the monitor supports the desired bpp depth. D2 contains this depth. 0 = 8 bpp, 1 = 16bpp
;
WITH CivicVidInRec, CVidInVRAMRec, CVidInBPPRec
;
; Check to see if we're driving out of the composite out and adjust the "monitor sensed"
; accordingly
Move.w GFlags(A3),D1 ; Get our flags
Btst #CompositeSyncOn,D1 ; Are we driving comp sync
Beq.s @ChkMultisync ; nope, so use the saveMonID <LW14>
Btst #NTSCTimingOn,D1 ; Are we driving NTSC?
beq.s @DrivingPAL ; no, we are doing PAL
Move.w #indexedSenseNTSC,D1 ; yes, say we have NTSC
Bra.s @ModifiedID
@DrivingPAL
Move.w #indexedSensePAL,D1 ; say we are driving PAL
bra.s @ModifiedID ; don't adjust D1 <LW14>
@ChkMultisync ; <LW14>
Cmpi.w #indexedSenseMSB1,saveMonID(A3) ; If we<77>re not in the multiscan mode, <LW14>
bne.s @OutRGBSyncs ; don't adjust D1 <LW14>
Move.w D2,-(SP) ; Save D2 'cause we trash it <LW14>
Move.b dCtlSlotID(A1),D2 ; Get the SpID. <LW14>
Moveq #0,D0 ; Clear hi-half of mode/depth register. <LW14>
Lea EquivalendMonIDTable,A0 ; get the equivalent ID table <LW14>
@ChkLoop Move.b (A0)+,D1 ; If we<77>re at the end of the table, <LW14>
Beq @BadExit ; then something<6E>s wrong. <LW14>
Move.b (A0)+,D0 ; Get the monID for this config. <LW14>
Cmp.b D1,D2 ; If this is not our spID, <LW14>
Bne.s @ChkLoop ; then keep looping. <LW14>
Move.w D0,D1 ; else, get our monID into the desired register <LW14>
Move.w (Sp)+,D2 ; Restore D2 <LW14>
Bra.s @ModifiedID ; and calculate the max size <LW14>
@OutRGBSyncs ; <LW14>
Move.w saveMonID(A3),D1 ; Get the monitor ID entry <LW14>
@ModifiedID
Lea CivicVidInTable,A0 ; Point to the Civic Video-In Table <LW14>
Move.w #CivicVidInRecSize,D0 ; Get the size of each entry into D0 <LW14>
Mulu D1,D0 ; Multiply it by the right entry
Adda.l D0,A0 ; Skip to the right monitor entry
Move.b saveSizeVRAM(A3),D1 ; VRAM size: 0 = 1Meg, 1 = 2Meg
Move.w #CVidInVRAMRecSize,D0 ; Get the size of each VRAM parameters entry
Mulu D1,D0 ; Multiply it by the right value
Adda.l D0,A0 ; and now point to the right VRAM entry
Move.w #CVidInBPPRecSize,D0 ; Get the size of each VRAM parameters entry
Mulu D2,D0 ; Multiply it by the right value
Adda.l D0,A0 ; and now point to the right bpp entry
@Exit ; <LW14>
Rts ; <LW14>
@BadExit
Move.w (Sp)+,D2 ; Restore D2 <LW14>
Lea CivicVidInTable+4,A0 ; Point to a bad entry in the table <LW14>
Bra.s @Exit ; and go away. <LW14>
ENDWITH
CivicCalcMaxHeight
; This subroutine will return the maximum height for the given width, depending on which monitor one is in.
; This is only called for 1MegVRAM configurations in 16bpp
; The max width is given by:
;
; maxHeight = ( width <= 512 ? 512 : 340 )
;
; Needs: D1 = current width
;
; Returns: D0 = max height
Move.w D1,D0
Beq MaxHExit ; If width = 0, max H = 0
Move.w #512,D0 ;
Cmp.w D0,D1 ; Is width <= then 512
Ble MaxHExit ; maxH = 512 else
Move.w #340,D0 ; maxH = 340
MaxHExit Rts ; go back
CVidInBad ; <LW17> #1084366
; <LW17> #1084366
; Need to restore the scratch registers and then call CivicCtlBad <LW17> #1084366
Move.w scratch(A3),saveVidInMode(A3) ; restore our Video-in mode <LW17> #1084366
MOVEM.L (SP)+, A4-A6/D3-D7 ; restore registers <LW17> #1084366
BRA.S CivicCtlBad ; go say we don't do this <LW17> #1084366
CivicSetVidInRect
;---------------------------------------------------------------------
;
; Set the Video-in parameters in Civic to the values specified in
; the rect passed to the routine.
;
; Entry: A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage (CivicVidPrivates)
;
; Used: A4 = scratch Ptr to VidParams ( restored)
; A5 = scratch Ptr to VDACBase (restored)
; D6 = Actual Graphics HAL
; D7 = Actual Graphics HFP
;
;---------------------------------------------------------------------
WITH CivicVidPrivates, CivicVidParams, CivicRecord, VDVidInRect
Tst.w csPage(A2) ; only page zero is valid
Bne.s CivicCtlBad ; => not a valid page
MOVEM.L A4-A6/D3-D7,-(SP) ; Save scratch registers
;
; Get the actual values for HAL and HFP. They are not the ones in the s-resource because they
; might've changed due to a VidInMode call.
;
Move.l saveVDACBase(A3), A5 ; Get a pointer to CLUT/DAC
Move.l saveVidPtr(A3),A4 ; Get a pointer to the video params.
Btst #videoInEnb,GFlags(A3) ; If video-in is not enabled
Beq VidInCtlBad ; then return error.
Bsr CivicChkVidInRect ; check rect values and return empty rect if illegal: 1. if not valid rect. 2. if rect too big for video
Bne CVidInRectBad ; If illegal rect return error (restore scratch registers) <LW17> #1084366
; Start of subroutine... (Reverse order 'cause stacks grows down.
Move.w (csRect+right)(A2),-(SP) ; right
Move.w (csRect+bottom)(A2),-(SP) ; bottom
Move.w (csRect+left)(A2),-(SP) ; left
Move.w (csRect+top)(A2),-(SP) ; Move top to stack
Jsr CivicSetVidRectJSR ; Go do the work
Bne CVidRectBad ; got an error
Move.w (SP)+,(csRect+top)(A2)
Move.w (SP)+,(csRect+left)(A2)
Move.w (SP)+,(csRect+bottom)(A2)
Move.w (SP)+,(csRect+right)(A2)
;
; Move the rect values into our vidin privates
;
Move.w (csRect+top)(A2),currentTop(a3) ; top
Move.w (csRect+left)(A2),currentLeft(a3) ; left
Move.w (csRect+bottom)(A2),currentBottom(a3) ; bottom
Move.w (csRect+right)(A2),currentRight(a3) ; right
Move.l #vCivicVidInBase,csBaseAddr(A2) ; Stuff the video-in base address
; Go home.
;
CVidInGoHome
VidInCtlGood
; Restore registers and exit
MOVEM.L (SP)+,A4-A6/D3-D7 ; restore registers
BRA.S CivicCtlGood ; go say we didn't have any errors
CVidRectBad
Move.w (SP)+,(csRect+top)(A2)
Move.w (SP)+,(csRect+left)(A2)
Move.w (SP)+,(csRect+bottom)(A2)
Move.w (SP)+,(csRect+right)(A2)
CVidInRectBad ; <LW17> #1084366
VidInCtlBad
;
; Need to restore the scratch registers and then call CivicCtlBad
MOVEM.L (SP)+, A4-A6/D3-D7 ; restore registers
BRA.S CivicCtlBad ; go say we don't do this
CivicChkVidInRect
;-------------------------------------------------------------
; Routine to check that a given Rect into SetVidInRect is kosher
;-------------------------------------------------------------
; This routine will check that the given rect is a valid rect
; There are 2 cases:
; 1. The Rect itself is invalid (right < left and/or botoom < top) return empty rect
; 2. The Rect is invalid because left or top are < 0.
; 2. The desired rect is greater than the max video-in rect allowed. Look at the monitor tables.
; 3. If in 8bpp-video in and graphics 8,4,2,1, then rect has to obey following rules:
; a. left has to be even (bit 0) == 0
; b. width has to be MOD 4 (bit 1,0) == 0;
; Uses: D0/D1/D2/D3
Clr.b D2 ; Used as a flag
Move.w (csRect+top)(A2),D0 ; Get the top edge of the rect
Bmi VidInNegativeRect ; If it's negative, return a -1 rect
Move.w (csRect+bottom)(A2),D1 ; and the bottom edge
Bmi VidInNegativeRect ; If it's negative, return a -1 rect
Cmp.w D0,D1 ; and see if the bottom edge is less
Ble VidInZeroRect ; return error with a zero rect
Move.w (csRect+left)(A2),D0 ; Get the left edge of the rect
Bmi VidInNegativeRect ; If it's negative, return a -1 rect
Move.w (csRect+right)(A2),D1 ; and the right
Bmi VidInNegativeRect ; If it's negative, return a -1 rect
Cmp.w D0,D1 ; and see if the right edge is less
Ble VidInZeroRect ; return error with a zero rect
; If the video is in 8bpp, make sure that the window width is MOD4 and the left is
; on an even bit. A5 contains the pointer to Sebastian
Move.b SebastPCBR(A5), D3 ; Get the PCBR Value
Btst #fCivicVidInBpp,D3 ; Are we in 16bpp
Bne VidRectOK
Sub.w D0,D1 ; calculate the width of the csRect
Btst #0,D0 ; Is the left edge on an even pixel
Beq CheckWidth
Bclr #0,D0 ; Make it even
Move.w D0,(csRect+left)(A2) ; and write it back out
Move.w (csRect+right)(A2),D1 ; Calculate the new width with the new left edge
Sub.w D0,D1 ; store the width in D1
Moveq #1,D2 ; Set up a flag that says we modifed csRect
CheckWidth
Btst #0,D1 ; Is the width even
Bne MakeRectMod4 ; if not, make it
Btst #1,D1 ; and also mod 4
Bne MakeRectMod4 ; if not, make it
Tst.b D2 ; Did we modify the left edge
Beq VidRectOK ; nope
Bra.s VidInRectMod ;
MakeRectMod4
Bclr #0,D1 ; make it even
Bclr #1,D1 ; and mod 4
Add.w (csRect+left)(A2),D1 ; Add the left edge to the width
Move.w D1,(csRect+right)(A2) ; and write it back out
Bra.s VidInRectMod
VidInNegativeRect
Move.w #-1,D0 ; Prepare to return a -1 rect
Move.w D0,(csRect+left)(A2) ; Returns a -1 rect to indicate
Move.w D0,(csRect+right)(A2) ; that the original rect was illegal
Move.w D0,(csRect+top)(A2)
Move.w D0,(csRect+bottom)(A2)
Bra.s VidInRectMod ; Return an error
VidInZeroRect
Clr.w (csRect+left)(A2) ; Returns a zero rect to indicate
Clr.w (csRect+right)(A2) ; that the original rect was illegal
Clr.w (csRect+top)(A2)
Clr.w (csRect+bottom)(A2)
VidInRectMod
Moveq #1,D0 ; Show that something went wrong
Bra.s CkVidRectExit
VidRectOK
Moveq #0,D0 ; For now, return a "good" value
CkVidRectExit
Rts
EndWith
CivicSetAltSense
;---------------------------------------------------------------------
;
; SetAltSense sets up the alternate senseID pRam byte to contain
; a valid <20>index<65> 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 MonIDs table (not restored)
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
With spBlock,CivicVidPrivates,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<6C>
;
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<64>
;
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<69>s the Radius ColorTPD,
Beq @WriteIt ; then write it out.
Cmp.b #extended2PRdMono,D1 ; If it<69>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<69>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<69>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 CivicMonIDs,A1 ; Get ptr to MonIDs 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 @TryGF ; Nope, try GoldFish.
Move.b #indexedSenseNTSC,D1
Bra.s @WriteIt
@TryGF Cmp.b #extendedSenseGF,D1 ; Is it the GoldFish?
Bne.s @Try19 ; Nope, try 19<31>.
Move.b #indexedSenseGF,D1 ;
Bra.s @WriteIt
@Try19 Cmp.b #extendedSense19,D1 ; Is it a 19<31>?
Bne.s @WriteIt ; Nope, must be indexed.
Move.b #indexedSense19,D1
@WriteIt Move.b D1,SP_AltSense(Sp) ; Write out <20>index<65> 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 and<6E>
Bra CivicCtlGood ; <09>leave.
@MonIDNotValid Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack and<6E>
Bra CivicCtlBad ; <09>leave with error.
Endwith
CivicSetRGBByPass
;---------------------------------------------------------------------
;
; This routine will do switch the frame buffer from RGB out to Composite out.
; In order to do this, it has to find the sresource that has the timing
; for NTSC or PAL, depending on the csType; it should delete the current
; sresource, insert it back as disabled, insert the NTSC/PAL one as enabled
; and reprogram Civic with these new values.
;
; VDCompositeFlagPtr: csMode [byte] 0: RGB Out, 1: Composite Out
; csStandard [byte] 0: NTSC, 1: PAL
; csConv [byte] 0: NonConvolved, 1: Convolved
;
; Entry: A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage (CivicVidPrivates)
;
; Used: A4 = scratch Ptr to VidParams ( restored)
; A5 = scratch Ptr to VDACBase (restored)
;
;---------------------------------------------------------------------
With VDCompositeOut,SPBlock,CivicFrame,CivicRecord,CVidInBPPRec
MOVEM.L A4-A7/D3-D7,-(SP) ; Save scratch registers
Move.w GFlags(A3),scratch(A3) ; Save our gflags for error exit
Move.l saveVidPtr(A3),A4 ; Get a Pointer to our current vidparams
Tst.b csMode(A2) ; Are we enabling composite out
Bne @SetCompositeSync ; Yes, go get the Composite VidParams.
; The call is to switch to drive to RGB, so first check to see if we're already doing it.
; If not, then there are two cases we have to look out for:
;
; 1. We are driving an interlaced display already. In this case saveRGBSlotId == 0 and
; the cvpScanCtl byte is 1. Just go and switch the bypass signal.
;
; 2. We need to drive a progressive scan display. In this case, the saveRGBSlotId <20> 0 and
; we need to get it and switch to it. (First we need to test if video-in was changed
; since the switch to composite and adjust the spID accordingly). We also then clear saveRGBSlotId.
;
@SetRGBSync
; First, check to see whether we are already driving RGB out:
Move.w GFlags(A3),D5 ; Get our gflags
Btst #CompositeSyncOn,D5 ; Look at our composite/RGB flag
Beq CBypassExit ; Already driving RGB
Bclr #CompositeSyncOn,D5 ; Say we are driving RGB
Move.w D5,GFlags(A3) ; and save it in our flags
; Now, check to see if we are supposed to drive an interlaced monitor (in which case we don't need to reprogram Civic)
Move.l #0,D3 ; MMC clock selects RGB Syncs
Move.b saveRGBSlotId(A3),D2 ; Do we have a 2nd slotID saved?
Beq.s @CheckInterlaced ; we don't if we originally had an interlaced disp through RGB)
; Set GFlags to reflect monochrome-only displays.
;
@SwitchSyncToRGB
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 @AllDone ; Otherwise, skip.
@SetMonoFlags Bset #IsMono,GFlags(A3) ; Turn on the IsMono and
Bset #GrayFlag,GFlags(A3) ; GrayFlag flags.
@AllDone
;
; In order to avoid driving the wrong timing into the composite monitor switch the bypass to RGB:
;
; Move.l saveYMCABaseAddr(A3),A0 ; MMC Clock Select. <LW19>
; Move.l #0,MMC_Bypass(A0) ; Switch to RGB Syncs <LW19>
Bra @GoSwitchMonitorsFromComposite ; We do, so go switch back to the correct monitor.
@CheckInterlaced
Tst.b cvpScanCtl(A4) ; Are our RGB Sync parameters for an interlaced display (1 = interlaced)
Bne CBypassQuick ; if so, then just switch mickey and turn on syncs
Bra CBypassExit ; Else, we don't know what monitor to drive.
; The call is to switch to drive Composite, so first check to see if we're already doing it.
; If not, then there are two cases we have to look out for:
;
; 1. We are driving an interlaced display already. In this case
; the cvpScanCtl byte is 1. Just go and switch the bypass signal.
;
; 2. We are driving a progressive scan display. In this case, save the current spID
; and get the desired switch ID from the vidparams and switch.
;
@SetCompositeSync
; First, check to see if we are already driving composite out:
Move.w GFlags(A3),D5 ; Get our gflags
Btst #CompositeSyncOn,D5 ; Look at our composite flag
Bne.s @AlreadyDrivingSync ; Don't need to save the spID
Move.b saveSlotId(A3),saveRGBSlotId(A3); Save our current slot ID so we can return to this monitor.
Bset #CompositeSyncOn,D5 ; If not, set the bit and
Move.w D5,GFlags(A3) ; save our internal flags
@AlreadyDrivingSync
Move.l #-1,D3 ; MMC clock select variable in D3
; When we get here, then we know that we should drive composite out and that our current display is not interlaced.
; Get the equivalent spID for NTSC/PAL out, depending on the selector csStandard
Tst.b csStandard(A2) ; Do we want NTSC or PAL
Beq.s @GetNTSC ; if 0, then we want NTSC
Tst.b csConv(A2) ; Do we want Convolution ON
Beq.s @GetPALNonConv ; if 1, then we want conv on
Bset #ConvolutionOn,D5 ; Say we are driving with convolution
Move.b cvpConvPALID(A4),D2 ; Get it in D2
Beq CBypassBad ; If it's zero, we can't do this.
Bra.s @SetPALFlag ; and carry on
@GetPALNonConv
Bclr #ConvolutionOn,D5 ; Say we are NOT driving with convolution
Tst.b saveSizeVRAM(A3) ; Load the correct spID depending on how much VRAM we have
Bne.s @1 ; branch if we have 2 megs
Move.b cvpPALID1Meg(A4),D2 ; Get the 1Meg spID
Beq CBypassBad ; If it's zero, we can't do this.
Bra.s @SetPALFlag ; Carry on
@1
Move.b cvpPALID2Meg(A4),D2 ; Get the 2Meg spID
Beq CBypassBad ; If it's zero, we can't do this.
* Bra.s @SetPALFlag ; Carry on
@SetPALFlag
Bclr #NTSCTimingOn,D5 ; Say we are driving PAL
Bra.s @GoSwitchMonitorsFromRGB ; Go Switch the monitor timing
@GetNTSC
Tst.b csConv(A2) ; Do we want Convolution ON
Beq.s @GetNTSCNonConv ; if 1, then we want conv on
Bset #ConvolutionOn,D5 ; Say we are driving with convolution
Move.b cvpConvNTSCID(A4),D2 ; Get it in D2
Beq CBypassBad ; If it's zero, we can't do this.
Bra.s @SetNTSCFlag ; and carry on
@GetNTSCNonConv
Bclr #ConvolutionOn,D5 ; Say we are NOT driving with convolution
Tst.b saveSizeVRAM(A3) ; Load the correct spID depending on how much VRAM we have
Bne.s @2 ; branch if we have 2 megs
Move.b cvpNTSCID1Meg(A4),D2 ; Get the 1Meg spID
Beq CBypassBad ; If it's zero, we can't do this.
Bra.s @SetNTSCFlag ; and carry on
@2
Move.b cvpNTSCID2Meg(A4),D2 ; Get the 2Meg spID
Beq CBypassBad ; If it's zero, we can't do this.
* Bra.s @SetNTSCFlag ; and carry on
@SetNTSCFlag
Bset #NTSCTimingOn,D5 ; say we are driving NTSC
; Disable the sync outputs to avoid driving them with the new interlaced parameters.
@GoSwitchMonitorsFromRGB
Move.w D5,GFlags(A3) ; save our internal flags
Bclr #IsMono,GFlags(A3) ; Turn off the IsMono and
Bclr #GrayFlag,GFlags(A3) ; GrayFlag flags.
@GoSwitchMonitorsFromComposite
; Save our current video-in bpp and state of the overlay enable bit so we can change it
; after the switch. (The DynamicSwitch routine will set it to the vidparams value for
; the PCBR, mainly overlay off and vid-in @ 8bpp).
Move.l saveVDACBase(A3), A5 ; Get the a pointer to CLUT/DAC
Move.b SebastPCBR(A5),D5 ; Store the current value
Andi.b #$88,D5 ; Clear all except overlay and vin bpp
dRead_Civic #VDCEnb,D7 ; Get the state of the VDCEnable bit in Civic
Move.w d7,-(SP) ; and save it.
dRead_Civic #VDCClk,D7 ; Get the state of the VDCClk
Move.w d7,-(SP) ; and save it.
Jsr DynamicSwitch ; Do the switch dynamically
Bne CBadMode ; Probably max mode < current mode
Move.w (Sp)+,D7 ; Get the saved VDCClk
dWrite_Civic D7,#VDCClk ; Write it out
Move.w (Sp)+,D7 ; Get the saved VDCEnb
dWrite_Civic D7,#VDCEnb ; Write it out
; Switch Mikey to drive out the correct port (RGB or Composite)
Move.l saveYMCABaseAddr(A3),A0 ; MMC Clock Select.
Move.l D3,MMC_Bypass(A0) ; Select the desired input clock, depending if we are
; going to RGB or to Composite
Move.l saveCivicBase(A3),A0 ; Point to the base of Civic.
Move.l D3,Civic_SyncClr(A0) ; Disable/Enable Sync outputs.
MOVEM.L (SP)+,A4-A7/D3-D7 ; restore registers
Move.w saveMode(a3),D2 ; get our current mode so the VidModeGuts
Move.w saveMode(a3),D1 ; get our current mode so the VidModeGuts
Sub.w #FirstVidMode,D1 ; Make mode zero-based.
Jsr CivicSetVidModeGuts2
Clr.l d0 ; Say we had no errors
BRA.S CivicCtlGood ; go say we didn't have any errors
; if VideoIn is enabled, we have to calculate the new video-in horiz/vert values
;
Move.w GFlags(A3),D0 ; Get our local flags to see
Btst #videoInEnb,D0 ; if video in is enabled
Beq.s CBypassExit ; if not, we don't have to adjust the video-in parameters
; Switch the CLUT/DAC<41>s depth.
;
Move.b SebastPCBR(A5),D7 ; Get the new programmed value
Andi.b #$77,D7 ; Clear the overlay enable and the vin bpp values
Or.b D5,D7 ; Get the saved ovly, vin bpp
Move.b D7,SebastPCBR(A5) ; Change the depth.
Jsr CSetVidInModeGuts ; Adjust the horizontal parameters
Movem.l A3-A5/D2-D7,-(Sp) ; Save our registers
Move.l saveVidPtr(A3),A4 ; Get a pointer to the vidParams.
Move.l saveVDACBase(A3), A5 ; Get the a pointer to CLUT/DAC
Move.w currentRight(a3),-(SP) ; Get the current video in rect
Move.w currentBottom(a3),-(SP) ;
Move.w currentLeft(a3),-(SP) ;
Move.w currentTop(a3),-(SP) ; in reverse order
Jsr CivicSetVidRectJSR ; Go do the work
Adda #8,SP ; Clean up the stack
Movem.l (Sp)+,A3-A5/D2-D7 ; Restore our registers
Jsr CivicReset ; Reset Civic (Needs A3 = vidprivates, trashes A0)
; Restore registers and exit
CBypassExit
MOVEM.L (SP)+,A4-A7/D3-D7 ; restore registers
BRA.S CivicCtlGood ; go say we didn't have any errors
CBadMode
Adda #4,SP ; Clean up the stack
Move.w d0,csMode(A2) ; return the max mode
CBypassBad
Move.w scratch(A3),GFlags(A3) ; restore our gflags
MOVEM.L (SP)+,A4-A7/D3-D7 ; restore registers
BRA.S CivicCtlBad ; go say we don't do this
ENDWITH
CBypassQuick
Move.l saveYMCABaseAddr(A3),A5 ; MMC Clock Select.
Move.l D3,MMC_Bypass(A5) ; Select the desired input clock, depending if we are
Move.l saveCivicBase(A3),A0 ; Point to the base of Civic.
Move.l D3,Civic_SyncClr(A0) ; Disable/Enable Sync outputs.
Bra.s CBypassExit
CBypassNoGo
Move.w scratch(A3),GFlags(A3) ; restore our gflags
Bra.s CBypassExit
CNoRGBSwitchExit
Move.w scratch(A3),GFlags(A3) ; restore our gflags
Bra.s CBypassExit
;---------------------------------------------------------------------
;
; This routine that will disable the current spID s-resource and
; enable a new spID as the current, enabled s-resource, and will change
; the vidparms pointer to it's parameters. It will then reprogram Civic
; to drive the new parameters.
;
;
; Entry: D2 = spID of the desired new monitor
;
; Exit: D0 = status
;
;---------------------------------------------------------------------
With VPBlock,SpBlock,CivicRecord
DynamicSwitch
MOVEM.L A0-A7/D1-D7,-(SP) ; Save scratch registers
SUBA #spBlockSize,SP ; make a slot parameter block
MOVE.L SP,A0 ; get pointer to block in A0
Clr.b spSlot(A0) ; Look at 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 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 CNoSwitch ; If an error, then bail out
MOVE.B #sVidParmDir,spID(A0) ; look for the video parameters dir
_sFindStruct ; Try to load it.
Bne CNoSwitch ; If an error, then bail out
MOVE.B D2,spID(A0) ; look in the directory for this config's parameters
_sGetBlock ; Try to load it.
Bne CNoSwitch ; If an error, then bail out
MOVE.L spResult(A0),A5 ; get pointer to it
;
; Look into the vidparams and see if we can support the current mode. If not,
; return an error with the max mode we can support.
;
; Get the current mode and see if our new resolution can support it, then return the
; zero-based video mode into D1
Clr.w D0 ; make sure byte is cleared
Move.b cvpMaxGraphMode(A5),D0 ; Read the max value for this configuration.
Cmp.w saveMode(A3),D0 ; Is our max mode greather than or equal
Bhs.s @ModeIsOK ; the current mode, if so, then go on
Move.b d0,d1 ; save our max mode
Move.l a5,a0
_DisposPtr
Move.b d1,d0 ; save our max mode
Andi.l #$000000FF,d0 ; make the return status be the max mode
Bra CSwitchBadMode ; return with D0 = max mode for the selected spID
@ModeIsOK
Clr.w D0 ; make sure byte is cleared <LW19>
Move.b cvpMaxVidInMode(A5),D0 ; Read the max value for this configuration. <LW19>
Subi.w #FirstVidMode,D0 ; make it zero based <LW19>
Cmpi.w #3,d0 ; Is the maximum video-in 8bpp <LW19>
bne.s @VidInOK ; nope, so no danger here <LW19>
Cmp.w #16,saveVidInMode(A3) ; Is our current vid in mode 16bpp <LW19>
bne.s @VidInOK ; nope, so we are in gray and going to a gray only display <LW19>
Move.l a5,a0 ; Get our pointer <LW19>
_DisposPtr ; <LW19>
Move.l #8,d0 ; report back our max vid-in mode <LW19>
Bra CSwitchBadMode ; return with D0 = max mode for the selected spID <LW19>
@VidInOK ; OK, VidMode and VidInMode are OK, so load the new spID <LW19>
; Delete the Current spID
Move.b saveSlotId(A3),spID(A0) ; Get the slotID
Clr.b spSlot(A0) ; Look at slot 0
Clr.b spExtDev(A0) ; no external devices.
_SDeleteSRTRec
Bne CNoSwitch ; If an error, then bail out
; Is the new s-resource already in the slot resource table? <LW17> #1084628
; Try to enable it, and if we get an error, then it wasn't in the table, so we need to insert it <LW17> #1084628
; <LW17> #1084628
Move.b D2,spID(A0) ; Get the spID that is in D2 <LW17> #1084628
Clr.b spSlot(A0) ; Look at slot 0 <LW17> #1084628
Clr.b spExtDev(A0) ; no external devices. <LW17> #1084628
Clr.l spParamData(A0) ; we want it enabled <LW17> #1084628
_SetSRsrcState ; <LW17> #1084628
Bne.s @InsertspID ; If no error, then get the base <LW17> #1084628
; <LW17> #1084628
; Delete the sRsrc so that we can insert it and the DCE fields get updated appropriately <LW17> #1084628
; <LW17> #1084628
_SDeleteSRTRec ; <LW17> #1084628
Bne CNoSwitch ; If an error, then bail out <LW17> #1084628
; <LW17> #1084628
; Insert the new s-resource, enabled ; <LW17> #1084628
@InsertspID ; <LW17> #1084628
Clr.l spsPointer(A0) ; spsPointer needs to be nil
Move.b D2,spID(A0) ; Get the spID that is in D2
Move.w dCtlRefNum(A1),spRefNum(A0) ; Get the driver's ref num so DCE gets updated.
Clr.l spParamData(A0) ; we want it enabled
_InsertSRTRec ; do it.
Bne CNoSwitch ; If an error, then bail out
; Load the "new" base address
_sFindDevBase ; Get the base address for this spID
Bne CNoSwitch ; If an error, then bail out
Move.l spResult(A0),D3 ; Move the base address.
Move.l D3,saveBaseAddr(A3) ; save our new base address
Lsr.l #5,D3 ; Normalize it for Civic
Andi.l #$FF,D3 ; Only 8 bits are valid
; Get the new offset and mode where it happens
Move.w #SixthVidMode,D1 ; Start at 32bpp
@LookForOffset
Move.b dCtlSlot(A1),spSlot(A0) ; Look at this slot
Clr.b spExtDev(A0) ; and no ExtDev
Move.b dCtlSlotID(A1),spID(A0) ; Put spID into spBlock.
_SRsrcInfo
Bne CNoSwitch ; If failed, quit.
Move.b D1,spID(A0) ; Look for this mode
_SFindStruct
Beq.s @ModeExists ; If noErr, then get block
Cmp.w #-330,D0 ; Did we get a smBadRefID
Bne CNoSwitch ; No, then quit.
Subi.w #1,D1 ; Look for next lower mode
bra.s @LookForOffset ;
@ModeExists
Move.b #mVidParams,spID(A0) ; Look for the video-parameters block
_SGetBlock
Bne CNoSwitch ; If failed, quit.
Move.l spResult(A0),a4 ; save the pointer to the block
Move.L vpBaseOffset(A4),d0 ; Get Offset
Beq.s @GotOffset ; If zero, then we have our offset stored in privates
Move.l d0,saveBaseAddrOffset(A3) ; Store non-zero offset in our privates
DBRA d1,@LookForOffset ; look at next lower mode
@GotOffset
Addi.w #1,d1 ; Adjust mode that has the non-zero offset
move.w d1, saveNewBaseMode(A3) ; and save it in our privates
; Release our spBlock
Adda #spBlockSize,Sp ; Clean up the stack.
; Save current spID in our globals, so that we can restore it when they switch from Composite to RGB
Move.l saveVidPtr(A3),A0 ; Get a Pointer to our current vidparams
_DisposPtr ; and dispose of it so we can load the new one
Move.l A5,saveVidPtr(A3) ; save it our globals
Move.l A5,A4 ; and in our scratch register
Move.b D2,saveSlotID(A3) ; save the new slot ID
; Now do the same code that primary init does in setting up video
Jsr CivicChangeHardware ; Reprogram Civic
MOVEM.L (SP)+,A0-A7/D1-D7 ; restore registers
Clr.l D0 ; return good status
CSwitchExit
RTS ; go say we didn't have any errors
CSwitchBadMode
Adda #spBlockSize,Sp ; Clean up the stack's spBlock;
MOVEM.L (SP)+,A0-A7/D1-D7 ; restore registers
Bra.s CSwitchExit ; and return.
CNoSwitch
Adda #spBlockSize,Sp ; Clean up the stack's spBlock;
MOVEM.L (SP)+,A0-A7/D1-D7 ; restore registers
Moveq.l #-1,D0 ; return bad status.
Bra.s CSwitchExit ; and return.
;---------------------------------------------------------------------
;
;
;---------------------------------------------------------------------
CivicChangeHardware
Move.w Sr,-(Sp) ; Save current interrupt level
Bsr CivicWaitVSync ; Wait for the next VBL.
dWrite_Civic #0,#Enable ; Disable Casio (the timing generator).
Move.l saveCivicBase(A3),A0 ; Point to the base of Civic.
; Set up to generate a stable raster.
;
dWrite_Civic #0,#ConvEnb ; Clear convolution before selecting progressive/interlaced display.
Move.b cvpFlags(A4),D2 ; Pick up the Video-in parameter parameter.
beq.s @NoVideoIn ; We don't want video-in enabled.
dWrite_Civic #0,#BusSize ; We do here, so program Civic and
Bra.s @SetupScanCtl ; and do the Scan Ctl stuff.
@NoVideoIn
dWrite_Civic #1,#BusSize ; We don't have video-in here, so program Civic and
@SetupScanCtl
Move.b cvpScanCtl(A4),D2 ; Pick up the ScanCtl parameter.
dWrite_Civic D2,#ScanCtl ; Write it out.
Move.b cvpConvEnb(A4),D2 ; Pick up the ConvEnb parameter.
dWrite_Civic D2,#ConvEnb ; Write it out.
Move.l #Endeavor,A0 ; Point to the VidClk.
;
; determine is we have a Clifton or Endeavor by writing to Endeavor M and reading it back
Cmp.b #BoxCentris660AV,saveBoxFlag(A3) ; Do we have a Tempest25 <SM18>
beq.s @DoClifton ; <09>yes, program Clifton
Cmp.b #BoxTempest33,saveBoxFlag(A3) ; Do we have a Tempest33
beq.s @DoClifton ; <09>yes, program Clifton
Move.b cvpEndeavorClk(A4),D0 ; Get the input clock source.
Bne.s @Use17MHz ; If one, use the 17MHz clock.
Moveq.l #0,D0 ; Set up to select the 14MHz clock.
Bra.s @SelClk ;
@Use17MHz Moveq.l #-1,D0 ; Set up to select the 17MHz clock.
@SelClk Move.l saveYMCABaseAddr(A3),A5 ; Otherwise, get a pointer to MMC.
Move.l D0,MMC_ClockSelect(A5) ; Select the desired input clock.
Clr.b EndeavorClk(A0) ; Always select Clk A.
Move.b cvpEndeavorM(A4),EndeavorM(A0) ; Program M.
Move.b cvpEndeavorN(A4),EndeavorN(A0) ; Program N.
bra.s @ProgramCivic
@DoClifton
Move.l A4,-(Sp) ; Save our scratch address <LW17> #PUMA
Bsr IsItPUMA ; Test to see if it's a PUMA ( if CC <20> 0, then Clifton) <LW17> #PUMA
Bne.s @ItsClifton ; It's a Clifton <LW17> #PUMA
Adda.l #(cvpPumaW-cvpCliftonW),A4 ; Adjust our video parameters with the correct offset <LW17> #PUMA
@ItsClifton ; <LW17> #PUMA
Move.b cvpCliftonClk(A4),D0 ; Get the input clock source.
Bne.s @Use17MHz2 ; If one, use the 17MHz clock.
Moveq.l #0,D0 ; Set up to select the 14MHz clock.
Bra.s @SelClk2 ;
@Use17MHz2 Moveq.l #-1,D0 ; Set up to select the 14MHz clock.
@SelClk2 Move.l saveYMCABaseAddr(A3),A5 ; Otherwise, get a pointer to MMC.
Move.l D0,MMC_ClockSelect(A5) ; Select the desired input clock.
; Writes to Clifton:
; D0: Contains the word written out, with %000000? (with ? being the bit for Clifton)
; D1: Contains the bits we want to serially write out
; D2: Contains the loop counter for all the bits
;
; Load the Clifton Control register to enable the MUX and the PROGram register
move.l #ControlWordSize-1,D2 ; Get the loop counter
move.l #LoadCliftonControl,D1 ; Enable MuxRef/Enable PROG Register
@LoadPROG
Move.l #1,D0 ; Set up the mask for the bit
And.l D1,D0 ; Transfer the first bit to D0
Move.b D0,EndeavorM(A0) ; write the bit out to Clifton
lsr.l #1,D1 ; get the next bit
Dbra D2,@LoadPROG ; <20>for the whole word
; Load the Frequency register
move.b cvpCliftonWSize(A4),D2 ; Get the size of the W Parameter
sub.b #1,D2 ; adjust loop # for dbra
extb.l D2 ; and make byte a long
move.l cvpCliftonW(A4),D1 ; And the W parameter
@LoadFreq
Move.l #1,D0 ; Set up the mask for the bit
And.l D1,D0 ; Transfer the first bit to D0
Move.b D0,EndeavorM(A0) ; write the bit out to Clifton
lsr.l #1,D1 ; get the next bit
Dbra D2,@LoadFreq ; <20>for the whole frequency
; Load the Clifton Control register to keep MUXREF enabled and disable loading of PROG Register
move.l #ControlWordSize-1,D2 ; Get the loop counter
move.l #LoadCliftonProgram,D1 ; Enable MuxRef/disable PROG Register
@DisablePROG
Move.l #1,D0 ; Set up the mask for the bit
And.l D1,D0 ; Transfer the first bit to D0
Move.b D0,EndeavorM(A0) ; write the bit out to Clifton
lsr.l #1,D1 ; get the next bit
Dbra D2,@DisablePROG ; <20>for the whole word
; Wait for 5 msec to enable the new frequency to get stable
jsr Wait5ms ; trashes D0
; Load the Clifton Control register to disable MUXREF and PROGram register.
move.l #ControlWordSize-1,D2 ; Get the loop counter
move.l #LoadCliftonMuxRef,D1 ; Disable MUXREF/disable PROG Register
@DisableMUXREF
Move.l #1,D0 ; Set up the mask for the bit
And.l D1,D0 ; Transfer the first bit to D0
Move.b D0,EndeavorM(A0) ; write the bit out to Clifton
lsr.l #1,D1 ; get the next bit
Dbra D2,@DisableMUXREF ; <20>for the whole word
Movea.l (Sp)+,A4 ; restore our address <LW17> #PUMA
@ProgramCivic
dWrite_Civic #0,#VDCEnb ; Disable VDC interrupts.
dWrite_Civic #1,#VDCClk ; Disable VDC clock.
dWrite_Civic cvpVHLine(A4),#VHLine ; Set up the vertical params.
dWrite_Civic cvpVSync(A4),#VSync ;
dWrite_Civic cvpVBPEq(A4),#VBPEq ;
dWrite_Civic cvpVBP(A4),#VBP ;
dWrite_Civic cvpVAL(A4),#VAL ;
dWrite_Civic cvpVFP(A4),#VFP ;
dWrite_Civic cvpVFPEq(A4),#VFPEq ;
dWrite_Civic cvpBusSize(A4),#BusSize ; Write the BusSize parameter
dWrite_Civic cvpHSerr(A4),#HSerr ; Write out the horizontal timing parameters.
dWrite_Civic cvpHlfLn(A4),#HlfLn ;
dWrite_Civic cvpHEq(A4),#HEq ;
dWrite_Civic cvpHSP(A4),#HSP ;
dWrite_Civic cvpHBWay(A4),#HBWay ;
dWrite_Civic cvpHAL(A4),#HAL ;
dWrite_Civic cvpHFP(A4),#HFP ;
dWrite_Civic cvpHPix(A4),#HPix ;
dWrite_Civic #$FF0,#VInHal ; For now, set the video-in params<6D>
dWrite_Civic #$000,#VInHFPD ; <09>way into the blanking period.
dWrite_Civic #$FF8,#VInHFP ;
dWrite_Civic #$FF0,#VInVal ;
dWrite_Civic #$FF8,#VInVFP ;
dWrite_Civic cvpGSCDivide(A4),#GSCDivide ; Set the framebuffer params for this depth.
dWrite_Civic cvpRowWords(A4),#RowWords ;
dWrite_Civic D3,#BaseAddr ;
dWrite_Civic cvpAdjF1(A4),#AdjF1 ;
dWrite_Civic cvpAdjF2(A4),#AdjF2 ;
dWrite_Civic cvpPipeD(A4),#PipeD ;
; Switch the CLUT/DAC<41>s depth.
;
Move.l saveVDACBase(A3), A5 ; Get the a pointer to CLUT/DAC
Move.w cvpSebastPCBR(A4),D0 ; Get the PCBR value
Move.b D0,SebastPCBR(A5) ; Change the depth.
; Now, reset the timing generator.
;
dWrite_Civic #1,#Enable ; Enable Casio (the timing generator).
Jsr CivicReset ; Reset Civic (Needs A3 = vidprivates, trashes A0)
Move.w (Sp)+,Sr ; Restore previous interrupt level.
Rts
ENDWITH
;---------------------------------------------------------------------
;
; SetResolution gets the video driver and the framebuffer controller
; set up for being switched to a different resolution.
;
; D1 containts the spID to the resolution (mode) to enable.
; A1 = AuxDCE POINTER
; A2 = parameter block pointer
; A3 = dCtlStorage pointer
;
; Preserves all registers
;
;---------------------------------------------------------------------
CivicSetResolution
With CivicVidParams,SpBlock,VpBlock
Movem.l D0-D1/A0/A4-A6,-(Sp) ; Save work registers.
Move.b dCtlSlotId(A1),D0 ; Remember which sRsrc to disable.
Move.b D1,dCtlSlotId(A1) ; Remember which sRsrc to enable.
; Do the Slot Manager changes<65>
;
Suba.w #spBlockSize,Sp ; Allocate a slot parameter block on the stack.
Move.l Sp,A0 ; Point to it with A0.
Clr.b spSlot(A0) ; Say that we<77>re Slot $0.
Clr.b spExtDev(A0) ; Don<6F>t ask why, just clear this guy.
Move.b D0,spID(A0) ; Write out the spID of the sRsrc.
_SRsrcInfo ; Update our SpBlock for SUpdateSRT call below.
Move.l #1,spParamData(A0) ; Say that we want it disabled.
_SetSRsrcState ; Do it.
Move.b dCtlSlotId(A1),spID(A0) ; Write out the spID of the sRsrc.
Move.l #0,spParamData(A0) ; Say that we want it enabled.
_SetSRsrcState ; Do it.
Bne CNoSwitch ; If an error, then bail out
_SUpdateSRT ; Tell Slot Manager to update itself (it should really know, but it does not).
; Load the "new" base address
_sFindDevBase ; Get the base address for this spID
Bne CNoSwitch ; If an error, then bail out
Move.l spResult(A0),D3 ; Move the base address.
Move.l D3,saveBaseAddr(A3) ; save our new base address
Lsr.l #5,D3 ; Normalize it for Civic
Andi.l #$FF,D3 ; Only 8 bits are valid
; Get the new offset and mode where it happens
@LookForOffset
Move.b dCtlSlot(A1),spSlot(A0) ; Look at this slot
Clr.b spExtDev(A0) ; and no ExtDev
Move.b dCtlSlotID(A1),spID(A0) ; Put spID into spBlock.
_SRsrcInfo
Bne CNoSwitch ; If failed, quit.
Move.b D1,spID(A0) ; Look for this mode
_SFindStruct
Beq.s @ModeExists ; If noErr, then get block
Cmp.w #-330,D0 ; Did we get a smBadRefID
Bne CNoSwitch ; No, then quit.
Subi.w #1,D1 ; Look for next lower mode
bra.s @LookForOffset ;
@ModeExists
Move.b #mVidParams,spID(A0) ; Look for the video-parameters block
_SGetBlock
Bne CNoSwitch ; If failed, quit.
Move.l spResult(A0),a4 ; save the pointer to the block
Move.L vpBaseOffset(A4),d0 ; Get Offset
Beq.s @GotOffset ; If zero, then we have our offset stored in privates
Move.l d0,saveBaseAddrOffset(A3) ; Store non-zero offset in our privates
DBRA d1,@LookForOffset ; look at next lower mode
@GotOffset
Addi.w #1,d1 ; Adjust mode that has the non-zero offset
move.w d1, saveNewBaseMode(A3) ; and save it in our privates
; Load the <20>new<65> video hardware setup block<63>
;
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.
Move.b #sVidParmDir,spID(A0) ; Look for the video parameters dir.
_sFindStruct ; Load it.
Move.b dCtlSlotId(A1),spID(A0) ; Look in the directory for this config's parameters.
_sGetBlock ; Load it.
Move.l spResult(A0),-(Sp) ; Save the new privates.
Movea.l saveVidPtr(A3),A0 ; Point to the old privates.
_DisposPtr ; Dispose them.
Move.l (Sp)+,saveVidPtr(A3) ; Start using the new ones.
Adda.w #spBlockSize,Sp ; De-allocate the slot parameter block.
; Change the hardware<72>
;
Movea.l saveVidPtr(A3),A4 ; Point to vidParams.
Jsr CivicChangeHardware ; Reprogram Civic
Movem.l (Sp)+,D0-D1/A0/A4-A6 ; Restore the work register.
Rts
Endwith
CivicSetCompOut
;---------------------------------------------------------------------
;
; Sets/Clears the PRAM flag that tells primary init to boot off the composite
; out port when no monitor is detected on the DB15 port.
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;
; Bit 0: if 0, set CompOutFlag, if 1, ClearCompOut.
;---------------------------------------------------------------------
WITH spBlock,CivicVidPrivates,SP_Params
;
; Set up a slot parameter block on the stack.
;
Move.w gFlags(A3),scratch(A3) ; save our flags
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 flag are in SP_FLAGS, which are in VendorUse5 byte.
;
SUBA #SizesPRAMRec,SP ; allocate block for pRAM record
MOVE.L SP,spResult(A0) ; point to it
_sReadPRAMRec ; read it
Bne CSetVinBadExit ; should not fail, but if so...
Move.b SP_Flags(SP),D0 ; Get the current flags
Move.b csMode(A2),D1 ; get boolean
Beq.s @SetFlag ; if 0, it means to set the flag
Bclr #spCompOut,D0 ; else, it means disable, so clear flag
Bra.s @WriteItOut ; and write it out
@SetFlag
Bset #spCompOut,D0 ; Set it, which means to enable
@WriteItOut
Move.b D0,SP_Flags(SP) ; write out the sp_flags byte
MOVE.L SP,spsPointer(A0) ; set up parameter block
_sPutPRAMRec ; write the new record out
Bne CSetVinBadExit ; any errors?
Adda #SizesPRAMRec+spBlockSize,SP ; Deallocate buffer and
Bra CivicCtlGood ; return good result.
CSetVinBadExit
Move.w scratch(a3),gflags(a3) ; Restore our gflags
Adda #SizesPRAMRec+spBlockSize,SP ; Deallocate buffer and
Bra CivicCtlBad ; return bad result.
CivicSwitchMode
;---------------------------------------------------------------------
;
; When driving a multiscan-capable display, this routine allows
; the various modes to swapped out both from a low-level software
; (i.e., Driver & Slot Manager) and hardware point of view.
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
With CivicVidPrivates,SpBlock,VDPageInfo
; Check to see if we even need to be here or not<6F>
;
Cmpi.w #indexedSenseMSB1,saveMonID(A3) ; If we<77>re not in the multiscan mode,
Bne CivicCtlBad ; then it's not safe to be here.
; Check to see if we can even do what was requested<65>
;
Tst.w csPage(A2) ; If requested page is not zero,
Bne.s CivicCtlBad ; then we can<61>t help <20>em.
Move.l csData(A2),D2 ; Get the requested SpID.
Moveq #0,D0 ; Clear hi-half of mode/depth register.
Tst.w saveSizeVRAM(A3) ; Load the correct table depending on how much VRAM we have
Bne.s @2MegTable ; If 0, then 1 meg
Lea SwitchTable1Meg,A0 ; Point to the SwitchMode1Meg table.
Bra.s @ChkLoop ; start checking
@2MegTable Lea SwitchTable2Meg,A0 ; get the 2 meg table
@ChkLoop Move.b (A0)+,D1 ; If we<77>re at the end of the table,
Beq CivicCtlBad ; then something<6E>s wrong.
Move.b (A0)+,D0 ; Get the max mode for this config.
Cmp.b D1,D2 ; If this is not the requested mode,
Bne.s @ChkLoop ; then keep looping.
; Make sure the new depth is okay for switching<6E>
;
Move.w csMode(A2),D1 ; Get the requested mode (depth).
Subi.w #FirstVidMode,D1 ; Make it indexed.
Subi.w #FirstVidMode,D0 ; Make the new max mode indexed.
Cmp.w D0,D1 ; If the current mode is > new max mode,
Bgt CivicCtlBad ; then punt.
Move.w D1,D0 ; Save the indexed mode.
; Switch to the new resolution<6F>
;
Cmp.b dCtlSlotID(A1),D2 ; If we<77>re already in the requested resolution,
Beq CivicSetVidModeGuts ; then go try the depth switch.
Move.b D2,D1 ; Set up to do the resolution switch.
Bsr CivicSetResolution ; Switch to the new resolution.
Move.w D0,D1 ; Set up to do the depth switch.
Bra CivicSetVidModeGuts ; Switch to the new depth.
Endwith
CivicSetSync
;---------------------------------------------------------------------
;
; Enable (csMode = 0) or disable (csMode = 1) the DB15 Sync
;
; This routine will disable the sync lines going to the DB15 connector
; so that "green-aware" monitors can go into power-saving mode. If we
; are not driving an monitor out of that port, it will return an error.
;
; Note: It might be that in the future, there will be several levels of
; power-saving; Dropping CSYNC- will be one, HSYNC-, another, and
; both syncs another. Since Civic can only drop both, I will ignore
; a second undefined parameter.
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
Move.w gFlags(A3),D0 ; get our flags
Btst #CompositeSyncOn,D0 ; are we driving out of Composite
Bne CivicCtlBad ; yes, then exit with bad mode
moveq #1,D0 ; Set up for CivicWrite
MOVE.b csMode(A2),D1 ; get the mode
Bne.s @WriteToSyncs ; To disable, write a 1 to CivicSyncEnable
Clr.l D0 ; else, write a 0 to enable
@WriteToSyncs
Move.l saveCivicBase(A3),A0 ; Get the Base Address for Civic
Move.l D0,Civic_SyncClr(A0) ; And disable or enable the sycns
BRA CivicStatGood ; => return no 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
*
**********************************************************************
CivicVidClose
WITH CivicVidPrivates
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
MOVE.L (A3),A3 ;
BSR CivicDisableVGuts ; call utility to deactivate interrupts
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 save2ndVidPtr(A3),D0 ; Get pointer to video parameters block for RGB
Beq.s @DisposePrivate ; if nil, then don't need to dispose
_DisposPtr ; and dispose of it.
@DisposePrivate
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
* ($0A) ????
* ($0B) GetSyncs
*
* The following calls are Civic-specific:
*
* ($83) GetAltSense
* ($85) GetCompOut <LW14>
* ($87) GetRGBByPass
* ($88) GetVideoIn
* ($89) GetVidInMode
* ($8A) GetVidInRect
* ($8B) CivicGetCompCapabilities
*
* 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
*
**********************************************************************
CivicVidStatus
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),A3 ;
MOVE.W csCode(A0),D0 ; get routine selector
Cmp.w #$80,D0 ; Is it a private control call
Bhs.s PrivateStatCall ; Go decode it
CMP.W #$0B,D0 ; IF csCode NOT IN [0..9] THEN
BHI.S CivicStatBad ; Error, csCode out of bounds.
MOVE.W CivicStatJumpTbl(PC,D0.W*2),D0 ;Get the relative offset to the routine.
JMP CivicStatJumpTbl(PC,D0.W) ;GOTO the proper routine.
CivicStatJumpTbl
DC.W CivicStatBad-CivicStatJumpTbl ; $00 => Error
DC.W CivicStatBad-CivicStatJumpTbl ; $01 => Error
DC.W CivicGetMode-CivicStatJumpTbl ; $02 => GetMode
DC.W CivicGetEntries-CivicStatJumpTbl ; $03 => GetEntries
DC.W CivicGetPage-CivicStatJumpTbl ; $04 => GetPage
DC.W CivicGetPageBase-CivicStatJumpTbl ; $05 => GetPageBase
DC.W CivicGetGray-CivicStatJumpTbl ; $06 => GetGray
DC.W CivicGetInterrupt-CivicStatJumpTbl ; $07 => GetInterrupt
DC.W CivicGetGamma-CivicStatJumpTbl ; $08 => GetGamma
DC.W CivicGetDefaultMode-CivicStatJumpTbl; $09 => GetDefaultMode
DC.W CivicStatBad-CivicStatJumpTbl ; $0A => Unused
DC.W CivicGetSyncs-CivicStatJumpTbl ; $0B => GetSyncs
PrivateStatCall
CMP.W #$8B,D0 ; IF csCode NOT IN [$80..$8B] THEN
BHI.S CivicStatBad ; Error, csCode out of bounds.
Subi.w #$80,D0 ; Normalize the code
MOVE.W PrivStatJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine.
JMP PrivStatJumpTbl(PC,D0.W) ; GOTO the proper routine.
PrivStatJumpTbl
DC.W CivicStatBad-PrivStatJumpTbl ; $80 => Unused
DC.W CivicStatBad-PrivStatJumpTbl ; $81 => Unused
DC.W CivicStatBad-PrivStatJumpTbl ; $82 => Unused
DC.W CivicGetAltSense-PrivStatJumpTbl ; $83 => CivicGetAltSense
DC.W CivicStatBad-PrivStatJumpTbl ; $84 => Unused (cscLowPower)
DC.W CivicGetCompOut-PrivStatJumpTbl ; $85 => CivicGetCompOut
DC.W CivicStatBad-PrivStatJumpTbl ; $86 => Unused
DC.W CivicGetRGBByPass-PrivStatJumpTbl ; $87 => CivicGetRGBByPass
DC.W CivicGetVideoIn-PrivStatJumpTbl ; $88 => GetVideoIn
DC.W CivicGetVidInMode-PrivStatJumpTbl ; $89 => GetVidInMode
DC.W CivicGetVidInRect-PrivStatJumpTbl ; $8A => GetVidInRect
DC.W CivicGetCompCapabilities-PrivStatJumpTbl ; $8B => CivicGetCompCapabilities
CivicStatBad MOVEQ #statusErr,D0 ; else say we don't do this one
BRA.S CivicStatDone ; and return
CivicStatGood MOVEQ #noErr,D0 ; return no error
CivicStatDone MOVEM.L (SP)+,A0/A1 ; Restore exit registers.
BRA CivicExitDrvr
CivicGetMode
;---------------------------------------------------------------------
;
; Return the current mode
;
; Inputs : A2 = pointer to csParams
; A3 = pointer to private storage
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVE.W saveMode(A3),csMode(A2) ; return the mode
Clr.w csPage(A2) ; return the page number (always 0)
Move.l saveBaseAddr(A3),csBaseAddr(A2) ; Return the screen baseAddr.
BRA.S CivicStatGood ; => return no error
ENDWITH
CivicGetEntries
;---------------------------------------------------------------------
;
; Read the current contents of the CLUT. These values were gamma corrected
; when they were set (by SetEntries), 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
;
;---------------------------------------------------------------------
With CivicCLUTRec
Movem.l D4-D7,-(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.
Move.l D0,(Sp) ; Save the non-zero pointer.
Move.w saveMode(A3),D1 ; Get the current video mode.
Sub.w #FirstVidMode,D1 ; Convert it to an index.
Moveq #0,D3 ; clear all of D3 for .w compare.
Lea CivicCLUTTbl,A0 ; Point to the table of CLUT data.
Lea (A0,D1*CivicCLUTSize),A0 ; Point to the right entry.
Move.b ccRange(A0),D3 ; Get the CLUT range.
Move.w csCount(A2),D4 ; Get the number of entries to fill,
Bmi @GEErr ; and hike if it<69>s out of range.
Cmp.w D3,D4 ; If D4-D3 > 0 (count > entries),
Bhi @GEErr ; then hike.
Move.w D4,D2 ; Otherwise, copy the count.
Move.b ccStart(A0),D4 ; Save the CLUT starting position.
Move.w ccSkip(A0),D5 ; Save the inter-entry skip factor.
Move.w D2,D6 ; Remember the csCount.
Move.l #colorSpecSize,D7 ; Save the size of each color spec entry
Move.w csStart(A2),D0 ; Get the start number to range check.
Addq.w #2,D0 ; If csStart < -2, then it<69>s out of
Bmi @GEErr ; range.
Cmp.w #indexEntries,csStart(A2) ; If table accesses are to be indexed (csStart = -1),
Beq.s @GECom ; then go on.
Cmp.w #alphaEntries,csStart(A2) ; Do we have alpha entries (XColorSpec) (always indexed, csStart = -2)
Bne.s @CycleSeq ; then go on.
Move.l #xColorSpecSize,D7 ; Use D7 to contain the size of each entry
Bra.s @GECom ; and go on
@CycleSeq
Move.w D2,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<65>s data. But all the previous Apple video drivers
; have done the same thing here, so we<77>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
Move.l (Sp)+,A0 ; Get/restore ptr to csTable.
Move.l saveVDACBase(A3),A2 ; Get ACDC base address.
Move.b SebastPCBR(A2),D0 ; Make sure we're writing to the Graphics CLUT
Bclr #fCivicVidInCLUT,D0 ; by zeroing the CLUT select bit in the PCBR
Move.b D0, SebastPCBR(A2) ; and write it back out.
Adda.w #SebastDataReg,A2 ; Add offset to Clut read register.
Move.w Sr,-(Sp) ; Save current interrupt level
Bsr CivicWaitVSync ; Wait for VBL (Preserves A0/D0).
@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.
Mulu.w D5,D1 ; Multiply index by skip value.
Add.b D4,D1 ; Add in the starting posistion.
Move.b D1,SebastAddrReg-SebastDataReg(A2) ; Tell the Clut where to read from.
Move.b (A2),D1 ; Get Red:
Move.b D1,rgb+red(A0) ; --> $rrXX
Move.b D1,rgb+red+1(A0) ; --> $rrrr
Move.b (A2),D1 ; Get Green:
Move.b D1,rgb+green(A0) ; --> $ggXX
Move.b D1,rgb+green+1(A0) ; --> $gggg
Move.b (A2),D1 ; Get Blue:
Move.b D1,rgb+blue(A0) ; --> $bbXX
Move.b D1,rgb+blue+1(A0) ; --> $bbbb
Cmp.l #xColorSpecSize,D7 ; Test for XColorSpec
Bne.s @DontReadAlpha ; if none then just skip alpha
Move.b (A2),D1 ; Get Alpha:
Move.b D1,xalpha(A0) ; --> $aaXX
Move.b D1,xalpha+1(A0) ; --> $aaaa
Bra.s @Until ; Go loop
@DontReadAlpha
Tst.b (A2) ; Skip Alpha.
@Until Add.l D7,A0 ; Point to next entry ColorTable.
Dbra D6,@Repeat
Move.w (Sp)+,Sr ; Restore previous interrupt level.
Movem.l (Sp)+,D4-D7 ; Restore work registers.
Bra CivicStatGood ; Return noError.
@GEErr Tst.l (Sp)+ ; Clean up stack.
Movem.l (Sp)+,D4-D7 ; Restore work registers.
Bra CivicStatBad ; Return statError.
CivicGetPage
;---------------------------------------------------------------------
;
; 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 CivicVidPrivates
MOVE csMode(A2),D1 ; get the mode
MOVE D1,D2 ; keep a copy
BSR CivicChkMode ; is this mode OK?
BNE CivicStatBad ; => not a valid mode
MOVE.W #1,csPage(A2) ; return page count
BRA CivicStatGood ; => return no error
ENDWITH
CivicGetPageBase
;---------------------------------------------------------------------
;
; Return the base address for the specified page in the current mode
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
TST.W csPage(A2) ; are we returning page zero info?
BNE CivicStatBad ; only page 0 is valid
Move.l saveBaseAddr(A3),csBaseAddr(A2) ; Return the screen baseAddr.
BRA CivicStatGood ; => return no error
ENDWITH
CivicGetGray
;---------------------------------------------------------------------
;
; Return a boolean, set true if luminance mapping is on
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVEQ #0,D1 ; set up for BFEXTU
CivicGetFlagCom
BFEXTU GFlags(A3){D1:1},D0 ; get the state of flag
MOVE.B D0,csMode(A2) ; return value
BRA CivicStatGood ; => and return
ENDWITH
CivicGetInterrupt
;---------------------------------------------------------------------
;
; Return a boolean in csMode, set true if VBL interrupts are disabled
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVEQ #1,D1 ; set up BFEXTU to point at IntDisFlag
BRA.S CivicGetFlagCom ; and use common code
ENDWITH
CivicGetGamma
;---------------------------------------------------------------------
;
; Return the pointer to the current gamma table
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
MOVE.L saveGammaPtr(A3),csGTable(A2) ; return the pointer to the structure
BRA CivicStatGood ; and return a good result
ENDWITH
CivicGetDefaultMode
;---------------------------------------------------------------------
;
; 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,CivicVidPrivates,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 CivicStatGood ;
ENDWITH
CivicGetVideoIn
;---------------------------------------------------------------------
;
; Return the status on whether video-in is enabled or not
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
; csMode: 0 = video-in is enabled
; 1 = video-in is disabled
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
Btst #videoInEnb,GFlags(A3) ; Test our internal flags
Seq csMode(A2) ; If flag=0, video-in is disabled, so return true.
BRA CivicStatGood ;
ENDWITH
CivicGetVidInMode
;---------------------------------------------------------------------
;
; Return the VidIn Mode in the specified page, along with the video-in base address
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
WITH VDPageInfo
TST.W csPage(A2) ; are we returning page zero info?
BNE CivicStatBad ; only page 0 is valid
Move.l #vCivicVidInBase,csBaseAddr(A2) ; Return the video-in VRAM baseAddr.
Move.w saveVidInMode(A3),csMode(A2) ; Return the Video-In mode.
BRA CivicStatGood ; => return no error
ENDWITH
CivicGetVidInRect
;---------------------------------------------------------------------
;
; Return the VidInRect in the specified page, along with the video-in base address
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
WITH CivicVidPrivates, VDVidInRect
TST.W csPage(A2) ; are we returning page zero info?
BNE CivicStatBad ; only page 0 is valid
Move.l #vCivicVidInBase,csBaseAddr(A2) ; Return the video-in VRAM baseAddr.
Move.w currentTop(a3),(csRect+top)(A2) ; Return the top
Move.w currentLeft(a3),(csRect+left)(A2) ; Return the left
Move.w currentBottom(a3),(csRect+bottom)(A2) ; Return the bottom
Move.w currentRight(a3),(csRect+right)(A2) ; Return the right
BRA CivicStatGood ; => return no error
ENDWITH
CivicGetAltSense
;---------------------------------------------------------------------
;
; Returns the alternate senseID code that<61>s in use. It
; should be noted that we cannot disguish between PAL &
; NTSC monitors & encoder boxes once SetAltSense has
; been called (because both the monitor & box codes are
; mapped into the same indexedSense code).
;
;---------------------------------------------------------------------
With spBlock,CivicVidPrivates,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 @TryGF ; Nope, try GoldFish.
Move.b #extendedSensePAL,D0
Bra.s @WriteExtended
@TryGF Cmp.b #indexedSenseGF,D0 ; Is it the GoldFish code?
Bne.s @Try19 ; Nope, try 19<31>.
Move.b #extendedSenseGF,D0
Bra.s @WriteExtended
@Try19 Cmp.b #indexedSense19,D0 ; Is it the 19<31> 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 CivicStatGood ; go home.
Endwith
CivicGetRGBByPass
;---------------------------------------------------------------------
;
; Return the RGBBypass status in the csMode field
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
; The parameters are:
; csMode: (Byte): 0: If not driving out of composite, 1: if driving
; csStandard (Byte): 0: Driving PAL, 1: driving NTSC
; csConv (Byte): 0: Not using Apple Convolution, 1: Using Apple Convolution
;
;---------------------------------------------------------------------
WITH VDCompositeOut, CivicRecord
Move.w gFlags(A3),D0 ; Get our flags
Btst #CompositeSyncOn,D0 ; Look at whether we're driving composite
Beq.s @ClearMode ; If 0, then return bypass = 0
Move.b #1,csMode(A2) ; Else, return a 1
Bra.s @GetBypassType ; and exit
@ClearMode Clr.b csMode(A2) ; return 0
@GetBypassType Btst #NTSCTimingOn,D0 ; Look at the composite timing flag
Beq.s @SetPAL ; if 0, then it's PAL
Clr.b csStandard(A2) ; Clear the NTSC/PAL type
Bra.s @CheckConv ; check convolution
@SetPal Move.b #1,csStandard(A2) ; say it was PAL
@CheckConv Btst #ConvolutionON,D0 ; Look at the convolution flag
Beq.s @ClearConv ; if 0, then no convolution is going on
Move.b #1,csConv(A2) ; Set the convolution flag
Bra.s @theEnd ; exit
@ClearConv Clr.b csConv(A2) ; return with no convolution on
@theEnd BRA CivicStatGood ; => return no error
ENDWITH
CivicGetCompOut
;---------------------------------------------------------------------
;
; Read the cards composite out flag from the slot pRAM.
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
;---------------------------------------------------------------------
WITH spBlock,CivicVidPrivates,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_Flags(SP),D0 ; Get the current flags
Btst #spCompOut,D0 ; Is composite out enabled
Beq @NoComposite ; no,
Move.b #0,csMode(A2) ; if it is, return the inverse (i.e. 0)
Bra.s @ExitCompOut
@NoComposite
Move.b #1,csMode(A2) ; Say we're not driving composite
@ExitCompOut
ADDA #SizesPRAMRec+spBlockSize,SP ; release buffer
BRA CivicStatGood ;
ENDWITH
CivicGetCompCapabilities
;---------------------------------------------------------------------
;
; Returns information on the capabilities of the current video mode
;
; A1 = Ptr to AuxDCE
; A2 = Ptr to cs parameter record
; A3 = Ptr to private storage
;
; The parameters are:
; csMode: (Byte) containing the spID of the mode we want info on
; (If 0, then use the current one)
;
; csNTSCID: (Byte): returns the spID for NTSC for the current amount of VRAM
; csNTSCIDConv: (Byte): returns the spID for NTSC Convolution
; csPALID: (Byte): returns the spID for PAL for the current amount of VRAM
; csPALIDConv: (Byte): returns the spID for PAL Convolution
;
;---------------------------------------------------------------------
WITH VDInternalInfo
Move.b csMode(A2),D1 ; Get the desired spID
Bne.s @GoodSPID ; If 0, then use the current one
Move.b saveSlotId(A3),D1 ; Get the current ID.
@GoodSPID
SUBA #spBlockSize,SP ; make a slot parameter block
MOVE.L SP,A0 ; get pointer to block in A0
Clr.b spSlot(A0) ; Look at slot 0
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 @BadVidInMax ; If an error, then bail out
MOVE.B #sVidParmDir,spID(A0) ; look for the video parameters dir
_sFindStruct ; Try to load it.
Bne @BadVidInMax ; If an error, then bail out
MOVE.B d1,spID(A0) ; look in the directory for this config's parameters
_sGetBlock ; Try to load it.
Bne @BadVidInMax ; If an error, then bail out
MOVE.L spResult(A0),A0 ; get pointer to it (dispose it later)
Move.l a0,-(sp) ; save it for later disposal
Tst.b saveSizeVRAM(A3) ; set up to return the correct spID's depending on VRAM
Bne.s @2Meg
Move.b cvpNTSCid1Meg(A0),csNTSCID(A2) ; return the equivalent NTSC Id
Move.b cvpPALid1Meg(A0),csPALID(A2) ; return the equivalent PAL Id
Bra.s @1
@2Meg
Move.b cvpNTSCid2Meg(A0),csNTSCID(A2) ; return the equivalent NTSC Id
Move.b cvpPALid2Meg(A0),csPALID(A2) ; return the equivalent PAL Id
@1
Move.b cvpConvNTSCid(A0),csNTSCIDConv(A2) ; return the equivalent id for NTSC Convolution
Move.b cvpConvPALid(A0),csPALIDConv(A2) ; return the equivalent id for NTSC Convolution
Clr.l D0 ; We will move amount of VRAM here
Move.b (A0),csMode(A2) ; Return the maxMode
Move.l (Sp)+,A0 ; Get the pointer to vidparams
_DisposPtr ; and dispose of it
ADDA #spBlockSize,SP ; release the spBlock
BRA CivicStatGood ; => return no error
@BadVidInMax
ADDA #spBlockSize,SP ; release the spBlock
BRA CivicStatBad ; => return error
ENDWITH
CivicGetSyncs
;---------------------------------------------------------------------
;
; Return a boolean, set true if RGB Syncs are OFF
; Clear the 2nd byte, saying we don't support levels of power-saving.
;
;---------------------------------------------------------------------
WITH CivicVidPrivates
Move.l saveCivicBase(A3),A0 ; Get the Base Address for Civic
Move.l Civic_SyncClr(A0),D0 ; Get the status of the enable bits
Andi.l #$1,D0 ; and look at bit 0
SEQ csMode(A2) ; if bit is 0, RGB Syncs are OFF, return true
Clr.b csMode+1(A2) ; and the next byte for good measure.
BRA CivicStatGood ; => and return
ENDWITH
;---------------------------------------------------------------------
;
; Exit from Control or Status.
;
; A0 = Ptr to param block.
; A1 = Ptr to AuxDCE.
; D0 = error code.
;
;---------------------------------------------------------------------
CivicExitDrvr BTST #NoQueueBit,ioTrap(A0) ; no queue bit set?
BEQ.S CivicGoIODone ; => no, not immediate
RTS ; otherwise, it was an immediate call
CivicGoIODone MOVE.L JIODone,-(Sp) ; Get the IODone address,
Rts ; and go there.
;---------------------------------------------------------------------
; Utils
;---------------------------------------------------------------------
;---------------------------------------------------------------------
;
; GetCivicReg
;
; This routine takes an offset into the CivicRegTable as input and
; returns the address and width of the corresponding
; Civic register.
;
; -> D0: The offset into the CivicRegTable of the desired Civic register.
; <- D1: The width (1 to 12 bits) of the Civic regiser/data.
; <- A0: Pointer to base address of the Civic register to write.
;
; Trashes D0-D1/A0.
With CivicFrame,CivicEntry,CivicRecord
dGetCivicReg
Lea dCivicRegTable,A0 ; Point to the CivicRegTable.
@GetCWidth Move.w width(A0,D0),D1 ; Get the register width
Move.w offset(A0,D0),D0 ; Get the register offset.
Move.l saveCivicBase(A3),A0 ; Point A0 at Civic<69>s base address.
Adda.w D0,A0 ; Point to the desired register.
Rts
Endwith
;---------------------------------------------------------------------
;
; WriteCivic
;
; Civic registers are accessed 1 bit a time using D[0] of the processor
; bus. However, most of the registers are more than 1 bit wide.
; So, this routine takes as input the base address of the Civic
; register to write, the data to write out, and how wide the
; register/data is.
;
; Note: Civic Registers are ONLY accessible in 32-bit addressing
; mode.
;
; -> D0: The data to write out.
; -> D1: The width (1 to 12 bits) of the Civic regiser/data.
; -> A0: Pointer to base address of the Civic register to write.
;
; Trashes D0-D1/A0.
dWriteCivic
Subq #1,D1 ; Set up for Dbra loop.
@WriteABit Move.l D0,(A0)+ ; Write the current bit out.
Lsr.l #1,D0 ; Set up for next write.
Dbra D1,@WriteABit ; Loop until done.
Rts ; Return home.
;---------------------------------------------------------------------
;
; ReadCivic
;
; This routine complements the WriteCivic routine. It takes as
; input the Civic register to read and how wide the
; register is. It returns the register<65>s value.
;
; Note: Civic Registers are ONLY accessible in 32-bit addressing
; mode.
;
; <- D0: The Civic register<65>s data.
; -> D1: The width (1 to 12 bits) of the Civic regiser/data.
; -> A0: Pointer to base address of the Civic register to write.
;
; Trashes D1/A0.
dReadCivic
Move.l D2,-(Sp) ; Save our non-trashable work register.
Move.w D1,D0 ; Copy the register width.
Lsl.w #2,D0 ; Multiply it by four.
Adda.w D0,A0 ; Point to the last bit.
Subq #1,D1 ; Set up for Dbra loop.
Moveq #0,D0 ; Set up return value.
@ReadABit Lsl.w #1,D0 ; Set up for this read.
Move.l -(A0),D2 ; Get the current bit.
Bfins D2,D0{31,1} ; Save it.
Dbra D1,@ReadABit ; Loop until done.
Move.l (Sp)+,D2 ; Restore our work register.
Rts ; And return home.
;---------------------------------------------------------------------
;
; 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 CivicVidPrivates,CivicVidParams
CivicChkMode
Movem.l A0/D0,-(Sp) ; Save work registers.
Sub.w #FirstVidMode,D1 ; Make mode zero-based.
Blt.s @ModeBad ; If the passed-in mode is < 0,
; then punt.
Move.l saveVidPtr(A3),A0 ; Get a pointer to the video params.
Clr.l D0 ; We will move amount of VRAM here
Move.b cvpMaxGraphMode(A0),D0 ; Read the max value for this configuration.
Sub.w #FirstVidMode,D0 ; Make the max mode zero-based.
Cmp.w D0,D1 ; If the passed-in mode is > max mode,
Bgt.s @ModeBad ; then punt.
Cmp.w D1,D1 ; Set Eq when okay.
@ModeBad Movem.l (Sp)+,A0/D0 ; Restore work registers.
Rts
Endwith
;---------------------------------------------------------------------
;
; Wait for vertical blanking. Interrupts are set to level-2 in
; this routine.
;
; IMPORTANT! - This routine expects to be called in 32-bit addressing mode!!!!
;
; A3 = pointer to private storage
;---------------------------------------------------------------------
With CivicVidPrivates
CivicWaitVSync
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 <20>, 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 saveCivicBase(A3),A0 ; Point to the base of Civic.
Move.l #0,Civic_VBLClr(A0) ; Clear any pending interrupts.
Move.l #1,Civic_VBLClr(A0) ; Re-enable for NEXT interrupt.
@WaitForVBL Move.l Civic_VBLInt(A0),D0 ; Read the interrupt register.
Btst #0,D0 ; If a 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
Endwith
;---------------------------------------------------------------------
;
; SetDepth sets the depth in the DAC and the framebuffer.
;
; D1 contains the spID of the depth - $80 (the zero based mode ID)
; A1 = AuxDCE POINTER
; A2 = parameter block pointer
; A3 = dCtlStorage pointer
;
; scratch(A3).w: contains the previous mode
;
; Preserves all registers
;
;---------------------------------------------------------------------
With CivicVidPrivates,CivicVidParams,CivicBppParams,CivicRecord
CivicSetDepth
Movem.l A0-A1/D0-D2,-(Sp) ; Save our work registers.
; Set up for this routine<6E>.
Move.l saveVidPtr(A3),A1 ; Get a pointer to the vidParams.
Adda.w #CVPHdrSize,A1 ; Skip past the header info.
Move.w #CBPSize,D0 ; Get the size of each bpp entry.
Mulu D1,D0 ; Multiply it by the right entry.
Adda.l D0,A1 ; Skip to the entry we want.
; Update our videoIn GFlag
Tst.w cbpBusSize(A1) ; If it's 0, video-in is enabled
Beq @SetDepthVin ;
Bclr #videoInEnb,GFlags(A3) ; say it's disabled
; Calculate the baseAddress to put into Civic
Move.l saveBaseAddr(A3),D2 ; Get our BaseAddress
Lsr.l #5,D2 ; Normalize it for Civic
Andi.l #$FF,D2 ; Only 8 bits are valid
; Get the current state of important video-in parameters
dRead_Civic #VDCClk,D1 ; Get the state of the VDC clock
Move.w D1,VDCCLkState(A3) ; and save it
dRead_Civic #VDCEnb,D1 ; Get the state of the VDC enable bit
Move.w D1,VDCEnbState(A3) ; and save it
Clr.w OverlayState(A3) ; Assume it's off
Move.l saveVDACBase(A3),A0 ; Get a pointer to the CLUT/DAC.
Move.b SebastPCBR(A0),D0 ; and get the value
Btst #fCivicVidInOvly,D0 ; Check the Overlay bit
beq.s @NoChange ; already off
Move.w #1,OverlayState(A3) ; say it's on.
@NoChange
dWrite_Civic #0,#VDCEnb ; Disable VDC interrupts.
dWrite_Civic #1,#VDCClk ; Disable VDC clock.
; Wait for the next VBL before trying to switch depths.
;
Move.w Sr,-(Sp) ; Save the current interrupt level.
Bsr.s CivicWaitVSync ; Wait for the next VBL.
dWrite_Civic #0,#Enable ; Disable Casio (the timing generator).
; Switch the framebuffer<65>s depth.
;
dWrite_Civic cbpBusSize(A1),#BusSize ; Write the BusSize parameter
dWrite_Civic cbpHSerr(A1),#HSerr ; Write out the horizontal timing parameters.
dWrite_Civic cbpHlfLn(A1),#HlfLn ;
dWrite_Civic cbpHEq(A1),#HEq ;
dWrite_Civic cbpHSP(A1),#HSP ;
dWrite_Civic cbpHBWay(A1),#HBWay ;
dWrite_Civic cbpHAL(A1),#HAL ;
dWrite_Civic cbpHFP(A1),#HFP ;
dWrite_Civic cbpHPix(A1),#HPix ;
dWrite_Civic #$FF0,#VInHal ; Since video-in is not enabled
dWrite_Civic #$000,#VInHFPD ; Set the video-in parameters
dWrite_Civic #$FF8,#VInHFP ; <20>way into the blanking period.
dWrite_Civic #$FF0,#VInVal ;
dWrite_Civic #$FF8,#VInVFP ;
dWrite_Civic cbpGSCDivide(A1),#GSCDivide ; Set the framebuffer params for this depth.
dWrite_Civic cbpRowWords(A1),#RowWords ;
dWrite_Civic D2,#BaseAddr ;
dWrite_Civic cbpAdjF1(A1),#AdjF1 ;
dWrite_Civic cbpAdjF2(A1),#AdjF2 ;
dWrite_Civic cbpPipeD(A1),#PipeD ;
; Switch the CLUT/DAC<41>s depth.
;
Move.l saveVDACBase(A3),A0 ; Get a pointer to the CLUT/DAC.
Move.w cbpSebastPCBR(A1),D0 ; Get the PCBR value (Overlay is disabled in sresource).
Move.b D0,SebastPCBR(A0) ; Change the depth.
; Now, reset the timing generator.
;
dWrite_Civic #1,#Enable ; Enable Casio (the timing generator).
Move.l saveCivicBase(A3),A0 ; Point to the base of Civic.
Jsr CivicReset ; Reset Civic (Needs A3 = vidprivates, trashes A0)
Move.w (Sp)+,Sr ; Restore the interrupt level.
@SetDepthFinishUp
Movem.l (Sp)+,A0-A1/D0-D2 ; Restore the work registers.
Rts ; Return to caller.
@SetDepthVin
Bset #videoInEnb,GFlags(A3) ; Say video-in is enabled
Movem.l A3-A5/D2-D7,-(Sp) ; Save our registers
Move.l saveVidPtr(A3),A4 ; A pointer to our VidParams
Move.l saveVDACBase(A3),A5 ; Get a pointer to the CLUT Base
Move.b SebastPCBR(A5),D7 ; and get the value of the CLUT
Andi.b #$80,D7 ; Clear all but the Overlay bit
Or.b D1,D7 ; or in D1 (contains the zero-based graphics mode)
Bset #fCivicVidInEnb,D7 ; Tell Sebastian we have video-in enabled
Cmp.w #16,saveVidInMode(A3) ; Is our video-in in 16bpp
Bne.s @SetVidInBpp ; no, don't set that bit
Bset #fCivicVidInBpp,D7 ; Tell Sebastain we have 16bpp video-in
@SetVidInBpp
Jsr CSetVidInModeGuts ; Program Civic when video-in is enabled
Move.l saveVDACBase(A3),A5 ; Get a pointer to the CLUT Base
Move.b D7,SebastPCBR(A5) ; Change the CLUT.
Move.w D7,-(SP) ; Save it accross SetVidRect
; Now resize the vid in rect
Move.l saveVidPtr(A3),A4 ; A pointer to our VidParams
Move.w currentRight(a3),-(SP) ; Get the current video in rect
Move.w currentBottom(a3),-(SP) ;
Move.w currentLeft(a3),-(SP) ;
Move.w currentTop(a3),-(SP) ; in reverse order
Jsr CivicSetVidRectJSR ; Go do the work
Adda #8,SP ; Clean up the stack
Move.w (SP)+,D7 ; Get our PCB value back
; If our previous mode was the "threshold" mode (where video-in was disabled) then the
; State registers are valid. Otherwise, they are not (since we can just be changing from one
; video-in capable mode to another.
Move.w saveNewBaseMode(A3),D0 ; Get the threshold mode
Cmp.w scratch(A3),D0 ; Was our old mode the "threshold" byte
Bne.s @DontChange ; If not, then don't write the saved state
Tst.w OverlayState(A3) ; Was the overlay enable bit on before the switch?
Beq.s @NoOverlay ; nope, then don't do it
Bset #fCivicVidInOvly,D7 ; else, enable the Overlay bit
Move.l saveVDACBase(A3),A5 ; Get a pointer to the CLUT Base
Move.b D7,SebastPCBR(A5) ; Change the CLUT.
@NoOverlay
Move.w VDCEnbState(A3),D2 ; Get it from our privates <LW16>
dWrite_Civic D2,#VDCEnb ; Restore VDC interrupt state. <LW16>
Move.w VDCClkState(A3),D2 ; Get it from our privates <LW16>
dWrite_Civic D2,#VDCClk ; Restore VDC clock state. <LW16>
@DontChange
Movem.l (Sp)+,A3-A5/D2-D7 ; Restore our registers
Bra @SetDepthFinishUp
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 CivicVidPrivates,CivicVidParams,CivicBppParams
CivicGrayScreen
Movem.l D0-D5/A1-A2,-(Sp) ; Save our work registers.
Move.l saveBaseAddr(A3),A2 ; Get the base address of the screen.
@GetParms Move.l saveVidPtr(A3),A1 ; Get a pointer to the vidParams.
Move.w cvpNumRows(A1),D4 ; Get the number of rows to gray.
Move.b cvpScanCtl(A1),D2 ; Flag whether we<77>re interlaced or not.
Adda.w #CVPHdrSize,A1 ; Skip past the header info.
Move.w #CBPSize,D0 ; Get the size of each bpp entry.
Mulu D1,D0 ; Multiply it by the right entry.
Adda.l D0,A1 ; Skip to the entry we want.
Move.w cbpRowWords(A1),D3 ; Get the number of longwords/row.
Tst.b D2 ; If we<77>re on an interlaced display
Bne.s @Interlace ; then adjust accordingly.
Lsl.w #3,D3 ; Normalize for progressive displays.
Bra.s @SizeIt ; (Skip interlace here.)
@Interlace Lsl.w #2,D3 ; Normalize for interlaced displays.
@SizeIt Cmp.b #SixthVidMode-FirstVidMode,D1 ; If we<77>re not doing 32bpp,
Bne.s @DbraAdj ; then just go on.
Lsr.w #1,D3 ; 32bpp uses double longs.
@DbraAdj Subq #1,D3 ; Set up for Dbra loop.
Lea CivicPats,A1 ; Point to the table of gray patterns.
Move.l (A1,D1*4),D2 ; Get the gray pattern.
@NxtRow Move.w D3,D5 ; Get the number of longswords/row.
@NxtLong Move.l D2,(A2)+ ; Write out gray to the frame buffer<65>
Cmp.b #SixthVidMode-FirstVidMode,D1 ; If we<77>re not doing 32bpp,
Bne.s @Skip32bpp ; then just go on.
Not.l D2 ; Invert for next pixel.
Move.l D2,(A2)+ ; Write it out.
Not.l D2 ; Invert for next pixel.
@Skip32bpp Dbra D5,@NxtLong ; Loop until done
Not.l D2 ; Invert the pattern for the next row.
Dbra D4,@NxtRow ; Repeat for each row.
Movem.l (Sp)+,D0-D5/A1-A2 ; Restore the work registers.
Rts ; Return to caller.
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 CivicVidPrivates,CivicVidParams,CivicBppParams
CivicBlackScreen
Movem.l D0-D5/A1-A2,-(Sp) ; Save our work registers.
Move.l saveBaseAddr(A3),A2 ; Get the base address of the screen.
@GetParms Move.l saveVidPtr(A3),A1 ; Get a pointer to the vidParams.
Move.w cvpNumRows(A1),D4 ; Get the number of rows to gray.
Move.b cvpScanCtl(A1),D2 ; Flag whether we<77>re interlaced or not.
Adda.w #CVPHdrSize,A1 ; Skip past the header info.
Move.w #CBPSize,D0 ; Get the size of each bpp entry.
Mulu D1,D0 ; Multiply it by the right entry.
Adda.l D0,A1 ; Skip to the entry we want.
Move.w cbpRowWords(A1),D3 ; Get the number of longwords/row.
Tst.b D2 ; If we<77>re on an interlaced display
Bne.s @Interlace ; then adjust accordingly.
Lsl.w #3,D3 ; Normalize for progressive displays.
Bra.s @SizeIt ; (Skip interlace here.)
@Interlace Lsl.w #2,D3 ; Normalize for interlaced displays.
@SizeIt Cmp.b #SixthVidMode-FirstVidMode,D1 ; If we<77>re not doing 32bpp,
Bne.s @DbraAdj ; then just go on.
Lsr.w #1,D3 ; 32bpp uses double longs.
@DbraAdj Subq #1,D3 ; Set up for Dbra loop.
Move.l #$FFFFFFFF,D2 ; Set the black pattern.
@NxtRow Move.w D3,D5 ; Get the number of longswords/row.
@NxtLong Move.l D2,(A2)+ ; Write out gray to the frame buffer<65>
Cmp.b #SixthVidMode-FirstVidMode,D1 ; If we<77>re not doing 32bpp,
Bne.s @Skip32bpp ; then just go on.
Not.l D2 ; Invert for next pixel.
Move.l D2,(A2)+ ; Write it out.
Not.l D2 ; Invert for next pixel.
@Skip32bpp Dbra D5,@NxtLong ; Loop until done
; Not.l D2 ; Invert the pattern for the next row.
Dbra D4,@NxtRow ; Repeat for each row.
Movem.l (Sp)+,D0-D5/A1-A2 ; Restore the work registers.
Rts ; Return to caller.
Endwith
;---------------------------------------------------------------------
;
; Trans5to8
;
; <-> D1: 5-bit value to be converted into an 8-bit index.
;
CivicTrans5to8
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
;---------------------------------------------------------------------
;
; DirectCLUTSet writes gamma-corrected ascending grayscale-like ramps
; into the CLUT
;
; A3 = dCtlStorage pointer
;
; Preserves all registers used.
;
;---------------------------------------------------------------------
With CivicVidPrivates
CivicDirectCLUTSet
MOVEM.L D0-D7/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<73>
ADDA D1,A6 ; <09>of blue
@OneTbl MOVE.W gDataCnt(A0),D2 ; Get number of entries.
Subq #1,D2 ; Make it zero based.
MOVE.L saveVDACBase(A3),A0 ; point to the hardware
Move.b SebastPCBR(A0),D0 ; Make sure we're writing to the Graphics CLUT
Bclr #fCivicVidInCLUT,D0 ; by zeroing the CLUT select bit in the PCBR
Move.b D0, SebastPCBR(A0) ; and write it back out.
ADDA #SebastDataReg,A0 ; point to data register
Clr.b SebastAddrReg-SebastDataReg(A0) ; start at the beginning of CLUT
Move.w GFlags(A3),D5 ; Get the flags for quick access.
Move.w saveMode(A3),D1 ; Get the current mode.
Cmp.b #FifthVidMode,D1 ; If we<77>re not doing 16bpp,
Bne.s @32bpp ; 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.
@32bpp MOVE.W SR,-(SP) ; preserve the status register
BSR CivicWaitVSync ; wait for next blanking period (preserves A0)
; Write an incrementing grayscale ramp.
Moveq #0,D0 ; Start the ramp at zero.
Btst #videoInEnb,D5 ; If video-in is enabled, need to read the alpha
Bne @VidRepeat ; before writing the grey
@Repeat Move.w D0,D1 ; Copy the current index.
Btst #UseTrans,D5 ; If we don<6F>t need to translate this value,
Beq.s @Index ; then just go on.
Bsr.s CivicTrans5to8 ; Otherwise, convert it, and use it
@Index MOVE.B (A4,D1),(A0) ; Write gamma-corrected red.
MOVE.B (A5,D1),(A0) ; Write gamma-corrected green
MOVE.B (A6,D1),(A0) ; Write gamma-corrected blue.
Clr.b (A0) ; Skip alpha.
Addq #1,D0 ; Increment the ramp index.
DBRA D2,@Repeat ; Loop until done.
Bra.s @FinishDGray ; Finish it off
@VidRepeat Move.w D0,D1 ; Copy the current index.
Btst #UseTrans,D5 ; If we don<6F>t need to translate this value,
Beq.s @VidIndex ; then just go on.
Bsr.s CivicTrans5to8 ; Otherwise, convert it, and use it
@VidIndex
Move.b (A0),D7 ; Read: red,
Move.b (A0),D7 ; green,
Move.b (A0),D7 ; blue,
Move.b (A0),D7 ; alpha,
Move.b D0,SebastAddrReg-SebastDataReg(A0) ; ReWrite the CLUT Address register
MOVE.B (A4,D1),(A0) ; Write gamma-corrected red.
MOVE.B (A5,D1),(A0) ; Write gamma-corrected green
MOVE.B (A6,D1),(A0) ; Write gamma-corrected blue.
Move.b D7,(A0) ; Write save alpha.
Addq #1,D0 ; Increment the ramp index.
DBRA D2,@VidRepeat ; Loop until done.
@FinishDGray
MOVE.W (SP)+,SR ; restore the status reg
MOVEM.L (SP)+,D0-D7/A0/A4-A6 ; restore saved registers
RTS
Endwith
;---------------------------------------------------------------------
;
; VideoCLUTSet writes gamma-corrected ascending grayscale-like ramps
; into the VideoCLUT
;
; A3 = dCtlStorage pointer
;
; Preserves all registers used.
;
;---------------------------------------------------------------------
With CivicVidPrivates
CivicVideoCLUTSet
MOVEM.L D0-D7/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<73>
ADDA D1,A6 ; <09>of blue
@OneTbl MOVE.W gDataCnt(A0),D2 ; Get number of entries.
Subq #1,D2 ; Make it zero based.
MOVE.L saveVDACBase(A3),A0 ; point to the hardware
Move.b SebastPCBR(A0),D0 ; Make sure we're writing to the Video CLUT
Bset #fCivicVidInCLUT,D0 ; by zeroing the CLUT select bit in the PCBR
Move.b D0, SebastPCBR(A0) ; and setting it back out.
Move.b D0,D5 ; Save the CLUT settings for quick access later.
ADDA #SebastDataReg,A0 ; point to data register
Clr.b SebastAddrReg-SebastDataReg(A0) ; start at the beginning of CLUT
Move.w #$1F,D2 ; There are only 32 entries to whack in 16bpp mode.
@32bpp MOVE.W SR,-(SP) ; preserve the status register
BSR CivicWaitVSync ; wait for next blanking period (preserves A0)
; Write an incrementing grayscale ramp.
Moveq #0,D0 ; Start the ramp at zero.
@Repeat Move.w D0,D1 ; Copy the current index.
Btst #fCivicVidInBpp,D5 ; Is the video-in in Grey scale
Bne.s @Color ; no, then just write the value
Moveq #31,D1 ; Need to invert the table
Sub.w D0,D1 ; so start at the top
@Color
lsl.w #3,D1 ; and shift it to the most significant 5 bits
@Index MOVE.B (A4,D1),(A0) ; Write gamma-corrected red.
MOVE.B (A5,D1),(A0) ; Write gamma-corrected green
MOVE.B (A6,D1),(A0) ; Write gamma-corrected blue.
Addq #1,D0 ; Increment the ramp index.
DBRA D2,@Repeat ; Loop until done.
@FinishDGray
MOVE.W (SP)+,SR ; restore the status reg
MOVEM.L (SP)+,D0-D7/A0/A4-A6 ; restore saved registers
RTS
Endwith
;---------------------------------------------------------------------
;
; This routine is used to program the VidIn Horiz and Vert values, depending
; on the rect that is in the stack.
;
; A3 = Pointer to CivicVidPrivates Table
; A4 = Pointer to VidParams
; A5 = Pointer to VDACBase
;
; Uses A6 (preserved)
; D0,D1,D2,D3,D4,D6,D7 (not preserved)
;
;
;---------------------------------------------------------------------
CivicSetVidRectJSR
; Adjust the stack pointer so our parameters our available
Move.l A6,-(Sp) ; save A6's value
Move.l Sp,A6 ; Get a pointer to it
Adda.l #8,A6 ; our local variables
; If all the parameters are 0, then set the vidRect way out in right field: (This will happen if
; video-in has never been enabled)
Move.w bottom(A6),D0 ; Gets the bottom (2-bytes) of the csRect
Add.w top(A6),D0 ; Gets the top (2-bytes) of the csRect
Add.w left(A6),D0 ; Gets the left of the csRect
Add.w right(A6),D0 ; Gets the right of the csRect
Bne.s @NotAZeroRect ; It's not a nil rect
dRead_Civic #VFP,D6 ; Saves actual HAL into D6
dRead_Civic #HFP,D7 ; Saves actual HFP into D7
Addi.w #2,D7 ;
Move.w D7,saveVinHAL(a3) ; Set the video-in params<6D>
Addi.w #2,D7 ;
Move.w D7,saveVinHFP(a3) ;
Move.w #$0,saveVinHFPD(a3) ;
Addi.w #2,D6 ;
Move.w D6,saveVinVAL(a3) ;
Addi.w #2,D6 ;
Move.w D6,saveVinVFP(a3) ;
Clr.w saveVidInSize(a3) ; 0 = "small video"
Bra WriteVidInParms
@NotAZeroRect
; We have a valid rect and page. Set the VidInSize to 0 -- will set to 1 if necessary later
dRead_Civic #HAL,D6 ; Saves actual HAL into D6
dRead_Civic #HFP,D7 ; Saves actual HFP into D7
Clr.w saveVidInSize(a3) ; 0 = "small video"
; Now, calculate the vertical parameters
;
; If we are in progressive mode the values for VinVAL and VinVFP are given by:
;
; VinVAL = VAL + (csRect.top << 1)
; VinVFP = VAL + (csRect.bottom << 1)
;
Move.w cvpVAL(A4), D1 ; Save VAL so we don't have to get it from memory repeatedly
Tst.b cvpScanCtl(A4) ; ScanCtl inverted when you read it back, but here it is the value programmed
; into Civic: 0 = progressive mode, 1 = interlaced
Bne.s VidInVertInter ; Do the interlaced mode
Move.w top(A6),D0 ; Gets the top (2-bytes) of the csRect
Lsl.w #1,D0 ; Multiply by two (if carry set the rect is too big. Check for this?)
Add.w D1,D0 ; and add VAL to it
Move.w D0, saveVinVAL(a3) ; Save VinVAL to dump it to civic later
Move.w bottom(A6),D0 ; Gets the bottom (2-bytes) of the csRect
Lsl.w #1,D0 ; Multiply by two (if carry set, there should've been an error
Add.w D1,D0 ; and add VAL to it
Move.w D0, saveVinVFP(a3) ; Save VinVFP to dump it to civic later
Bra.s VidInHoriz ; Go do the horizontal parameters
VidInVertInter
;
; If we are in interlaced mode, we have to adjust the parameters to the fact that each field contains only half
; the number of lines that it does in interlace mode, thus:
;
; VinVAL = VAL + csRect.top
; VinVFP = VAL + csRect.bottom
;
; VAL is in D1
;
Move.w top(A6),D0 ; Gets the top (2-bytes) of the csRect
Add.w D1,D0 ; Add the top edge to VAL
Bclr #0,D0 ; Make sure VinVAL is even
Move.w D0, saveVinVAL(a3) ; Save VinVAL to dump it to civic later
Move.w bottom(A6),D0 ; Get the left point of the csRect
Add.w D1,D0 ; Add the adjusted VAL to it
Bclr #0,D0 ; Make sure VinVFP is also even (or Interlaced Mode)
Move.w D0, saveVinVFP(a3) ; Save VinVFP to dump it to civic later
VidInHoriz
; Now, we are ready to do the horizontal parameters. This is more complicated because the VidParams for the horizontal
; values change depending on the bit depth
;
; These values will depend on whether we are in 8bpp/16bpp video-in and the graphics bpp:
;
; For 16bpp Video-in (any graphics bpp) OR 8bpp video-in with 16bpp graphics:
;
; VinHAL = HAL + csRect.left
; VinHFP = HFP + csRect.right
;
; For 8bpp Video-in AND 1,2,4,8bpp graphics
;
; VinHAL = HAL + (csRect.left >> 1) - 1
; VinHFP = HFP + (CsRect.left >> 1) - 1
;
; VinHFPD = 0 always.
;
Clr.w saveVinHFPD(a3) ; VinVFPD is always zero
Move.b SebastPCBR(A5), D0 ; Get the PCBR Value
Btst #fCivicVidInBpp,D0 ; Check to see what bpp video-in we have
Bne.s VidInHoriz16bpp ; ( 1 = 16bpp)
; we're in 8bpp video-in here
Andi.b #mCivicGrBpp,D0 ; Look at the graphics bpp (#mCivicGrBpp = $07);
Cmp.b #vCivicGr16Bpp,D0 ; Is it 16bpp graphics (8bpp video)
Beq.s VideoIsSmall ; We're in 8bpp video-in, so saveVidInSize should always <LW14>
; be 0 <LW14>
; OK, now only in 8bpp video-in, 1,2,4,8 graphics (HAL in D6)
; First check to see if we have to set the "big/small" video bit
;
Move.w (right)(A6),D2 ; Gets the right of the csRect
Sub.w (left)(A6),D2 ; we have the width * 2
Lsr.w #1,D2 ; Divide by 2 to get the width
Cmpi.w #496,D2 ; the max size for a small video <LW14>
Ble.s VideoIs8bppSmall ; no need to set this VidInSize bit
Move.w #1,saveVidInSize(a3) ; each scan line is written into 1.5 lines of VRAM
VideoIs8bppSmall
Move.w (left)(A6),D2 ; Gets the left of the csRect
Lsr.w #1,D2 ; Divide it by 2
Add.w D6,D2 ; Add HAL to it
Subi.w #1,D2 ; and subtract the fudge factor
Move.w D2,saveVinHAL(a3) ; Save it in our privates
Move.w (right)(A6),D2 ; Gets the right of the csRect
Lsr.w #1,D2 ; Divide it by 2
Add.w D6,D2 ; Add HAL to it
Subi.w #1,D2 ; and subtract the fudge factor
Move.w D2,saveVinHFP(a3) ; Save it in our privates
Moveq #0,D4 ; Flag for use in CkClipping: 0: csRect parameters need to be halved
Bra.s CkHorizClipping ; Make sure video-in rect fit in screen
; we're in 16bpp video-in here (HAL in D1)
VidInHoriz16bpp
; First check to see if we have to set the "big/small" video bit
;
Move.w (right)(A6),D2 ; Gets the right of the csRect
Sub.w (left)(A6),D2 ; we have the width
Cmpi.w #496,D2 ; the max size for a small video <LW14>
Ble.s VideoIsSmall ; no need to set this VidInSize bit
Move.w #1,saveVidInSize(a3) ; each scan line is written into 1.5 lines of VRAM
VideoIsSmall
Move.w (left)(A6),D2 ; Gets the left of the csRect
Add.w D6,D2 ; Add HAL to it
Subi.w #1,D2 ; and subtract the fudge factor
Move.w D2,saveVinHAL(a3) ; Save it in our privates
Move.w (right)(A6),D2 ; Gets the right of the csRect
Add.w D6,D2 ; Add HAL to it
Subi.w #1,D2 ; and subtract the fudge factor
Move.w D2,saveVinHFP(a3) ; Save it in our privates
Moveq #1,D4 ; Flag for use in CkClipping: 1: csRect parameters do not need to be halved
CkHorizClipping
;
; Horizontal Clipping will occur if VinHFP > HFP. In that case, we need to return in the csRect the
; maximum value for csRect.right:
;
; csRect.right = csRect.left + ( D4 == 0 ? (HFP - VinHAL)*2 : (HFP - VinHAL) )
; D4 contains a flag that will tell me (if 0) that the VinHAL needs to be doubled to arrive at the correct screen coordinates
;
; Vertical Clipping will occur if VinVFP > VFP. Again, we need to return the maximum vlaue for csRect.bottom
;
; csRect.bottom = csRect.top + ( Interlaced ? (VFP - vinVFP) : (VFP - VinVFP) / 2
;
; depending on whether we're in interlaced or not
; VinHFP is in D2
Clr.w D3 ; Flag to show that clipping occurred
Cmp.w D7,D2 ; Need to clip Horizontally if VinHFP
Bgt DoHorizClipping ; is greater than HFP (Set D3 to 1 if clipped occurred)
CkVertClipping
Move.w cvpVFP(A4),D0 ; Get the graphics vert front porch
Move.w saveVinVFP(a3),D2 ; Get the video-in vert front porch
Cmp.w D0,D2 ; Need to clip Horizontally if VinHFP
Bgt DoVertClipping ; is greater than HFP (Set D3 to 1 if clipped occurred)
Bra.s TestClipping ; do the vertical checking
DoHorizClipping
; Horizontal Clipping will occur if VinHFP > HFP. In that case, we need to return in the csRect the
; maximum value for csRect.right:
;
; csRect.right = csRect.left + ( D4 == 0 ? (HFP - VinHAL)*2 : (HFP - VinHAL) )
; D4 contains a flag that will tell me (if 0) that the VinHAL needs to be doubled to arrive at the correct screen coordinates
Moveq #1, D3 ; set "Clipped" Flag
Move.w D7,D1 ; get HFP
Sub.w saveVinHAL(a3),D1 ; subtract VinHAL from it
Tst.b D4 ; do we need to double the value (D4 has the "need to double flag for horiz values")
Bne.s ExitHorizClipping ; nope
Lsl.w #1, D1 ; we double the value
ExitHorizClipping
Add.w (left)(A6), D1 ; write the max right to csRect
Move.w D1,(right)(A6) ;
Bra.s CkVertClipping ; do the vertical checking
DoVertClipping
; Vertical Clipping will occur if VinVFP > VFP. Again, we need to return the maximum vlaue for csRect.bottom
;
; csRect.bottom = csRect.top + ( Interlaced ? (VFP - vinVFP) : (VFP - VinVFP) / 2
;
; depending on whether we're in interlaced or not
Moveq #1, D3 ; set "Clipped" Flag
Move.w cvpVFP(A4),D1 ; get VFP
Sub.w saveVinVAL(a3),D1 ; subtract VinVAL from it
Tst.b cvpScanCtl(A4) ; do we need to half the value (cvpScanCtl = 1 for interlaced)
Bne.s ExitVertClipping ; nope
Lsr.w #1, D1 ; we half the value for progressive
ExitVertClipping
Add.w (top)(A6), D1 ; write the max bottom to csRect
Move.w D1,(bottom)(A6) ;
TestClipping
Tst.b D3 ; Any Clipping?
Bne CRectGotClipped ; yes, return an error (csRect was already written with the write value in the Do..Clipping routines
; prepare to write the VidIn parameters (We're still in 32-bit mode)
WriteVidInParms
; Wait for the next VBL before trying to write to Civic.
;
Move.w Sr,-(Sp) ; Save the current interrupt level.
Bsr CivicWaitVSync ; Wait for the next VBL.
; Write the Vin parameters.
;
dWrite_Civic saveVidInSize(a3),#VidInSize ; Write out the size parameter for video in ("BigSmall Video").
dWrite_Civic saveVinHFP(a3),#VInHFP ; Write out the horizontal timing parameters.
dWrite_Civic saveVinHFPD(a3),#VInHFPD ;
dWrite_Civic saveVinHAL(a3),#VInHAL ;
dWrite_Civic saveVinVFP(a3),#VInVFP ;
dWrite_Civic saveVinVAL(a3),#VInVAL ;
Move.w (Sp)+,Sr ; Restore the interrupt level.
; Exit subroutine, write back stack to csRect in case of clipping
CSetVRectGoodExit
Move.l (Sp)+,A6 ; Restore our used variable
Moveq #0,D0 ; Set noerr return
CSetVRectExit
Rts ; and go back
CRectGotClipped
Move.l (Sp)+,A6 ; Restore our used variable
Moveq #1,D0 ; Set error return
Bra.s CSetVRectExit ; and go back
;---------------------------------------------------------------------
;
; This routine is used to program Civic when video-in is enabled, depending
; on the what video-in mode and the graphics mode are
;
; A3 = Pointer to CivicVidPrivates Table
; A4 = Pointer to VidParams
; A5 = Pointer to VDACBase
;
; D7 = CLUT value with desired graphics and video-in bpp
; D0,D1,D2,D3,D4,D6,D7 (not preserved)
;
;
;---------------------------------------------------------------------
CSetVidInModeGuts
;
; SubRoutine to change depths when video in is enabled
;
Clr.w D4 ; D4 contains the GSCDivideAdjust field
Clr.w D6 ; D6 contains the VSCDivideAdjust field
Move.b D7,D1 ; Get a copy of the desired bpp
Andi.w #mCivicGrBpp,D1 ; Look at the graphics bpp (#mCivicGrBpp = $07). Save for later.
Btst #fCivicVidInBpp,D7 ; Look at the Video-in Bpp
Beq CVidIn8bppMode ; do an 8bpp mode
; We're doing video-in 16bpp here
Cmp.w #vCivicGr16Bpp,D1 ; Is the graphics in 16bpp
Beq @GSCOK ; if it is not the GSCDivide value from the parameters
Moveq #1,D4 ; needs to be increased by one.
@GSCOK Adda.w #CVPHdrSize,A4 ; Skip past the header info
Move.l A4,A5 ; Make a copy of the base vidparams field (Use A5 to point to the horizontal values)
Move.w #CBPSize,D0 ; Get the size of each entry
Mulu D1,D0 ; We want the correct bpp entry
Adda.l D0,A4 ; Add it to our base, A4 now points to the bpp entry
Move.w #CBPSize,D0 ; Get the size of each entry
Mulu #4,D0 ; We want the 4th bpp entry
Adda.l D0,A5 ; Add it to our base, A5 now points to the 16bpp entry
; Make sure that the 16bpp entry has video-in enabled, If not, look at the 32bpp entry.
Tst.w cbpBusSize(A5) ; This tells us if video-in is enabled
Beq.w @goodEntry ; when 0, video-in is enabled
Adda.l #CBPSize,A5 ; if the 16bpp has no video-in, the 32bpp entry will have the double parameters
@goodEntry
Bra CivicVidModeHWParams ; A4 -> ptr to desired bpp entry, A5->desired horiz parameters entry.
CVidIn8bppMode
; We're doing video-in 8bpp.
Cmp.w #vCivicGr16Bpp,D1 ; Is the graphics in 16bpp
Bne @CVidIn8Gr8bpp ; if not, go do 8bpp stuff
Move.w #1,D6 ; D6 contains the value for VSCDivide
@CVidIn8Gr8bpp
Adda.w #CVPHdrSize,A4 ; Skip past the header info
Move.w #CBPSize,D0 ; Get the size of each entry
Mulu D1,D0 ; Get the entry we want
Adda.l D0,A4 ; We want the 0th entry
Move.l A4,A5 ; Point A5 to the desired entry for the horizontal parameters.
CivicVidModeHWParams
; Calculate the baseAddress to put into Civic
Move.l saveBaseAddr(A3),D2 ; Get our BaseAddress
Lsr.l #5,D2 ; Normalize it for Civic
Andi.l #$FF,D2 ; Only 8 bits are valid
; Wait for the next VBL before trying to switch depths.
;
Move.w Sr,-(Sp) ; Save the current interrupt level.
Bsr CivicWaitVSync ; Wait for the next VBL.
; Switch the framebuffer<65>s depth.
;
; Note: cbpBusSize(A5) might not have the correct value. Always program it 0 here. <LW15>
Move.w d2,-(Sp) ; Save d2 'cause we'll trash it <LW15>
clr.w d2 ; Bus Size is 0 in this case <LW15>
dWrite_Civic d2,#BusSize ; Write the BusSize parameter <LW14><LW15>
Move.w (Sp)+,d2 ; restore d2 <LW15>
dWrite_Civic cbpHSerr(A5),#HSerr ; Write out the horizontal timing parameters.
dWrite_Civic cbpHlfLn(A5),#HlfLn ;
dWrite_Civic cbpHEq(A5),#HEq ;
dWrite_Civic cbpHSP(A5),#HSP ;
dWrite_Civic cbpHBWay(A5),#HBWay ;
dWrite_Civic cbpHAL(A5),#HAL ;
dWrite_Civic cbpHFP(A5),#HFP ;
dWrite_Civic cbpHPix(A5),#HPix ;
Add.w cbpGSCDivide(A4),D4 ; Add GSCDivide to 1 or 0, depending on the factor
dWrite_Civic D4,#GSCDivide ; Write it out
dWrite_Civic cbpRowWords(A4),#RowWords ;
dWrite_Civic D2,#BaseAddr ;
dWrite_Civic cbpAdjF1(A4),#AdjF1 ;
dWrite_Civic cbpAdjF2(A4),#AdjF2 ;
dWrite_Civic cbpPipeD(A5),#PipeD ;
dWrite_Civic D6,#VSCDivide ; and VSCDivide
; Now, reset the timing generator.
;
Bsr CivicWaitVSync ; Wait for the next VBL.
Jsr CivicReset ; Reset Civic (Needs A3 = vidprivates, trashes A0)
Move.w (Sp)+,Sr ; Restore the interrupt level.
Rts
;-------------------------------------------------------------
; This routine resets Civic
;-------------------------------------------------------------
CivicReset
; Reset of Civic
Move.l saveCivicBase(A3),A0 ; Point to the base of Civic.
Move.l #0,Civic_Reset(A0) ; Reset Casio.
Move.l #0,Civic_Reset(A0) ; Reset Casio.
Move.l #0,Civic_Reset(A0) ; Reset Casio.
Move.l #0,Civic_Reset(A0) ; Reset Casio.
Move.l #0,Civic_Reset(A0) ; Reset Casio.
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #0,Civic_Reset(A0) ;
Move.l #0,Civic_Reset(A0) ;
Move.l #0,Civic_Reset(A0) ;
Move.l #0,Civic_Reset(A0) ;
Move.l #0,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Move.l #1,Civic_Reset(A0) ;
Rts
;---------------------------------------------------------------------
;
; Wait5ms
; Entry: Not Used
; Exit: D0 destroyed
;---------------------------------------------------------------------
;
; This loop will wait 5 milliseconds before returning. It is used for the Clifton clock chip
Wait5ms Move.l #(-5)<<16,d0 ; outer loop count 500*1ms
@outer Move.w TimeDBRA,d0 ; inner loop count 1ms
@inner dbra d0,@inner ; wait 1ms
Addq.l #1,d0 ; increment outer loop counter
Bne.s @outer ; wait 5*1ms
rts ; the long wait is over
;--------------------------------------------------------------------- <LW17> #PUMA
; <LW17> #PUMA
; IsItPUMA <LW17> #PUMA
; Entry: A4 (Endeavor Base) <LW17> #PUMA
; Exit: D0-D2 destroyed <LW17> #PUMA
;--------------------------------------------------------------------- <LW17> #PUMA
; <LW17> #PUMA
; This routine will try to read the ID register from Clifton or PUMA. Clifton does not <LW17> #PUMA
; have one, so it should read all 1's, where PUMA does. The routine will exit with the <LW17> #PUMA
; condition code set to 0 if it's a PUMA. <LW17> #PUMA
; <LW17> #PUMA
IsItPUMA ; <LW17> #PUMA
move.l #ControlWordSize-1,D2 ; Get the loop counter <LW17> #PUMA
move.l #ReadPUMAID,D1 ; Enable MuxRef/Enable PROG Register <LW17> #PUMA
@LoadID ; <LW17> #PUMA
Move.l #1,D0 ; Set up the mask for the bit <LW17> #PUMA
And.l D1,D0 ; Transfer the first bit to D0 <LW17> #PUMA
Move.b D0,EndeavorM(A0) ; write the bit out to Clifton <LW17> #PUMA
lsr.l #1,D1 ; get the next bit <LW17> #PUMA
Dbra D2,@LoadID ; <20>for the whole word <LW17> #PUMA
; <LW17> #PUMA
Move.l #(8-1),D2 ; The loop counter <LW17> #PUMA
clr.b D0 ; We'll store the ID here <LW17> #PUMA
@ReadID Move.b EndeavorM(A0),D1 ; Read a bit <LW17> #PUMA
Andi.b #1,D1 ; Mask all but the 0th bit <LW17> #PUMA
Or.b D1,D0 ; Or into our save register <LW17> #PUMA
ror.b #1,D0 ; And get ready to accept the new bit <LW17> #PUMA
Dbra D2,@ReadID ; <20>for the whole word <LW17> #PUMA
; <LW17> #PUMA
cmpi.b #PUMAVer1Id,D0 ; Is it our version 1 ID <LW17> #PUMA
rts ; <LW17> #PUMA
; <LW17> #PUMA
;-------------------------------------------------------------
; The Interrupt handler for the Civic Built-In Video
;-------------------------------------------------------------
; On entry A1 contains the pointer to the driver's private storage
CivicBeginIH
Move.l A0,-(Sp) ; Save work registers (according to IM V).
Move.l D1,-(Sp) ; (Two Moves are faster than a Movem.)
Move.l saveCivicBase(A1),A0 ; Point to the base of Civic.
Move.l Civic_VBLInt(A0),D0 ; Is this a VBL Interrupt
Btst #0,D0 ; Only bit 0 is valid
Bne @ItsAVBL ; Active high interrupt
; If it's not a VBL, then it has to be a VDC interrupt. Just exit without saying we handle the interrupt.
* Bra.s @InterruptNotServiced
@InterruptNotServiced
Moveq #0,D0 ; Signal that the interrupt was NOT serviced
Bra @ExitVBLHandler
@ItsAVBL
Clr.l Civic_VBLClr(A0) ; Clear this interrupt.
Move.l #1,Civic_VBLClr(A0) ; Re-enable VBLs.
Moveq #0,D0 ; Set up for Slot $0<>
Jsr ([jVBLTask]) ; <09>and call the VBL Task Manager.
@InterruptServiced
Moveq #1,D0 ; Signal that the interrupt was serviced
@ExitVBLHandler
Move.l (Sp)+,D1 ; Restore our work registers.
Move.l (Sp)+,A0 ; (Two Moves are faster than a Movem.)
Rts ; Return to caller.
END