mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-04 01:29:22 +00:00
0ba83392d4
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
5165 lines
204 KiB
Plaintext
5165 lines
204 KiB
Plaintext
;
|
||
; 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: © 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Õs base address.
|
||
mmcBaseAddr DS.L 1 ; Pointer to MMCÕ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 ÒskipÓ 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Õs base address
|
||
Move.l CivicAddr(A0),saveCivicBase(A3) ; save CivicÕs base address
|
||
Move.l DecoderAddr(A0),saveYMCABaseAddr(A3) ; Save YMCAÕ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 ÒrealÓ
|
||
; monitor ID. At PrimaryInit time, we store the real monitor ID in slot pRAM. So, we extract that
|
||
; information out here. Also, it should be noted that it would actually be inappropriate for us
|
||
; to re-read the sense-lines now, in that someone could potentially change/unplug the attached
|
||
; display between PrimaryInit and VidOpen, and that would cause us all sorts of havoc.
|
||
;
|
||
With SP_Params
|
||
|
||
Move.l Sp,A0 ; Point to spBlock on the stack.
|
||
Move.b dCtlSlot(A1),spSlot(A0) ; Put slot into spBlock.
|
||
|
||
Suba #sizeSPRamRec,Sp ; Allocate an SPRam block on the stack.
|
||
Move.l Sp,spResult(A0) ; Point to it.
|
||
_SReadPRAMRec ; Read Slot PRam.
|
||
Bne @OpError5 ; If failed quit.
|
||
|
||
Moveq #0,D2 ; Clear D2.w.
|
||
Move.b SP_MonID(Sp),D2 ; Get the monID (itÕ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É
|
||
;
|
||
@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Õ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É
|
||
;
|
||
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 ³ 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Õs only one table,
|
||
Beq.s @OnlyOneTable ; then weÕre set.
|
||
|
||
Move.w gDataWidth(A0),D2 ; Get width of each entry (in bits).
|
||
Move.w gDataCnt(A0),D0 ; Get # of entries in table.
|
||
Addq #7,D2 ; Round to nearest byte.
|
||
Lsr.w #3,D2 ; Get bytes per entry.
|
||
Mulu D2,D0 ; Get size of table in bytes.
|
||
|
||
Adda.w D0,A5 ; Calc base of green (red base + D0).
|
||
Adda.w D0,A6 ; Calc baseÉ
|
||
Adda.w D0,A6 ; Éof blue (red base + D0 + D0).
|
||
|
||
@OnlyOneTable
|
||
|
||
Move.w gDataCnt(A0),D3 ; Save number of gamma entries.
|
||
|
||
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É
|
||
;
|
||
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Õs not 8bbp, 16bpp, or 32bpp,
|
||
Blt.s @SkipSeq ; need to use ÒindexedÓ.
|
||
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Õ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Õ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Õ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 ÒindexedÓ 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É
|
||
MOVE.L (A2)+,(A0)+ ; É12 bytes long
|
||
|
||
; Copy the data.
|
||
|
||
MULU D0,D2 ; multiply by number of tables
|
||
ADD D1,D2 ; add in size of formula data
|
||
SUBQ #1,D2 ; get count - 1
|
||
@NxtByte MOVE.B (A2)+,D0 ; get a byte
|
||
MOVE.B D0,(A0)+ ; move a byte
|
||
DBRA D2,@NxtByte ; => repeat for all bytes
|
||
|
||
Bra.s @GammaDone ; Check to see if itÕs a direct device.
|
||
|
||
;
|
||
; Set up a linear gamma table. To prevent memory thrash, build this new one
|
||
; the same size as the existing one (one or three channel).
|
||
;
|
||
|
||
@LinearTab
|
||
|
||
MOVE.L saveGammaPtr(A3),A0 ; get current gamma in A0
|
||
MOVE.W gFormulaSize(A0),D0 ; get size of formula in new
|
||
MOVE.W gChanCnt(A0),D2 ; get the number of tables
|
||
SUBQ #1,D2 ; zero based, of course
|
||
Move.w gDataCnt(A0),D3 ; get the number of entries
|
||
Subq #1,D3 ; zero base
|
||
ADDA #gFormulaData,A0 ; point to tables
|
||
ADDA D0,A0 ; point past monID, if present
|
||
@ChanLoop MOVE.W D3,D0 ; loop count within each channel
|
||
@entryLoop MOVE.B D0,(A0) ; write this value out
|
||
Not.b (A0)+ ; invert to make table ramp properly
|
||
DBRA D0,@entryLoop ; for each entry in channel
|
||
DBRA D2,@ChanLoop ; and each channel
|
||
|
||
@GammaDone
|
||
BTST #IsDirect,GFlags(A3) ; are we in a direct mode?
|
||
BEQ.S @Out ; if not, then we're done
|
||
BSR 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Õt cause a problem. But we should check it anyway for unsavory
|
||
; applications.
|
||
;
|
||
|
||
Move.b csMode(A2),spID(A0) ; Look for the passed in spID.
|
||
Clr.l spParamData(A0) ; Clear the fNext flag; we want THIS sRsrc.
|
||
Ori.b #(1<<fall)|\ ; Search for both enabled/disabled sRsrcÕs
|
||
(1<<foneslot),spParamData+3(A0) ; Only search in our slot.
|
||
_GetsRsrc ; Do it.
|
||
Bne.s @BadExit ; If failed, quit.
|
||
|
||
Move.w spCategory(A0),D0 ; Get the category.
|
||
Cmp.w #catDisplay,D0 ; If itÕs not catDisplay,
|
||
Bne.s @BadExit ; then quit.
|
||
Move.w spCType(A0),D0 ; Get the type.
|
||
Cmp.w #typVideo,D0 ; If itÕs not typVideo,
|
||
Bne.s @BadExit ; then quit.
|
||
Move.w spDrvrSw(A0),D0 ; Get the software kind.
|
||
Cmp.w #drSwApple,D0 ; If itÕs not drSwApple,
|
||
Bne.s @BadExit ; then quit.
|
||
Move.w spDrvrHw(A0),D0 ; Get the hardware ID.
|
||
Cmp.w #drHwCivic,D0 ; If itÕ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Õ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Õre at the end of the table, <LW14>
|
||
Beq @BadExit ; then somethingÕ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 ÒindexÓ code if a valid sense code is passed
|
||
; in csMode (byte 0 is the sense code, byte 1 is the type).
|
||
;
|
||
; A1 = Ptr to AuxDCE/Ptr to 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É
|
||
;
|
||
|
||
Suba #SizesPRAMRec,Sp ; Make an sPRAM block on the stack.
|
||
Move.l Sp,spResult(A0) ; Point to it.
|
||
_sReadPRamRec ; Get pRAM.
|
||
|
||
;
|
||
; See what we need to doÉ
|
||
;
|
||
|
||
Move.b csMode+1(A2),D0 ; Get the sense-code type.
|
||
Beq.s @NoConnect ; If indexed (0), use type 7.
|
||
Cmp.b #indexedSense2P,D0 ; If we got a type 3,
|
||
Beq.s @2PExtended ; then go there.
|
||
Cmp.b #indexedSenseHR,D0 ; If we got a type 6,
|
||
Beq.s @HRExtended ; then go there.
|
||
Cmp.b #indexedNoConnect,D0 ; If we got a type 7,
|
||
Beq.s @NoConnect ; then go there.
|
||
Bra @MonIDNotValid ; Otherwise, return an error.
|
||
|
||
@2PExtended
|
||
Move.b csMode(A2),D1 ; Get the sense code into D0.
|
||
Cmp.b #extended2PRdRGB,D1 ; If itÕs the Radius ColorTPD,
|
||
Beq @WriteIt ; then write it out.
|
||
Cmp.b #extended2PRdMono,D1 ; If itÕs the Radius MonoTPD,
|
||
Beq.s @WriteIt ; then write it out.
|
||
Bra @MonIDNotValid ; Otherwise, return an error.
|
||
|
||
@HRExtended
|
||
Cmp.b #extendedHR,csMode(A2) ; If itÕs not the MultiSync code,
|
||
Bne @MonIDNotValid ; return an error.
|
||
Move.b #indexedSenseHR,D1 ; Otherwise, default to HR.
|
||
Bra.s @WriteIt
|
||
|
||
@NoConnect
|
||
Move.b csMode(A2),D1 ; Get the monID.
|
||
Cmp.b #indexedNoConnect,D1 ; If itÕs one of the no-connect codes,
|
||
Beq.s @ClearIt ; then zero-out the no-connect pRam byte.
|
||
Cmp.b #extendedNoConnect,D1 ;
|
||
Beq.s @ClearIt ;
|
||
|
||
Lea 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Ó.
|
||
Move.b #indexedSenseGF,D1 ;
|
||
Bra.s @WriteIt
|
||
|
||
@Try19 Cmp.b #extendedSense19,D1 ; Is it a 19Ó?
|
||
Bne.s @WriteIt ; Nope, must be indexed.
|
||
Move.b #indexedSense19,D1
|
||
|
||
@WriteIt Move.b D1,SP_AltSense(Sp) ; Write out ÒindexÓ to pRam record.
|
||
Ori.b #spAltSenseValidMask,SP_AltSense(Sp) ; Validate it.
|
||
Bra.s @WritePRam
|
||
|
||
@ClearIt Clr.b SP_AltSense(Sp) ; Invalidate no-connect byte.
|
||
|
||
@WritePRam Move.l Sp,spsPointer(A0) ; Set up to whack pRam.
|
||
_sPutPRAMRec ; Whack it.
|
||
|
||
Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack andÉ
|
||
Bra CivicCtlGood ; Éleave.
|
||
|
||
@MonIDNotValid Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack andÉ
|
||
Bra CivicCtlBad ; É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 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Õ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 ; Éyes, program Clifton
|
||
Cmp.b #BoxTempest33,saveBoxFlag(A3) ; Do we have a Tempest33
|
||
beq.s @DoClifton ; É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 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 ; É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 ; É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 ; É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 ; É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É
|
||
dWrite_Civic #$000,#VInHFPD ; É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Õ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É
|
||
;
|
||
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Õre Slot $0.
|
||
Clr.b spExtDev(A0) ; DonÕ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 ÒnewÓ video hardware setup blockÉ
|
||
;
|
||
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É
|
||
;
|
||
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É
|
||
;
|
||
Cmpi.w #indexedSenseMSB1,saveMonID(A3) ; If weÕ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É
|
||
;
|
||
Tst.w csPage(A2) ; If requested page is not zero,
|
||
Bne.s CivicCtlBad ; then we canÕt help Õ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Õre at the end of the table,
|
||
Beq CivicCtlBad ; then somethingÕ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É
|
||
;
|
||
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É
|
||
;
|
||
Cmp.b dCtlSlotID(A1),D2 ; If weÕ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Õ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Õ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Õs data. But all the previous Apple video drivers
|
||
; have done the same thing here, so weÕll continue the trend for now.
|
||
|
||
Move.l (Sp),A0 ; Get ptr to csTable.
|
||
|
||
@TableLoop Move.w D2,value(A0,D1*colorSpecSize) ; Write the index into the table.
|
||
Subq #1,D2 ; Decrement index.
|
||
Dbra D1,@TableLoop ;
|
||
|
||
@GECom
|
||
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Õ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Ó.
|
||
Move.b #extendedSenseGF,D0
|
||
Bra.s @WriteExtended
|
||
|
||
@Try19 Cmp.b #indexedSense19,D0 ; Is it the 19Ó code?
|
||
Bne.s @TryRdRGB ; No, try the Radius ColorTPD.
|
||
Move.b #extendedSense19,D0
|
||
Bra.s @WriteExtended
|
||
|
||
@TryRdRGB Cmp.b #extended2PRdRGB,D0 ; Is it the ColorTPD.
|
||
Bne.s @TryRDMono ; Nope, try the Mono.
|
||
Bra.s @Write2PExtended
|
||
|
||
@TryRdMono Cmp.b #extended2PRdMono,D0 ; Is it the MonoTPD.
|
||
Bne.s @WriteIt ; Nope, assume indexed.
|
||
|
||
@Write2PExtended
|
||
Move.b #indexedSense2P,csMode+1(A2) ; Say code is type 3.
|
||
Bra.s @WriteIt
|
||
|
||
@WriteExtended Move.b #indexedNoConnect,csMode+1(A2) ; Say code is type 7.
|
||
@WriteIt Move.b D0,csMode(A2) ; Return valid monID.
|
||
|
||
@Exit Adda #SizesPRAMRec+spBlockSize,Sp ; Restore stack, and
|
||
Bra 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Õ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Õs value.
|
||
;
|
||
; Note: Civic Registers are ONLY accessible in 32-bit addressing
|
||
; mode.
|
||
;
|
||
; <- D0: The Civic registerÕ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 ³, 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É.
|
||
|
||
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Õ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 ; É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Õ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Õ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Õ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Õ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É
|
||
Cmp.b #SixthVidMode-FirstVidMode,D1 ; If weÕ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Õ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Õ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Õ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É
|
||
Cmp.b #SixthVidMode-FirstVidMode,D1 ; If weÕ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É
|
||
ADDA D1,A6 ; É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Õ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Õ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Õ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É
|
||
ADDA D1,A6 ; É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É
|
||
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Õ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 ; É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 ; É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]) ; É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
|