sys7.1-doc-wip/OS/IoPrimitives/SndPrimitives.a
2019-07-27 22:37:48 +08:00

2084 lines
85 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; File: SndPrimitives.a
;
; Contains: Low-level routines for the control of sound dependent hardware.
;
; Written by: Dave Wong, Andy Gong, Helder Ramalho
;
; Copyright: © 1991-1993 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: ROM
;
; Change History (most recent first):
;
; <SM16> 12/21/93 ged Rolled back everything from the previous checkin except minimal
; support for Yeager and Blackbird sound primitives. Additional
; Blackbird sound primitives will be rolled in when ready.
; <SM15> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM14> 10/1/93 JDR Rolled in the InstallSndPrimitives routine from Reality patches.
; System Software has SndPrimitives patches that patch certain
; machines that were never rolled into the ROM. Why wasn't any of
; this code rolled in previously? Hope it works! I did roll in
; TIMInputSelect patch. I think ElsieInputSelect might still be
; wrong.
; <SM13> 8/20/93 chp Sound interrupt primitives all referred to the ASC, which was a
; misnomer. This has been updated to reflect the appropriate level
; of abstraction in InterruptHandlers.a.
; <SM12> 8/4/93 JDR SoundPriv.a was changed to SoundPrivate.a
; <SM11> 5/25/93 joe Added vector table & stub routines for PDM.
; <SM10> 1/14/93 PN Add SndCntlMacIIsi table for Macsi sound init.
; <SM9> 12/5/92 SWC Added routines to do sound hardware initialization for
; StartInit. Added a table for DJMEMC-based machines because the
; sound init code does more stuff than the standard Batman code.
; Moved InitSndHW, InitSndNoRAM, InitSoundHW here from
; StartInit.a.
; <SM8> 12/3/92 EH Zero out entries for DFAC-related routines in the Blackbird
; table (for now).
; <SM7> 12/01/92 HY Changed default value for DFAC initialization for LCR/LCII.
; <SM6> 12/1/92 EH Added table for Blackbird.
; <SM5> 11/30/92 SWC Updated to latest Horror. Added in build conditionals.
; <H23> 11/9/92 ag Added save of d2 in baselevel inputselect routine. The routine
; was trashing d2.
; <SM4> 11/6/92 rab Roll in Horror changes. Comments follow:
; <H22> 10/15/92 NJV Changed the Vail InputSelect and SetVol primitives so that the
; UserVolume variable is treated correctly with the new scheme of
; Volume control on Vail.
; <H21> 9/10/92 NJV Added new SndCntlVail table that controls volume via DFAC rather
; than the standard ASIC volume control. Added VailInputSelect,
; changed SonoraInputSelect to call on to InputSelect rather than
; SonoraNewInputSelect.
; <H20> 7/14/92 ag Removed redundent routine adjustautosleep.
; <H19> 7/13/92 ag Added DartPlayThru and DartQueryInput routines. Added changes to
; disable playthru if input select is internal mic otherwise we
; get HORRible feedback.
; <H18> 6/29/92 GMR Added modem sound support for DB-Lite.
; <H17> 6/3/92 NJV Changed SonoraInputSelect to enable Sonora to Play and Record
; simultaneously.
; <H16> 6/03/92 HY Make LC use same sound vector table as Apollo. Add label SndCntlElsie.
; <H15> 5/19/92 ag Fixed bugs with DartInputSelect.
; <H14> 5/8/92 djw Modify DartDFACInit to not use low mem to get DecoderInfo ptr
; <H13> 5/7/92 ag Added a new table for dartanian. Moved all the tables to the end
; due to an assembler problem ??
; <H12> 05/06/92 jmp Just added a comment to the EgretDFACInit routine; no code was
; changed.
; <SM3> 9/9/92 RB Added a Sound control vector table for LC. (Same as for Classic
; II (Apollo)).
; <SM2> 5/21/92 RB Making changes for Cyclone. Change history is below: some
; comments may be duplicated due to the Pandora/Horror history.
; <P11> 5/13/92 KW (djw,H14) Modify DartDFACInit to not use low
; mem to get DecoderInfo ptr (ag,H13) Added a new table for
; dartanian. Moved all the tables to the end due to an assembler
; problem ?? (jmp,H12) Just added a comment to the EgretDFACInit
; routine; no code was changed. <P10> 4/16/92 KW (SWC, H11)
; Modified the DFAC send routine for DBLite to send the DFAC
; command byte and a byte specifying the input source.
; (NJV,H10)Changed SonoraDFACInit to reverse the order of bits
; it's sending, so that equate can be in DFAC order <P9> 03/23/92
; jmp (jmp,H9) Moved the SonoraDFACInit and SonoraInputSelect
; routines so that the Horror ROM map lines up with Zydecos. <P8>
; 03/22/92 jmp Put back <P6>. <P7> 3/19/92 FU Rolled back changes
; in <P6>. <P6> 3/18/92 FU (NJV,H8) Added SonoraDFACInit,
; SonoraInputSelect, and updated table for Sonora-based machines.
; <P5> 02/21/92 jmp Added a fake SoundPrimitives table for
; Cyclone. <P4> 02/07/92 jmp (jmp,H7/BG,Z16) Changed
; EclipseInputSelect to call ReGenSoundInt after the final
; VIA2[vBufB] reference is made. Added ReGenSoundInt. Also, moved
; the Sonora table to the end of the file to make the
; TERROR/Zydeco ROM map line up with HORRORs. <P3> 1/15/92 RP
; Added Cyclone sound stub (that will never work). <P2> 01/13/92
; jmp (SWC,H6) Found it's better if A0 points to a parameter block
; before calling _PMgrOp in DBLiteDFACSend.
; <1> 5/17/92 kc first checked in
; <SM0> 5/2/92 kc Roll in Horror. Comments follow:
; <H11> 4/13/92 SWC Modified the DFAC send routine for DBLite to send the DFAC
; command byte and a byte specifying the input source.
; <H10> 3/25/92 NJV Changed SonoraDFACInit to reverse the order of bits it's
; sending, so that equate can be in DFAC order
; <H9> 03/23/92 jmp Moved the SonoraDFACInit and SonoraInputSelect routines so that
; the Horror ROM map lines up with Zydecos.
; <H8> 3/12/92 NJV Added SonoraDFACInit, SonoraInputSelect, and updated table for
; Sonora-based machines.
; <H7> 01/27/92 jmp (BG,Z16) Changed EclipseInputSelect to call ReGenSoundInt after
; the final VIA2[vBufB] reference is made. Added ReGenSoundInt.
; Also, moved the Sonora table to the end of the file to make the
; TERROR/Zydeco ROM map line up with HORRORs.
; <H6> 1/6/92 SWC Found it's better if A0 points to a parameter block before
; calling _PMgrOp in DBLiteDFACSend.
; <H5> 12/16/91 HJR Add primitives for Dartanian.
; <H4> 12/4/91 CCH Added sound information for Vail and Carnation.
; <H3> 8/6/91 SWC Oops! Got snagged by a MOVEQ value out of range...
; <H2> 8/6/91 SWC Added DB-Lite input select routine to disable auto sleep when a
; sound source is enabled.
; <1> 12/29/91 RB first checked in
; ———————————————————————————————————————————————————————————————————————————————————————
; Pre-HORROR ROM comments begin here.
; ———————————————————————————————————————————————————————————————————————————————————————
; <15> 7/8/91 djw Take out debugger statement that I left in.
; <14> 7/8/91 djw Undid <t13> and made spike and eclipse not force AGC on in the
; input select.
; <13> 6/27/91 HJR & AG, AGCInputSelect still needs to be used in Spike and
; Eclipses InputSelect.
; <12> 6/25/91 ag (djw) Fix bug in EclipseInputSelect were you can never change
; the input source.
; <11> 6/24/91 ag added code to disable auto sleep when a sound source is enabled.
; Changed AGCcontrol to use AGCoff instead of TCAoff.
; <10> 6/24/91 HJR Added appropriate WITH statements since pmCommand and Sleepq are
; now records.
; <9> 6/13/91 djw Disable interrupts around critical code sections. Make
; InputSelect routine return old source.
; <8> 5/31/91 djw Fix bug in DB-Lite DFAC initialization due to value change
; (can't use MOVEQ)
; <7> 5/23/91 HJR Added include to PowerPrivEqu.a.
; <6> 5/10/91 djw Add new hardware recommondations for DFAC settings to lessen
; noise leakage. Roll in SWC's DBLite additions plus code
; optimizations. Changed all "jsrTBL" macro calls to not need to
; pass a register in. Added padding to end of file, added new
; Eclipse input select routine for new VIA bits MUX.
; <5> 3/18/91 djw Changed TIM to use same routines as Spike for EVT3 hardware.
; Added Apollo support. Added new sound primitive routines and
; fixed bugs in InputSelect for Eclipse.
; <4> 2/18/91 djw Have Eclipse DFAC routines always leave AGC enabled.
; <3> 2/18/91 djw Correct relative table offsets for Spike and Eclipse. Corrected
; DFAC bit on TIM from 6 to 5 (thanks to KIP). Improved DFAC TIM
; and VIA2 routines to init clock to known state.
; <2> 2/15/91 djw Add Scott Smyers changes to DFAC Init routines: use DecoderInfo
; record and clean up register use and equates. Make tables
; addresses relative, will create separate entry points for
; Eclipse, Elsie, and Erickson DFAC Init. Re-write Egret/DFAC
; routines.
; <1> 1/24/91 HJR First check in.
;
print off
LOAD 'StandardEqu.d'
include 'HardwarePrivateEqu.a'
include 'SoundPrivate.a'
include 'UniversalEqu.a'
include 'PowerPrivEqu.a'
include 'EgretEqu.a'
include 'IOPrimitiveEqu.a'
include 'SysPrivateEqu.a' ; <SM2>
include 'MMUEqu.a'
include 'BootEqu.a' ; needs MMUEqu.a
print on
print nomdir
machine mc68020
;_________________________________________________________________________________________
; Install Sound Primitives routines into ExpandMem vector
InstallSndPrimitives proc export
WITH DecoderInfo,DecoderKinds,ProductInfo,SoundIOHeader,ExpandMemRec
WITH SleepqRec,pmCommandRec,PmgrRec
IMPORT ClearSoundInt ; InterruptHandlers.a
IMPORT DisableSoundInts ; InterruptHandlers.a
IMPORT EnableSoundInts ; InterruptHandlers.a
IMPORT GetHardwareInfo ; Universal.a
IMPORT RDXBYTE ; USTPram.a
EXPORT InitSndHW, InitSndNoRAM
; Convert ROM sound primitive offset table into a RAM pointer table.
movea.l UnivInfoPtr,a1 ; a1 = ptr to productinfo record
move.l ProductInfo.SndControlPtr(a1),d0 ; get offset to sound vector tbl
adda.l d0,a1 ; a1 = ptr to ROM tbl
moveq.l #0,d0 ; clear d0
move.w SndTblLength(a1),d0 ; d0 = number of entries in table
asl.l #2,d0 ; convert long entries to byte count
addq.l #SoundIOHeaderSize,d0 ; size of global header records
_NewPtr ,sys,clear ; alloc storage
adda.l #SoundIOHeaderSize,a0 ; inc past global header
move.l a0,([Expandmem],\
ExpandMemRec.emSndPrimitives) ; set the expandmem pointer
move.b #sndAGCOff,UserAGC(a0) ; init AGC off as default
; Convert the offset values in the original table to long addresses in the RAM-based
; table. a0 = ptr to new RAM-based tbl, a1 = ptr to old ROM table
move.w SndTblLength(a1),d0 ; get number of entries in table
subq.w #1,d0 ; adjust for dbra
move.l a1,d1 ; d1 = address of ROM/RAM table
@Loop
move.l (a1)+,(a0) ; get routine offset
add.l d1,(a0)+ ; add ROM/RAM table address to convert to 32 bit address
dbra d0,@Loop
moveq.l #1,d0 ; default all cpu's with AGC on
jsrTBL sndAGCcontrol
rts
;_________________________________________________________________________________________
; Sound primitives vector table
;
; Tables pointed to by the universal ProductInfo record (SndControlPtr)
; for low level sound routines dependent on the hardware. There should
; be a table for each supported productinfo.
;
align 4
IF hasVISADecoder THEN
Export SndCntlClassicII,SndCntlLC
dc.w 0 ; flags
dc.w (SndCntlClassicIIEnd-SndCntlClassicII)/4 ; number of entries
SndCntlLC ; <H16>
SndCntlClassicII
dc.l ElsieDFACInit-SndCntlClassicII
dc.l EgretDFACSend-SndCntlClassicII
dc.l ASCSetVol-SndCntlClassicII
dc.l EnableSoundInts-SndCntlClassicII
dc.l DisableSoundInts-SndCntlClassicII
dc.l ClearSoundInt-SndCntlClassicII
dc.l ElsieInputSelect-SndCntlClassicII
dc.l QueryInput-SndCntlClassicII
dc.l ByPassControl-SndCntlClassicII
dc.l PlayThruVol-SndCntlClassicII
dc.l AGCControl-SndCntlClassicII
dc.l ASCInitSoundHW-SndCntlClassicII ; <SM9>
SndCntlClassicIIEnd
ENDIF
IF hasMDU THEN
Export SndCntlMacIIsi ; <SM10> PN.start
dc.w 0 ; flags <SM10> PN
dc.w (SndCntlMacIIsiEnd-SndCntlMacIIsi)/4 ; number of entries <SM10> PN
SndCntlMacIIsi
dc.l ElsieDFACInit-SndCntlMacIIsi
dc.l EgretDFACSend-SndCntlMacIIsi
dc.l ASCSetVol-SndCntlMacIIsi
dc.l EnableSoundInts-SndCntlMacIIsi
dc.l DisableSoundInts-SndCntlMacIIsi
dc.l ClearSoundInt-SndCntlMacIIsi
dc.l InputSelect-SndCntlMacIIsi
dc.l QueryInput-SndCntlMacIIsi
dc.l ByPassControl-SndCntlMacIIsi
dc.l PlayThruVol-SndCntlMacIIsi
dc.l AGCControl-SndCntlMacIIsi
dc.l ASCInitSoundHW-SndCntlMacIIsi ; <SM10> PN.end
SndCntlMacIIsiEnd
ENDIF
IF hasOrwell THEN
Export SndCntlQuadra900
dc.w 0 ; flags
dc.w (SndCntlQuadra900End-SndCntlQuadra900)/4 ; number of entries
SndCntlQuadra900
SndCntlQuadra950
dc.l EclipseDFACInit-SndCntlQuadra900
dc.l EgretDFACSend-SndCntlQuadra900 ; <t6>
dc.l ASCSetVol-SndCntlQuadra900
dc.l EnableSoundInts-SndCntlQuadra900
dc.l DisableSoundInts-SndCntlQuadra900
dc.l ClearSoundInt-SndCntlQuadra900
dc.l EclipseInputSelect-SndCntlQuadra900 ; <t6>
dc.l QueryInput-SndCntlQuadra900
dc.l ByPassControl-SndCntlQuadra900
dc.l PlayThruVol-SndCntlQuadra900
dc.l AGCControl-SndCntlQuadra900
dc.l BatmanInitSoundHW-SndCntlQuadra900
SndCntlQuadra900End
Export SndCntlQuadra700
dc.w 0 ; flags
dc.w (SndCntlQuadra700End-SndCntlQuadra700)/4 ; number of entries
SndCntlQuadra700
dc.l SpikeDFACInit-SndCntlQuadra700
dc.l VIA2DFACSend-SndCntlQuadra700
dc.l ASCSetVol-SndCntlQuadra700
dc.l EnableSoundInts-SndCntlQuadra700
dc.l DisableSoundInts-SndCntlQuadra700
dc.l ClearSoundInt-SndCntlQuadra700
dc.l InputSelect-SndCntlQuadra700 ; <t14>
dc.l QueryInput-SndCntlQuadra700
dc.l ByPassControl-SndCntlQuadra700
dc.l PlayThruVol-SndCntlQuadra700
dc.l AGCControl-SndCntlQuadra700
dc.l BatmanInitSoundHW-SndCntlQuadra700 ; <SM9>
SndCntlQuadra700End
ENDIF
IF hasJaws THEN
Export SndCntlPB170
dc.w 0 ; flags
dc.w (SndCntlPB170End-SndCntlPB170)/4 ; number of entries
SndCntlPB170
dc.l TimDFACInit-SndCntlPB170
dc.l VIA2DFACSend-SndCntlPB170
dc.l TimPlayBackVol-SndCntlPB170
dc.l EnableSoundInts-SndCntlPB170
dc.l DisableSoundInts-SndCntlPB170
dc.l ClearSoundInt-SndCntlPB170
dc.l TIMInputSelect-SndCntlPB170 ; <t11>
dc.l QueryInput-SndCntlPB170
dc.l ByPassControl-SndCntlPB170
dc.l PlayThruVol-SndCntlPB170
dc.l AGCControl-SndCntlPB170
dc.l JawsInitSoundHW-SndCntlPB170 ; <SM9>
SndCntlPB170End
ENDIF
IF hasNiagra THEN
Export SndCntlPB180
dc.w 0 ; flags
dc.w (SndCntlPB180End-SndCntlPB180)/4 ; number of entries
SndCntlPB180 ; <H13>
dc.l DartDFACInit-SndCntlPB180
dc.l VIA2DFACSend-SndCntlPB180
dc.l TimPlayBackVol-SndCntlPB180
dc.l EnableSoundInts-SndCntlPB180
dc.l DisableSoundInts-SndCntlPB180
dc.l ClearSoundInt-SndCntlPB180
dc.l DartInputSelect-SndCntlPB180 ; <t11>
dc.l DartQueryInput-SndCntlPB180 ; <H19>
dc.l ByPassControl-SndCntlPB180
dc.l DartPlayThruVol-SndCntlPB180 ; <H19>
dc.l AGCControl-SndCntlPB180
dc.l NiagraInitSoundHW-SndCntlPB180 ; <SM9>
SndCntlPB180End
ENDIF
IF hasMSC THEN
Export SndCntlPBDuo210
dc.w 0 ; flags
dc.w (SndCntlPBDuo210End-SndCntlPBDuo210)/4 ; number of entries
SndCntlPBDuo210
dc.l DBLiteDFACInit-SndCntlPBDuo210
dc.l DBLiteDFACSend-SndCntlPBDuo210
dc.l DBLiteSetVol-SndCntlPBDuo210 ; <H18>
dc.l EnableSoundInts-SndCntlPBDuo210
dc.l DisableSoundInts-SndCntlPBDuo210
dc.l ClearSoundInt-SndCntlPBDuo210
dc.l DBInputSelect-SndCntlPBDuo210 ; <H2>
dc.l QueryInput-SndCntlPBDuo210
dc.l ByPassControl-SndCntlPBDuo210
dc.l PlayThruVol-SndCntlPBDuo210
dc.l AGCControl-SndCntlPBDuo210
dc.l ASCInitSoundHW-SndCntlPBDuo210 ; <SM9>
SndCntlPBDuo210End ; <t6>
Export SndCntlYeager ; <t6>
dc.w 0 ; flags
dc.w (SndCntlYeagerEnd-SndCntlYeager)/4 ; number of entries
SndCntlYeager
dc.l DBLiteDFACInit-SndCntlYeager ; (sndDFACInit)
dc.l DBLiteDFACSend-SndCntlYeager ; (sndDFACSend)
dc.l DBLiteSetVol-SndCntlYeager ; (sndPlaybackVol)
dc.l EnableSoundInts-SndCntlYeager ; (sndEnableInt)
dc.l DisableSoundInts-SndCntlYeager ; (sndDisableInt)
dc.l ClearSoundInt-SndCntlYeager ; (sndClearInt)
dc.l DBInputSelect-SndCntlYeager ; (sndInputSelect)
dc.l QueryInput-SndCntlYeager ; (sndInputSource)
dc.l ByPassControl-SndCntlYeager ; (sndAuxByPass)
dc.l PlayThruVol-SndCntlYeager ; (sndPlayThruVol)
dc.l AGCControl-SndCntlYeager ; (sndAGCcontrol)
dc.l ASCInitSoundHW-SndCntlYeager ; (sndInitSoundHW)
dc.l DoNothing-SndCntlYeager ; (sndInitGlobals)
dc.l DoNothing-SndCntlYeager ; (sndModemSound)
dc.l DoNothing-SndCntlYeager ; (sndModemSndVol)
dc.l DoNothing-SndCntlYeager ; (sndGetSmplRate)
dc.l DoNothing-SndCntlYeager ; (sndSetSmplRate)
dc.l DoNothing-SndCntlYeager ; (sndGetInputGain)
dc.l DoNothing-SndCntlYeager ; (sndSetInputGain)
dc.l DoNothing-SndCntlYeager ; (sndPlayThruCntl)
dc.l DoNothing-SndCntlYeager ; (sndSoundHWCntl)
dc.l DoNothing-SndCntlYeager ; (sndSoundHWState)
dc.l DoNothing-SndCntlYeager ; (sndVirtualHWHook)
SndCntlYeagerEnd ; <t6>
ENDIF
IF hasDJMEMC THEN
EXPORT SndCntlQuadra800
dc.w 0 ; flags
dc.w (SndCntlQuadra800End-SndCntlQuadra800)/4; number of entries
SndCntlQuadra800
dc.l SpikeDFACInit-SndCntlQuadra800
dc.l VIA2DFACSend-SndCntlQuadra800
dc.l ASCSetVol-SndCntlQuadra800
dc.l EnableSoundInts-SndCntlQuadra800
dc.l DisableSoundInts-SndCntlQuadra800
dc.l ClearSoundInt-SndCntlQuadra800
dc.l InputSelect-SndCntlQuadra800
dc.l QueryInput-SndCntlQuadra800
dc.l ByPassControl-SndCntlQuadra800
dc.l PlayThruVol-SndCntlQuadra800
dc.l AGCControl-SndCntlQuadra800
dc.l DJMEMCInitSoundHW-SndCntlQuadra800 ; <SM9>
SndCntlQuadra800End
ENDIF
IF hasPratt THEN
Export SndCntlBlackbird
dc.w 0 ; flags (SuperMario style table)
dc.w (SndCntlBlackEnd-SndCntlBlackbird)/4 ; number of entries
SndCntlBlackbird
dc.l DoNothingViaA6-SndCntlBlackbird ; (sndDFACInit)
dc.l DoNothing-SndCntlBlackbird ; (sndDFACSend)
dc.l ASCSetVol-SndCntlBlackbird ; (sndPlaybackVol)
dc.l EnableSoundInts-SndCntlBlackbird ; (sndEnableInt)
dc.l DisableSoundInts-SndCntlBlackbird ; (sndDisableInt)
dc.l ClearSoundInt-SndCntlBlackbird ; (sndClearInt)
dc.l DoNothing-SndCntlBlackbird ; (sndInputSelect)
dc.l DoNothing-SndCntlBlackbird ; (sndInputSource)
dc.l DoNothing-SndCntlBlackbird ; (sndAuxByPass)
dc.l DoNothing-SndCntlBlackbird ; (sndPlayThruVol)
dc.l DoNothing-SndCntlBlackbird ; (sndAGCcontrol)
dc.l WhitneyInitSoundHW-SndCntlBlackbird ; (sndInitSoundHW)
dc.l DoNothing-SndCntlBlackbird ; (dontUse1)
dc.l DoNothing-SndCntlBlackbird ; (dontUse2)
dc.l DoNothing-SndCntlBlackbird ; (dontUse3)
dc.l DoNothing-SndCntlBlackbird ; (sndInitSoundHW2)
dc.l DoNothing-SndCntlBlackbird ; (sndInitGlobals)
dc.l DoNothing-SndCntlBlackbird ; (sndModemSound)
dc.l DoNothing-SndCntlBlackbird ; (sndModemSndVol)
dc.l DoNothing-SndCntlBlackbird ; (sndGetSmplRate)
dc.l DoNothing-SndCntlBlackbird ; (sndSetSmplRate)
dc.l DoNothing-SndCntlBlackbird ; (sndGetInputGain)
dc.l DoNothing-SndCntlBlackbird ; (sndSetInputGain)
dc.l DoNothing-SndCntlBlackbird ; (sndPlayThruCntl)
dc.l DoNothing-SndCntlBlackbird ; (sndSoundHWCntl)
dc.l DoNothing-SndCntlBlackbird ; (sndSoundHWState)
dc.l DoNothing-SndCntlBlackbird ; (sndVirtualHWHook)
SndCntlBlackEnd
ENDIF
IF hasSonora THEN
Export SndCntlSonora
dc.w 0 ; flags
dc.w (SndCntlSonoraEnd-SndCntlSonora)/4 ; number of entries
SndCntlSonora
dc.l SonoraDFACInit-SndCntlSonora
dc.l EgretDFACSend-SndCntlSonora
dc.l ASCSetVol-SndCntlSonora
dc.l EnableSoundInts-SndCntlSonora
dc.l DisableSoundInts-SndCntlSonora
dc.l ClearSoundInt-SndCntlSonora
dc.l SonoraInputSelect-SndCntlSonora
dc.l QueryInput-SndCntlSonora
dc.l ByPassControl-SndCntlSonora
dc.l PlayThruVol-SndCntlSonora
dc.l AGCControl-SndCntlSonora
dc.l BatmanInitSoundHW-SndCntlSonora ; <SM9>
SndCntlSonoraEnd
Export SndCntlLCIII
dc.w 0 ; flags
dc.w (SndCntlLCIIIEnd-SndCntlLCIII)/4 ; number of entries
SndCntlLCIII
dc.l SonoraDFACInit-SndCntlLCIII
dc.l EgretDFACSend-SndCntlLCIII
dc.l VailSetVol-SndCntlLCIII
dc.l EnableSoundInts-SndCntlLCIII
dc.l DisableSoundInts-SndCntlLCIII
dc.l ClearSoundInt-SndCntlLCIII
dc.l VailInputSelect-SndCntlLCIII
dc.l QueryInput-SndCntlLCIII
dc.l ByPassControl-SndCntlLCIII
dc.l PlayThruVol-SndCntlLCIII
dc.l AGCControl-SndCntlLCIII
dc.l BatmanInitSoundHW-SndCntlLCIII ; <SM9>
SndCntlLCIIIEnd
ENDIF
Export SndCntlCyclone
dc.w 0 ; flags
dc.w (SndCntlCycloneEnd-SndCntlCyclone)/4 ; number of entries
SndCntlCyclone
dc.l CycloneSndStubNoRam-SndCntlCyclone ; Fake em for now.
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub2-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStub1-SndCntlCyclone
dc.l CycloneSndStubNoRam-SndCntlCyclone ; <SM9>
SndCntlCycloneEnd
Export SndCntlPDM
dc.w 0 ; flags
dc.w (SndCntlPDMEnd-SndCntlPDM)/4 ; number of entries
SndCntlPDM ; Fake 'em
dc.l PDMSndStubNoRam-SndCntlPDM ; For machines that need to init DFAC via Egret
dc.l PDMSndStub1-SndCntlPDM ; For machines that use Egret to talk to DFAC
dc.l PDMSndStub1-SndCntlPDM ; Set Volume
dc.l PDMSndStub1-SndCntlPDM ; Enable Sound Interrupts
dc.l PDMSndStub1-SndCntlPDM ; Disable Sound Interrupts
dc.l PDMSndStub1-SndCntlPDM ; Clear Sound Interrupt(s)
dc.l PDMSndStub1-SndCntlPDM ; Input Select
dc.l PDMSndStub2-SndCntlPDM ; Query which input device(s) is/are selected
dc.l PDMSndStub1-SndCntlPDM ; Enable/Disable Aux Bypass
dc.l PDMSndStub1-SndCntlPDM ; Set PlayThru Volume
dc.l PDMSndStub1-SndCntlPDM ; Enable/Disable AGC
dc.l PDMSndStubNoRam-SndCntlPDM ; InitSoundHW - called by StartInit to set vol
SndCntlPDMEnd
;••••••••••••••••••••••••••••••••••• Common Routines ••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————— <SM9>
; Routine: InitSndHW
;
; Inputs: none
;
; Outputs: none
;
; Trashes: D0-D1
;
; Function: This routine is meant to be called after lowmem has been setup.
; It calls common RAM-less code in the system to initialize the
; sound hardware.
;——————————————————————————————————————————————————————————————————————————————
InitSndHW movem.l d3-d4/a0-a6,-(sp)
movea.l UnivInfoPtr,a1 ; point to the machine's ProductInfo table
MOVEA.L A1,A0
adda.l ProductInfo.DecoderInfoPtr(a0),a0 ; and to its DecoderInfo table
move.b SdVolume,d0 ; get the sound volume
moveq.l #1,d1 ; flag RAM routine origin for InitSoundHW <ged>
bsr6 InitSoundHW ; initialize the sound hardware (trashes d0-d4/a0-a6)
movem.l (sp)+,d3-d4/a0-a6
rts
;—————————————————————————————————————————————————————————————————————————————— <SM9>
; Routine: InitSndNoRAM
;
; Inputs: A5 - return address
;
; Outputs: none
;
; Trashes: D0-D4, A0-A6
;
; Function: called by BSR5 to initialize sound hardware without using RAM
;——————————————————————————————————————————————————————————————————————————————
InitSndNoRam
move.l a5,d3 ; save return addr in d3
; Setup necessary registers
moveq.l #0,d2 ; decoder unknown
bsr6 GetHardwareInfo ; get decoder address (trashes d0-d2/a0-a2/a5/a6)
movea.l DecoderInfo.VIA1Addr(a0),a2 ; get VIA1 base addr for PRAM routine
; Call start test utility to read sound volume from pram
move.w #$10,d1 ; pram addr of validation byte
bsr6 RdXByte ; trashes d0,d2,a0,a3,a4,a5
cmpi.b #$a8,d1 ; is PRAM valid?
beq.s @pramValid ; pram is valid
moveq.l #5,d1 ; pram invalid - fake a volume level of 5
bra.s @skipRead
@pramValid
move.w #8,d1 ; pram addr of sound volume
bsr6 RdXByte ; trashes d0,d2,a0,a3,a4,a5
@skipRead
and.b #%00000111,d1 ; mask volume bits
bne.s @nonZeroVol ; a good non-zero volume
move.b #5,d1 ; set minimum volume for boot beep
@nonZeroVol
move.b d1,d4 ; save pram value
; Setup registers again
moveq.l #0,d2 ; decoder unknown
bsr6 GetHardwareInfo ; get decoder address (trashes d0-d2/a0-a2/a5)
move.b d4,d0 ; restore volume
moveq.l #0,d1 ; flag RAMless routine origin for InitSoundHW <SMXX>
bsr6 InitSoundHW ; init sound (trashes d0-d1/a3/a6)
movea.l d3,a5 ; restore return address
rts5
;—————————————————————————————————————————————————————————————————————————————— <SM9>
; Routine: InitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; A0 - pointer to DecoderInfo table
; A1 - pointer to ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0-D1, A3
;
; Function: This routine is called by routines which can use RAM, and RAM-less
; routines. It is a central place in the ROM where all sound hardware
; initialization should happen.
;——————————————————————————————————————————————————————————————————————————————
InitSoundHW MOVEA.L A1,A3 ; get the ProductInfo pointer <SM82>
ADDA.L SndControlPtr(A3),A3 ; point to the sound primitives table <SM82>
ADDA.L sndInitSoundHW*4(A3),A3 ; and then to the routine to initialize sound hardware <SM82>
JMP (A3) ; call the routine (will return with RTS6) <SM82>
IF hasASC THEN
;——————————————————————————————————————————————————————————————————————————————
; ASCSetVol - Set the playback volume on normal ASC/Batman hardware
;
; Set the playback volume using the volume control register on Batman.
;
; Input: d0.b = volume level (0-7)
; Output: none
;
ASCSetVol move.l a0,-(sp)
movea.l ASCBase,a0 ; get base address of asc/batman
lsl.b #5,d0 ; shift volume up to pwm position
move.b d0,ascVolControl(a0) ; save it in ASC volume register
movea.l (sp)+,a0
rts
;——————————————————————————————————————————————————————————————————————————————
;
; Routine: ASCInitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; A0 - pointer to machine's DecoderInfo table
; A1 - pointer to machine's ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0,A3
;
; Function: called by BSR6 from StartInit to set the default volume for ASC
; based machines
;——————————————————————————————————————————————————————————————————————————————
ASCInitSoundHW
MOVEA.L ASCAddr(A0),A3 ; point to the base of the ASC
ASL.B #5,D0 ; shift the sound volume into the upper 3 bits
MOVE.B D0,ascVolControl(A3) ; and set the volume
RTS6
;——————————————————————————————————————————————————————————————————————————————
;
; Routine: BatmanInitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; A0 - pointer to machine's DecoderInfo table
; A1 - pointer to machine's ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0,A3
;
; Function: called by BSR6 from StartInit to set the default volume for Batman
; based machines
;——————————————————————————————————————————————————————————————————————————————
BatmanInitSoundHW
MOVEA.L ASCAddr(A0),A3 ; point to the base of the ASC
ASL.B #5,D0 ; shift the sound volume into the upper 3 bits
MOVE.B D0,ascVolControl(A3) ; and set the volume
MOVE.W #$7F00,bmLeftScaleA(A3) ; pan channel A full left
MOVE.W #$007F,bmLeftScaleB(A3) ; pan channel B full right
FinishBatmanInit
MOVEQ #1,D0
MOVE.B D0,bmIntControlA(A3) ; mask sound interrupts on channels A & B
MOVE.B D0,bmIntControlB(A3)
ORI.B #$80,ascFifoControl(A3) ; toggle the clear FIFO bit
ANDI.B #$7F,ascFifoControl(A3)
MOVE.B #2,ascPlayRecA(A3) ; set to play mode at 22KHz
MOVE.B D0,ascMode(A3) ; set to FIFO mode
MOVEQ #0,D0
MOVE.B D0,bmFifoControlA(A3) ; force Batman to do mode-change housekeeping
MOVE.B D0,bmFifoControlB(A3)
MOVE.W #$812F,bmSrcTimeIncrA(A3) ; set sample rate to 22.254.5454 kHz on channels A & B
MOVE.W #$812F,bmSrcTimeIncrB(A3)
MOVE.W D0,$F10(A3) ; initialize the CD-XA coefficients for channel A
MOVE.W #$003C,$F12(A3)
MOVE.W #$CC73,$F14(A3)
MOVE.W #$C962,$F16(A3)
MOVE.W D0,$F30(A3) ; initialize the CD-XA coefficients for channel B
MOVE.W #$003C,$F32(A3)
MOVE.W #$CC73,$F34(A3)
MOVE.W #$C962,$F36(A3)
MOVE.B #$80,bmFifoControlA(A3) ; turn on Sample Rate Conversion (SRC) for channels A & B
MOVE.B #$80,bmFifoControlB(A3)
RTS6
ENDIF ; {hasASC}
;——————————————————————————————————————————————————————————————————————————————
; InputSelect - Select the sound input source
;
; If we are selecting "none" for the input source, then turn off the volume
; and AGC to prevent any noise leakage. Save the old volume and restore it
; later when a new source is selected.
;
; AGCInputSelect
; On Tim and Spike, sound input does not work unless AGC is enabled. We
; kludge something to always set AGC.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; Output: d0.b last source
;
AGCInputSelect
tst.b d0 ; turning on sound input? <t6>
beq.s InputSelect ; no - go ahead and turn off sound input <t6>
or.b #sndAGCOn,d0 ; this fixes buggy hardware <t6>
InputSelect
@saveregs reg d1-d2/a0-a1 ; added d2 to save registers <H23>
movem.l @saveregs,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
moveq.l #3,d2 ; get selection bits to return <t9>
and.b DFAClast(a0),d2 ; save for return <t9>
moveq #(sndSelectMask\ ; <t6>
AND sndPlayThruMask\
AND sndAGCMask),d1 ; mask off selection, volume, and AGC bits
and.b DFAClast(a0),d1 ; in the DFAC register image <t6>
or.b d0,d1 ; and OR them into DFAC image <t6>
; Check for volume and AGC to update in DFAC now that a sound source has been selected.
; If we are disabling input, then zero the volume and disable AGC to prevent noise
; leakage, otherwise set the currently selected volume and AGC levels.
tst.b d0 ; are we turning off input?
beq.s @send ; yes - set no input and zero volume
or.b UserVolume(a0),d1 ; set volume level
cmpi.b #sndMicrophone,d0 ; are we selecting the mike input? <H13>
bne.s @send ; no - do not enable AGC <H13>
or.b UserAGC(a0),d1 ; set AGC level <t6>
@send
move.b d1,d0 ; d0 = new DFAC value
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem <t6>
move.w (sp)+,sr ; enable ints <t9>
move.b d2,d0 ; return source bits we replaced <t9>
movem.l (sp)+,@saveregs
rts
;——————————————————————————————————————————————————————————————————————————————
; QueryInput - return current input source selected
;
; Input: none
; Output: d0.b input source
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
QueryInput move.l a0,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
moveq #~(sndSelectMask-256),d0 ; mask off selection bits <t6>
and.b DFAClast(a0),d0 ; in the DFAC register image <t6>
movea.l (sp)+,a0
rts
;—————————————————————————————————————————————————————————————————————————————— <t6>
; ByPassControl - enable or disable aux bypass
;
; Input: d0.b = 0 is disable, nonzero is enable
; Output: none
;
ByPassControl
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
moveq.l #sndByPassOff,d1 ; assume bypass off
tst.b d0 ; enable or disable bypass
beq.s @continue ; was bypass off
moveq.l #sndByPassOn,d1 ; set bypass on
@continue move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
moveq #sndByPassMask-256,d0 ; mask off bypass control bit
and.b DFAClast(a0),d0 ; in the DFAC register image
or.b d1,d0 ; d0 = value to send DFAC
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem
move.w (sp)+,sr ; enable ints <t9>
movem.l (sp)+,@saveregs
rts
;—————————————————————————————————————————————————————————————————————————————— <t6>
; PlayThruVol - Set the playthrough volume
;
; If a sound source has not been selected, then save the volume in the globals
; to be updated to DFAC later when the source is selected. Also set playback
; volume for consistancy.
;
; Input: d0.b = volume level (0-7)
; Output: none
;
PlayThruVol
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
asl.b #5,d0 ; shift volume into s5-s7 position
move.b d0,UserVolume(a0) ; save user set volume level
moveq #(sndSelectMask-256),d1 ; mask off selection bits
and.b DFAClast(a0),d1 ; in the DFAC register image
beq.s @Done ; no sound source - we are done
moveq #sndPlayThruMask,d1 ; mask off volume bits
and.b DFAClast(a0),d1 ; in the DFAC register image
or.b d1,d0 ; or-in value to send DFAC to set volume
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem
@Done
move.w (sp)+,sr ; enable ints <t9>
movem.l (sp)+,@saveregs
rts
;—————————————————————————————————————————————————————————————————————————————— <t6>
; AGCControl - enable or disable AGC
;
; Enable or disable AGC. If no sound source has been selected, then
; save the AGC value and set it whenever the sound source is selected.
;
; Input: d0.b = 0 is disable, nonzero is enable
; Output: none
;
AGCControl
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
moveq.l #sndAGCOff,d1 ; assume AGC off (min gain) <t11>
tst.b d0 ; enable or disable AGC
beq.s @continue ; was disable AGC
moveq.l #sndAGCOn,d1 ; enable AGC
@continue
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
move.b d1,UserAGC(a0) ; save value
moveq #(sndSelectMask-256),d0 ; mask off selection bits
and.b DFAClast(a0),d0 ; in the DFAC register image
beq.s @Done ; no sound source - we are done
moveq #sndAGCMask-256,d0 ; mask off the AGC control bits
and.b DFAClast(a0),d0 ; in the DFAC register image
or.b d1,d0 ; or-in AGC value to send to DFAC
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem
@Done
move.w (sp)+,sr ; enable ints <t9>
movem.l (sp)+,@saveregs
rts
IF hasVISADecoder THEN
;••••••••••••••••••••••••••••••••••••••••• VISA •••••••••••••••••••••••••••••••••••••••••
;——————————————————————————————————————————————————————————————————————————————
; ElsieInputSelect - Select the sound input source on Elsie
;
; If we are turning off the source (equivalent to disabling recording), then
; re-establish the playback mode by selecting the Aux source with AGC on and
; playthrough volume set to the maximum.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; Output: none
;
; NOTE: System software has a different version of this being patched in ?!?!?
ElsieInputSelect
cmpi.b #sndMicrophone,d0 ; are we selecting the mike?
beq InputSelect ; yes - continue
; In Elsie sound, the playthrough with the auxiliary source is how playback is
; done. If not selecting mike, then enable playback
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
; movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
; moveq #(sndSelectMask\ ; <t6>
; AND sndPlayThruMask\
; AND sndAGCMask),d0 ; mask off selection, volume, and AGC bits
; and.b DFAClast(a0),d0 ; get DFAC register image
moveq #sndElsieDFAC-256,d0 ; DFAC playback mode for Elsie sound <t6>
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem <t6>
movem.l (sp)+,@saveregs
rts
ENDIF ; {hasVISADecoder}
IF hasEgret THEN
;••••••••••••••••••••••••••••••••••••••••• Egret ••••••••••••••••••••••••••••••••••••••••
WITH EgretPB
Import SendEgretCmd
;——————————————————————————————————————————————————————————————————————————————
; EgretDFACInit - send a byte to DFAC using Egret
;
; Use this routine during initialization before traps are enabled.
;
; Input: a6.l = return address
; a0.l = Pointer to Base address table
;
; Output: none
; Destroys: d0-d2/a2-a3
; Called by: bsr6
;
IF hasSonora THEN
SonoraDFACInit
moveq #sndSonoraReverseDFAC,d0 ; DFAC data to send for Elsie <SM5>
bra.s EgretDFACInit
ENDIF
IF hasOrwell THEN
EclipseDFACInit
moveq #sndEclipseDFAC,d1 ; DFAC data to send for Eclipse <t6>
bra.s EgretDFACInit
ENDIF
IF hasVISADecoder THEN
ElsieDFACInit
move.l #ElsieDFAC,d1 ; DFAC data to send for Elsie <SM7>
**** bra.s EgretDFACInit
ENDIF
EgretDFACInit
movea.l a6,a3 ; save return address
move.l #(WrDFAC<<16) | PseudoPkt,d0 ; Send DFAC command
moveq #DFACInitLen,d2 ; number of bytes of DFAC data
bigbsr6 SendEgretCmd,a2 ; send the command to Egret
tst.w d0 ; negative if error
jmp (a3) ; return to the caller
;——————————————————————————————————————————————————————————————————————————————
; EgretDFACSend - send a byte to DFAC using Egret
;
; Use this routine during runtime after traps are enabled.
;
; Input: d0.b = byte to send DFAC (in DFAC order)
; Output: none
;
EgretDFACSend
@saveregs reg d1-d3/a0-a1
movem.l @saveregs,-(sp) ; work register
; Reverse the order of the bits because Egret shifts them out in reverse order
; to what DFAC is expecting MSB first.
move.l d0,d3 ; save DFAC value in DFAC order
moveq #0,d1 ; destination
moveq #8-1,d2 ; loop count for 8 bits
@Loop
asr.b #1,d0 ; shift lsb into extend bit
roxl.b #1,d1 ; shift extend bit towards msb
dbra d2,@Loop
; Build a Parameter block for the default DFAC message
suba.w #EgretPbSize,sp ; make room for PB
movea.l sp,a0 ; point a0 to pbBuffer
move.b #pseudoPkt,pbCmdType(a0)
move.b #WrDFAC,pbCmd(a0)
move.w #1,pbByteCnt(a0) ; set byte count
clr.l pbBufPtr(a0) ; clear unused fields
clr.w pbFlags(a0)
clr.w pbResult(a0)
clr.l pbCompletion(a0)
move.b d1,pbParam(a0) ; set byte to send DFAC
_EgretDispatch
adda.w #EgretPbSize,sp ; discard the parameter block and data buffer
bne.s @Done ; some error - do not update image of DFAC
; Update the RAM image of the DFAC register
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
move.b d3,DFAClast(a0) ; update DFAC register image
@Done
movem.l (sp)+,@saveregs
rts ; Return to Caller
ENDWITH ; {EgretPB}
ENDIF ; {hasEgret}
IF hasOrwell THEN
;••••••••••••••••••••••••••••••••••••••••• Orwell •••••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————— <t6>
; EclipseInputSelect - Select the sound input source on Eclipse
;
; On Eclipse, the sound input source is selected by two bits on VIA2 port B
; register in addition to DFAC. There are four sound input sources on
; Eclipse: Microphone (or none?), RCA jacks, Microphone, and the CD (aux).
; These sources are selected through the VIA2 bits and routed through DFAC.
;
; If we are selecting "none" for the input source, then turn off the volume
; and AGC to prevent any noise leakage. Save the old volume and restore it
; later when a new source is selected.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; 3 = RCA jacks
; Output: none
;
EclipseInputSelect
move.w sr,-(sp) ; <t12> djw
ori.w #HiIntMask,sr ; <t12> djw
movem.l d0-d1,-(sp) ; <t12> djw
move.b ([via2],vBufB),d1 ; read current via values <t12> djw
and.b #%10110111,d1 ; clear the previous value (bits pb6,pb3) <t12> djw
andi.w #$ff,d0 ; make a word index
or.b EclipseSelectTable(pc,d0.w),d1 ; set new input <t12> djw
move.b d1,([via2],vBufB) ; set via2 bits
bsr.s ReGenSoundInt ; since VIA2 access clear interrupts, fix em <Z16> BG
movem.l (sp)+,d0-d1 ; <t12> djw
move.w (sp)+,sr ; <t12> djw
tst.b d0 ; selecting no source?
beq InputSelect ; yes - ok to go setup DFAC <t14> djw
moveq.l #sndMicrophone,d0 ; all sound sources go through DFAC mike input
bra InputSelect ; <t14> djw
EclipseSelectTable
dc.b %00000000 ; none (or microphone?) pb6=0, pb3=0
dc.b %01000000 ; microphone pb6=1, pb3=0
dc.b %01001000 ; auxilary (CD) pb6=1, pb3=1
dc.b %00001000 ; RCA jacks pb6=0, pb3=1
;_______________________________________________________________________ <Z16> thru next <Z16> <Z18> thru next <Z18>
;
; Routine: ReGenSoundInt
;
; Desc: Since reading VIAx[vBufB] causes interrupts to cleared,
; this re-generates those sound interrupts.
;
; This routine stolen from
;
; {Regatta}Toolbox:SoundMgr:SoundMgrPatch.a
;
;_______________________________________________________________________
interruptControlA EQU $F09 ; interrupt mask registers for Batman
interruptControlB EQU $F29
ReGenSoundInt
move.l a1,-(sp) ; save A1 so we can play with it
movea.l VIA2,a1 ; grab the address of VIA2
cmpa.l #-1,a1 ; check if it's been set up yet
beq.s @rts ; exit if not
btst.b #ifCB1,vIFR(a1) ; check if we still think there's an interrupt
bne.s @rts ; yes, we still have an interrupt - exit
movea.l ASCBase,a1 ; point to Batman
cmpa.l #-1,a1 ; check if it's been set up yet
beq.s @rts ; exit if not
move.w sr,-(sp) ; preserve the status register
ori.w #$0700,sr ; mask interrupts
tst.b interruptControlA(a1) ; channel A interrupt enabled?
bne.s @checkB ; BRIF not enabled
move.b #1,interruptControlA(a1) ; disable chnl A interrupts
nop ; give Batman time to process the disable
clr.b interruptControlA(a1) ; clear the interrupt mask to re-generate
@checkB
tst.b interruptControlB(a1) ; channel B interrupt enabled?
bne.s @Done ; interrupt not enabled - done
; To re-generate Batman interrupts, first disable interrupts on both channels,
; then re-enable them.
@reGen
move.b #1,interruptControlB(a1) ; disable chnl B interrupts
nop ; give Batman time to process the disable
clr.b interruptControlB(a1) ; clear the interrupt mask to re-generate
@Done move.w (sp)+,sr
@rts move.l (sp)+,a1 ; restore original value of A1
rts ; <Z16>
ENDIF ; {hasOrwell}
IF hasJaws THEN
;••••••••••••••••••••••••••••••••••••••••• Jaws •••••••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————— <r8> thru next <r8> djw
; TIMInputSelect - Select the sound input source on Tim
;
; On Tim, the input selection routine in ROM always turns AGC on. Patch
; it out to not force AGC on.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim)
; Output: d0.b last source
;
AutoSlpDisable equ $f8 ; Counting semaphor to disable sleep
TIMInputSelect
@workingReg reg d2/a0-a1
move.w sr,-(sp) ; save the old sr
movem.l @workingReg,-(sp) ; save working registers
move.l PmgrBase,a1 ; point a1 to globals
movea.l ([Expandmem],emSndPrimitives),a0 ; a0 = ptr to vector table
ori.w #HiIntMask,sr ; disable ints
moveq.l #3,d2 ; get selection bits
and.b DFAClast(a0),d2 ;
beq.s @currentlyOff ; is a source active ??
@currentlySelected ; sound source currently selected
tst.b d0 ; check new state,
bne.s @setsource ; if just new source, set the source
subq.b #1,AutoSlpDisable(a1) ; ... if turning off source, dec the nosleep semaphore
bra.s @setsource
@currentlyOff ; sound source currently off
tst.b d0 ; check new state,
beq.s @setsource ; if new source still off, set the source
addq.b #1,AutoSlpDisable(a1) ; ... if turning on source, inc the nosleep semaphore
; bra.s @setsource
@setsource
movem.l (sp)+,@workingReg ; restore working registers
bsr InputSelect ; change the source <r10> djw
move.w (sp)+,sr ; enable ints
rts
;——————————————————————————————————————————————————————————————————————————————
; TimPlayBackVol - Set the playback volume on Tim
;
; Tim uses the left and right scale registers to control the volume. Volume
; levels 0-7 are table mapped. Also should also set playthrough volume for
; consistancy.
;
; Input: d0.b = volume level (0-7)
; Output: none
;
TimPlayBackVol
move.l a0,-(sp)
andi.w #$ff,d0 ; mask to word index <t6>
move.b @TimVolumeTable(d0.W),d0 ; index into tbl to get mapped volume value <t6>
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
movea.l ASCBase,a0 ; get base address of asc/batman
move.b d0,bmLeftScaleA(a0) ; channel A plays out left speaker at this volume
move.b #0,bmRightScaleA(a0) ; channel A does not play out of the right speaker at all
move.b #0,bmLeftScaleB(a0) ; channel B does not play out of the left speaker at all
move.b d0,bmRightScaleB(a0) ; channel B plays out right speaker at this volume
move.w (sp)+,sr ; enable ints <t9>
movea.l (sp)+,a0
rts
; Table of values to jam into the Batman scale registers for each sound volume setting (0..7)
@TimVolumeTable
dc.b 1, 18, 36, 54, 72, 90, 108, 127
align 4
ENDIF ; {hasJaws}
IF hasNiagra THEN
;••••••••••••••••••••••••••••••••••••••••• Niagra •••••••••••••••••••••••••••••••••••••••
;——————————————————————————————————————————————————————————————————————————————
; DartQueryInput - return current input source selected
;
; Input: none
; Output: d0.b input source
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Dart)
DartQueryInput
bsr.s QueryInput ;
tst.b d0 ;
beq.s @done ; if off, done
move.l a0,-(sp) ; save a0
movea.l UnivInfoPtr,a0 ; point to the ProductInfo table,
adda.l DecoderInfoPtr(a0),a0 ; then to the DecoderInfo table,
movea.l JAWSAddr(a0),a0 ; then to the Niagra base address,
adda.l #(NiagraGUR+PontiSndCtl),a0 ; point sound control register
move.b #sndSelectAux,d0 ; assume modem sound
btst.b #PontiSndMux1,(a0) ; check for modem sound override
bne.s @returninput ; if override bit, return current d0 value
move.b #sndSelectMike,d0 ; set to mike
@returninput
move.l (sp)+,a0 ; restore a0 |
; V
@done rts ; <H19>
;——————————————————————————————————————————————————————————————————————————————
; DartPlayThruVol - Set the playthrough volume
;
; If a sound source has not been selected, then save the volume in the globals
; to be updated to DFAC later when the source is selected. Also set playback
; volume for consistancy. In Dart's case, playthru is disabled (set to 0) if
; the internal microphone is used. This prevents HORRible feedback.
;
;
;
; Input: d0.b = volume level (0-7)
; Output: none
;
DartPlayThruVol
@saveregs reg d1/a0
; get the current source
movem.l @saveregs,-(sp) ; save working set of registers
move d0,d1 ; use d1 for volume until later
bsr.s DartQueryInput ; get the current source
cmp.b #sndSelectMike,d0 ; is the mike selected,
bne.s @setvol ; if not mike, just set the volume
; get pointer to sound control register
movea.l UnivInfoPtr,a0 ; point to the ProductInfo table,
adda.l DecoderInfoPtr(a0),a0 ; then to the DecoderInfo table,
movea.l JAWSAddr(a0),a0 ; then to the Niagra base address,
adda.l #(NiagraGUR+PontiSndCtl),a0 ; point sound control register
; check for internal mike
btst.b #PontiSndIntMic,(a0) ; check for internal microphone operation
beq.s @setvol ; if external microphone, allow playthru
move.b #0,d1 ; ... else set playthru to off
@setvol move.b d1,d0 ; move volume back to d0
movem.l (sp)+,@saveregs ; restore working set
bra PlayThruVol ; set playthru volume
;—————————————————————————————————————————————————————————————————————————————— <t6>
; DartInputSelect - <H13> Select the sound input source on Dartanian
;
; If we are selecting "none" for the input source, then turn off the volume
; and AGC to prevent any noise leakage. Save the old volume and restore it
; later when a new source is selected. If a source has been selected, then
; disable auto sleep otherwise enable auto sleep
;
; On Dart however, there is an additional sound mux in front of DFAC. For sound
; input selection, we will use this hardware instead of that in DFAC. All sound input
; will feed through DFAC's mike input port.
;
; On Dart ,as on TIM, sound input does not work unless AGC is enabled. We
; kludge something to always set AGC.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim)
; Output: d0.b last source
;
DartInputSelect
@workingreg reg d1/a0
move.w sr,-(sp) ; save the old sr
movem.l @workingreg,-(sp) ; save working register
; get pointer to sound control register
movea.l UnivInfoPtr,a0 ; point to the ProductInfo table,
adda.l DecoderInfoPtr(a0),a0 ; then to the DecoderInfo table,
movea.l JAWSAddr(a0),a0 ; then to the Niagra base address,
adda.l #(NiagraGUR+PontiSndCtl),a0 ; point sound control register
bclr.b #PontiSndMux0,(a0) ; default to auto mike selection
ori.w #HiIntMask,sr ; disable ints
; determine is we should use the modem override
cmp.b #sndSelectAux,d0 ; is the new input the modem channel
bne.s @modemOFF
@modemON ; don't preset, might cause "pop"
bset.b #PontiSndMux1,(a0) ; set modem sound override
bra.s @exitsndmux
@modemOFF
bclr.b #PontiSndMux1,(a0) ; clr modem sound override
@exitsndmux
move.l d0,d1 ; save the source information
bsr.s HandleAutoSleep ; handle autosleep semaphore
; disable Playthru if using internal mike
tst.b d0 ; test the new input source <H19>
cmp.b #sndSelectMike,d0 ; if it the mic ? <H19>
blt.s @setsource ; (case 0) no sources <H19>
bgt.s @modemsource ; (case 2) modem sound source <H19>
; <H19>
btst.b #PontiSndIntMic,(a0) ; check for internal microphone operation <H19>
beq.s @modemsource ; if external microphone, allow playthru <H19>
; <H19>
move.b #0,d0 ; set playthru to off <H19>
bsr.s PlayThruVol ; <H19>
@modemsource
moveq #sndSelectMike,d0 ; on dart all inputs through mike port on DFAC
@setsource
bsr.s AGCInputSelect ; change the source
move.l d1,d0 ; restore the source information
movem.l (sp)+,@workingreg ; restore register
move.w (sp)+,sr ; enable ints
rts
ENDIF ; {hasNiagra}
IF hasJaws | hasNiagra THEN
;——————————————————————————————————————————————————————————————————————————————
;
; Routine: JawsInitSoundHW,NiagraInitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; A0 - pointer to machine's DecoderInfo table
; A1 - pointer to machine's ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0,D1,A3
;
; Function: Called by BSR6 from StartInit to set the default volume for Jaws
; and Niagra based machines. Their Batman implementation is different
; from "standard" Batman since they do volume control using the scale
; registers.
;——————————————————————————————————————————————————————————————————————————————
JawsInitSoundHW
NiagraInitSoundHW
MOVEQ #18,D1 ; map volume to scale value
MULU D0,D1
MOVEA.L ASCAddr(A0),A3 ; point to the base of the ASC
ASL.B #5,D0 ; shift the sound volume into the upper 3 bits
MOVE.B D0,ascVolControl(A3) ; and set the volume
MOVE.B D1,bmLeftScaleA(A3) ; channel A plays out left speaker at this volume
MOVE.B #0,bmRightScaleA(A3) ; channel A does not play out of the right speaker at all
MOVE.B #0,bmLeftScaleB(A3) ; channel B does not play out of the left speaker at all
MOVE.B D1,bmRightScaleB(A3) ; channel B plays out right speaker at this volume
BRA FinishBatmanInit ; finish up with normal initialization
ENDIF
IF hasPwrControls THEN
;••••••••••••••••••••••••••••••••••••• Power Manager ••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————— <t6>
; HandleAutoSleep - handle the auto sleep semaphore
;
; this code handles the autosleep semaphore. when an input source is selected,
; we increment the semaphore to disable auto sleep. care must be taken to not
; increment the semaphone when changing between microphone and aux, this does
; not change the semaphore state.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim)
;
; a0 pointer to primitives table and globals
;
; Output: d0.b last source
;
HandleAutoSleep
@workingreg reg d2/a0-a1
movem.l @workingreg,-(sp) ; save working registers
move.l PmgrBase,a1 ; point a1 to globals
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
moveq.l #3,d2 ; get selection bits
and.b DFAClast(a0),d2 ;
beq.s @currentlyOff ; is a source active ??
@currentlySelected ; sound source currently selected
tst.b d0 ; check new state,
bne.s @exit ; if just new source, set the source
subq.b #1,AutoSlpDisable(a1) ; ... if turning off source, dec the nosleep semaphore
bra.s @exit
@currentlyOff ; sound source currently off
tst.b d0 ; check new state,
beq.s @exit ; if new source still off, set the source
addq.b #1,AutoSlpDisable(a1) ; ... if turning on source, inc the nosleep semaphore
@exit
movem.l (sp)+,@workingreg ; restore working registers
rts
ENDIF ; {hasPwrControls}
IF hasMSC THEN
;•••••••••••••••••••••••••••••••••••••••••• MSC •••••••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————— <t6>
; DBLiteDFACInit - send a byte to DFAC using the PMGR micro
;
; Use this routine during initialization before traps are enabled.
;
; Input: D0.B = byte to have the PMGR stuff into DFAC
; A0.L = ptr to DecoderInfo record
; A6.L = return address
; Output: none
; Destroys: D3-D4/D6/A2-A4/A5
; Called by: BSR6
;
IMPORT USTPMGRSendByte
DBLiteDFACInit
MOVEQ #sndDBLiteDFAC-256,D0 ; <t8>
MOVEA.L DecoderInfo.VIA1Addr(A0),A2 ; point to the base of VIA 1
MOVEA.L DecoderInfo.VIA2Addr(A0),A3 ; point to the base of VIA 2
MOVEQ #SetDFAC-256,D3 ; send the command <H3>
BIGBSR5 USTPMGRSendByte,A4
MOVE.B D0,D3 ; send the DFAC initialization value
BIGBSR5 USTPMGRSendByte,A4
MOVEQ #sndInputOff,D3 ; send the input source (none) <H11>
BIGBSR5 USTPMGRSendByte,A4 ; <H11>
RTS6
;—————————————————————————————————————————————————————————————————————————————— <t6>
; DBLiteDFACSend - send a byte to DFAC using the PMGR micro
;
; Use this routine during runtime after traps are enabled.
;
; Input: d0.b = byte to send DFAC (in DFAC order)
; Output: none
;
DBLiteDFACSend
@saveRegs REG D1/A0
MOVEM.L @saveRegs,-(SP)
MOVEA.L ([Expandmem],emSndPrimitives),A0; get the pointer to the vector table <H11>
MOVE.B D0,DFAClast(A0) ; and update the DFAC register image <H11>
MOVEQ #3,D1 ; mask off the input source <H11>
AND.B D0,D1 ; <H11>
CMPI.B #sndSelectAux,d1 ; is the aux modem sound selected? <H18>
BNE.S @nonAux ; no, use standard DFAC byte from table <H18>
MOVE.B @dfacTable(d1),d1 ; yes, get modem dfac byte <H18>
MOVEA.L ASCBase,a0 ; get base address of asc/batman <H18>
MOVE.B ascVolControl(a0),d0 ; get current ASC volume, <H18>
ANDI.B #$E0,d0 ; use as DFAC attenuation <H18>
OR.B d1,d0 ; bits for modem volume <H18>
MOVEQ #sndSelectAux,d1 ; <H18>
BRA.S @dfac ; and set DFAC <H18>
@nonAux MOVE.B @dfacTable(D1),D0 ; get the appropriate DFAC command byte <H11>
@dfac LSL.W #8,D0 ; move the DFAC command <H11>
OR.B D1,D0 ; include the desired input selection <H11>
MOVE.W D0,-(SP) ; put the bytes to send in a buffer on the stack<H11>
MOVE.L SP,-(SP) ; pmRBuffer points to it to be safe
MOVE.L (SP),-(SP) ; pmSBuffer points to it
MOVE.W #2,-(SP) ; pmLength <H11>
MOVE.W #SetDFAC,-(SP) ; pmCommand
MOVEA.L SP,A0 ; point to the parameter block <H6>
_PMgrOp ; have the PMGR stuff the byte in DFAC
LEA pmData+2(SP),SP ; toss the parameter block and buffer
MOVEM.L (SP)+,@saveRegs
RTS
@dfacTable DC.B (7<<5)|sndByPassOff|sndTCAOff|sndSelectAux ; 0 = no input source (i.e., play)
DC.B (0<<5)|sndByPassOff|sndAGCOn|sndSelectMike ; 1 = microphone
DC.B (0<<5)|sndByPassOff|sndAGCOn|sndSelectMike ; 2 = modem sound <H18>
DC.B (7<<5)|sndByPassOff|sndAGCOn|sndSelectMike ; 3 = undefined (set for modem sound)
;—————————————————————————————————————————————————————————————————————————————— <H2>
; DBInputSelect - Select the sound input source on DB-Lite
;
; If we are selecting "none" for the input source, then turn off the volume
; and AGC to prevent any noise leakage. Save the old volume and restore it
; later when a new source is selected. If a source has been selected, then
; disable auto sleep otherwise enable auto sleep
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on DB-Lite)
; Output: d0.b last source
;
DBInputSelect
MOVE.W SR,-(SP) ; save the old sr
ori.w #HiIntMask,sr ; disable ints <H20>
BSR.S HandleAutoSleep ; turn auto-sleep on/off if necessary <H20>
CMPI.B #sndAuxiliary,D0 ; is it modem sound (aux)? <H18>
BNE.S @std ; no, continue <H18>
move.l a0,-(sp) ; save a0 <H18>
move.l VIA2,a0 ; point to the MSC's sound control register <H18>
lea MSCSndCntl(a0),a0 ; <H18>
bset #MSCSndPower,(a0) ; turn on sound power <H18>
move.l (sp)+,a0 ; restore a0 <H18>
@std bsr.s InputSelect ; select it as the source
MOVE.W (SP)+,SR ; enable ints
RTS ;
;——————————————————————————————————————————————————————————————————————————————
; DBLiteSetVol - Set the playback volume on DBLite's ASC/Batman hardware
; If the modem is selected as the sound source, then set DFAC
; as well.
;
; Input: d0.b = volume level (0-7)
; Output: none
;——————————————————————————————————————————————————————————————————————————————
DBLiteSetVol ; <H18>
move.l a0,-(sp)
move.w sr,-(sp) ; save sr
ori.w #HiIntMask,sr ; disable ints
movea.l ASCBase,a0 ; get base address of asc/batman
lsl.b #5,d0 ; shift volume up to pwm position
move.b d0,ascVolControl(a0) ; save it in ASC volume register
move.l PMgrBase,a0 ; Modem sound volume is controlled through DFAC
tst.b SysTaskFlag(a0) ; are the sound input primitives set up?
beq.s @exit ; -> no, don't worry about modem yet
movea.l ([Expandmem],emSndPrimitives),a0 ; a0 = ptr to vector table
moveq.l #3,d0 ; get selection bits
and.b DFAClast(a0),d0 ;
cmpi.b #sndSelectAux,d0 ; is the aux modem sound selected?
bne.s @exit ; no, set the ASC volume
jsrTBL sndDFACSend ; call DFACSend to adjust modem sound
@exit move.w (sp)+,sr ; restore ints
movea.l (sp)+,a0
rts
ENDIF ; {hasMSC}
;•••••••••••••••••••••••••••••••••••• VIA2 DFAC stuff •••••••••••••••••••••••••••••••••••
;——————————————————————————————————————————————————————————————————————————————
; VIA2DFACInit - send a byte to DFAC using via2
;
; Use this routine during initialization before traps are enabled.
;
; Input: a0.l = ptr to DecoderInfo record
; a6.l = return address
; Output: none
; Destroys: d0-d1/a3
; Called by: bsr6
;
IF hasNiagra THEN
DartDFACInit
movea.l JAWSAddr(a0),a3 ; point to the Niagra base address, <H14>
adda.l #(NiagraGUR+PontiSndCtl),a3 ; then to the sound control register <H14>
bclr.b #PontiSndMux0,(a3) ; default to auto mike selection <H14>
bclr.b #PontiSndMux1,(a3) ; disable modem override <H14>
**** bra.s TimDFACInit ; fall through to TimDFACInit <H13>
ENDIF
IF hasJaws | hasNiagra THEN
TimDFACInit
moveq #sndTimDFAC,d0 ; DFAC data to send for Tim <t6>
bra.s VIA2DFACInit
ENDIF
IF hasOrwell THEN
SpikeDFACInit
moveq #sndSpikeDFAC,d0 ; DFAC data to send for Spike <t6>
**** bra.s VIA2DFACInit ; fall through to VIA2DFACInit
ENDIF
IF hasOrwell | hasJaws | hasNiagra THEN
VIA2DFACInit
movea.l VIA2Addr(a0),a3 ; a3 = base addr of via2
bset.b #0,vBufB(a3) ; disable data (to aviod nasty accidental data clocking)
bset.b #4,vBufB(a3) ; set clock to high
bclr.b #0,vBufB(a3) ; enable data
moveq.l #8-1,d1 ; adjust for dbra
@Loop
asr.b #1,d0 ; shift data byte through carry
bcc.s @zeroBit
bset.b #3,vBufB(a3) ; write a one
bra.s @clock
@zeroBit bclr.b #3,vBufB(a3) ; write a zero
@clock bclr.b #4,vBufB(a3) ; toggle clock
bset.b #4,vBufB(a3) ; toggle clock
dbra d1,@Loop ; do all 8 data bytes
bset.b #0,vBufB(a3) ; disable data
rts6
;——————————————————————————————————————————————————————————————————————————————
; VIA2DFACSend - send a byte to DFAC using via2
;
; Use this routine during runtime after traps are enabled. There are three
; bits in VIA2 used to communicate to DFAC:
; bit 0 = latch enable
; 3 = data
; 4 = data clock
;
; To send data, enable data latch and clock each bit out separately.
;
; Input: d0.b = byte to send DFAC (in DFAC order)
; Output: none
;
VIA2DFACSend
@saveregs reg d1-d2/a0
movem.l @saveregs,-(sp)
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
; Update the RAM image of the DFAC register
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
move.b d0,DFAClast(a0) ; update DFAC register image
; Clock the data byte out through VIA2. Data is shifted out
; in DFAC order (LSB first).
movea.l VIA2,a0 ; get via2 base addr
bset.b #0,vBufB(a0) ; disable data (to aviod nasty accidental data clocking)
bset.b #4,vBufB(a0) ; set clock to high
bclr.b #0,vBufB(a0) ; drop bit to enable data
moveq.l #8-1,d1 ; adjust for dbra
@Loop
asr.b #1,d0 ; shift data byte through carry
bcc.s @zeroBit
bset.b #3,vBufB(a0) ; write a one
bra.s @clock
@zeroBit bclr.b #3,vBufB(a0) ; write a zero
@clock bclr.b #4,vBufB(a0) ; toggle clock
bset.b #4,vBufB(a0) ; toggle clock
dbra d1,@Loop ; do all 8 data bytes
bset.b #0,vBufB(a0) ; disable data
move.w (sp)+,sr ; enable ints <t9>
movem.l (sp)+,@saveregs
rts
ENDIF ; {hasOrwell | hasJaws | hasNiagra}
IF hasSonora THEN
;•••••••••••••••••••••••••••••••••••••••• Sonora ••••••••••••••••••••••••••••••••••••••••
;——————————————————————————————————————————————————————————————————————————————
; SonoraInputSelect - Select the sound input source on Sonora-based Macs
;
; If we are turning off the source (equivalent to disabling recording), then
; re-establish the playback mode.
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; Output: none
;
SonoraInputSelect
cmpi.b #sndMicrophone,d0 ; are we selecting the mike?
beq InputSelect ; yes - continue
; Since we're not selecting mike, then enable playback
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
moveq #sndSonoraDFAC-256,d0 ; DFAC playback mode for Sonora sound
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem
movem.l (sp)+,@saveregs
rts
;——————————————————————————————————————————————————————————————————————————————
; VailInputSelect - Select the sound input source on Vail
;
; If we are turning off the source (equivalent to disabling recording), then
; re-establish the playback mode.
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; Output: none
;
VailInputSelect
cmpi.b #sndMicrophone,d0 ; are we selecting the mike?
beq VailNewInputSelect ; yes - continue
@saveregs reg d1/a0
movem.l @saveregs,-(sp)
moveq #sndSonoraDFAC-256,d0 ; DFAC playback mode for Sonora sound
andi.b #sndPlayThruMask,d0 ; mask off playthru volume
move.b SDVolume,d1 ; get the volume <H22>
lsl.b #5,d1 ; shift it into top 3 bits <H22>
or.b d1,d0 ; or in last volume <H22>
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem
movem.l (sp)+,@saveregs
rts
;——————————————————————————————————————————————————————————————————————————————
; VailNewInputSelect - Select the sound input source on a Vail
;
; If we are selecting "none" for the input source, then turn off the volume
; and AGC to prevent any noise leakage. Save the old volume and restore it
; later when a new source is selected. Turn on Playthru while recording so that
; we can play and record simultaneously. Turning Playthru on while in record mode
; causes the filtering mechanism to be by-passed in the playback sound path.
; This difference is not audibly noticable in 22kHz mode.
;
; Input: do.b input selection
; 0 = none (off)
; 1 = microphone
; 2 = auxillary (modem sound on Tim, CD on Spike and Eclipse)
; Output: d0.b last source
;
VailNewInputSelect
@saveregs reg d1/a0-a1
movem.l @saveregs,-(sp)
movea.l ([Expandmem],emSndPrimitives),a0; a0 = ptr to vector table
move.w sr,-(sp) ; <t9>
ori.w #HiIntMask,sr ; disable ints <t9>
moveq.l #3,d2 ; get selection bits to return <t9>
and.b DFAClast(a0),d2 ; save for return <t9>
moveq #(sndSelectMask\ ; <t6>
AND sndPlayThruMask\
AND sndAGCMask),d1 ; mask off selection, volume, and AGC bits
and.b DFAClast(a0),d1 ; in the DFAC register image <t6>
or.b d0,d1 ; and OR them into DFAC image <t6>
; Check for volume and AGC to update in DFAC now that a sound source has been selected.
; If we are disabling input, then zero the volume and disable AGC to prevent noise
; leakage, otherwise set the currently selected volume and AGC levels.
tst.b d0 ; are we turning off input?
beq.s @send ; yes - set no input and zero volume
or.b UserVolume(a0),d1 ; set volume level <H22>
cmpi.b #sndMicrophone,d0 ; are we selecting the mike input? <H13>
bne.s @send ; no - do not enable AGC <H13>
or.b UserAGC(a0),d1 ; set AGC level <t6>
@send
move.b d1,d0 ; d0 = new DFAC value
bset #sndPlayThruBit,d0 ; set bit
jsrTBL sndDFACSend ; call DFACSend routine thru expandmem <t6>
move.w (sp)+,sr ; enable ints <t9>
move.b d2,d0 ; return source bits we replaced <t9>
movem.l (sp)+,@saveregs
rts
;——————————————————————————————————————————————————————————————————————————————
; VailSetVol - Set the playback volume on Sonora hardware
;
; Set the playback volume using the DFAC chip instead of the volume control register
; on Batman.
;
; Input: d0.b = volume level (0-7)
; Output: none
;
VailSetVol
@SaveRegs reg a0-a1
movem.l @SaveRegs,-(sp)
movea.l ASCBase,a0 ; get base address of asc/batman
move.l ExpandMem,d1 ; do we have expandmem set up yet?? <SM5>
ble.s @oldWay ; nope, do it the old way <SM5>
movea.l d1,a1 ; <SM5>
move.l emSndPrimitives(a1),d1 ; do we have sound primitives yet?? <SM5>
beq.s @oldWay ; nope, do it the old way
movea.l d1,a1 ; point to the table <SM5>
tst.b DFAClast(a1) ; has DFAClast been initialized?
bne.s @skipDFAClastInit ; yep, don't reinitialize it...
move.b #sndSonoraDFAC,DFAClast(a1) ; initialize DFAClast
@skipDFAClastInit
moveq #3,d1 ; mask off the input source <SM5>
and.b DFACLast(a1),d1 ; <H22><SM5>
cmpi.b #sndSelectMike,d1 ; is it in record mode?? <H22>
beq.s @restore ; yes, don't do anything <H22>
move.b #(7<<5),ascVolControl(a0) ; set volume to seven
move.b UserVolume(a1),-(sp) ; save off UserVolume <H22>
jsrTBL sndPlayThruVol ; head off to set PlayThru volume
move.b (sp)+,UserVolume(a1) ; restore original UserVolume <H22>
@restore movem.l (sp)+,@SaveRegs ; restore registers
rts ; and return
@oldWay
lsl.b #5,d0 ; shift volume up to pwm position
move.b d0,ascVolControl(a0) ; save it in ASC volume register
movem.l (sp)+,@SaveRegs ; restore registers
rts ; and split
ENDIF ; {hasSonora}
IF hasDJMEMC THEN
;•••••••••••••••••••••••••••••••••••••••• DJMEMC ••••••••••••••••••••••••••••••••••••••••
;——————————————————————————————————————————————————————————————————————————————
;
; Routine: DJMEMCInitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; A0 - pointer to machine's DecoderInfo table
; A1 - pointer to machine's ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0,A3
;
; Function: Called by BSR6 from StartInit to set the default volume for DJMEMC
; based machines. Although they have a standard Batman implementation,
; the need to whack on their built-in video to prevent calamity.
;——————————————————————————————————————————————————————————————————————————————
DJMEMCInitSoundHW
MOVEA.L ASCAddr(A0),A3 ; point to the base of the ASC
ASL.B #5,D0 ; shift the sound volume into the upper 3 bits
MOVE.B D0,ascVolControl(A3) ; and set the volume
MOVE.W #$7F00,bmLeftScaleA(A3) ; pan channel A full left
MOVE.W #$007F,bmLeftScaleB(A3) ; pan channel B full right
MOVEQ #1,D0
MOVE.L D0,$F9800100 ; shut off sync to built-in video BEFORE beeping
CMPI.L #WmStConst,WarmStart ; If were just powering on,
BNE FinishBatmanInit ; then just go on
MOVE.B #0,$50F14f2f ; otherwise, reset the Sound Block Configuration register
BRA FinishBatmanInit ; finish up with normal initialization
ENDIF
;•••••••••••••••••••••••••••••••••••••••• Cyclone •••••••••••••••••••••••••••••••••••••••
CycloneSndStubNoRam
Rts6
CycloneSndStub2
Moveq #0,D0
CycloneSndStub1
Rts
;••••••••••••••••••••••••••••••••••••••••••• PDM ••••••••••••••••••••••••••••••••••••••••••
PDMSndStubNoRam
Rts6
PDMSndStub2
Moveq #0,D0
PDMSndStub1
Rts
IF hasPratt THEN
;•••••••••••••••••••••••••••••••••••••••• Blackbird •••••••••••••••••••••••••••••••••••••••
;—————————————————————————————————————————————————————————————————————————————————————————
; DoNothing routines - The following routines simply return to the caller (used for
; unimplemented sound primitives).
DoNothingViaA6
RTS6
DoNothing
rts
;——————————————————————————————————————————————————————————————————————————————
;
; Routine: WhitneyInitSoundHW
;
; Inputs: D0 - sound volume (0-7)
; D1 - 0 is called via the RAMless routine, else 1
; A0 - pointer to machine's DecoderInfo table
; A1 - pointer to machine's ProductInfo table
; A6 - return address
;
; Outputs: none
;
; Trashes: D0,A3
;
; Function: Called by InitSoundHW (via BSR6) to configure hardware for Whitney
; based machines (i.e. Blackbird). Called before the trap dispatcher
; is initialized. Always returns via (A6).
;——————————————————————————————————————————————————————————————————————————————
BB_BASE EQU $10000 ; sound buffer base addr for bootbeep (64K)
WhitneyInitSoundHW
movea.l ASCAddr(a0),a3 ; point to the base of the ASC
; Set Whitney sound FIFO base address
; NOTE: We use the value of d1 to determine how to set the base address. If d1
; is 0, then we know that we entered via the RAMless entry point (called immediately
; before and after bootbeep). In this case, we know we have some RAM available,
; so we temporarily grab some low in memory for the sound buffer.
; If d1 is 1, we set the "real" FIFO base address to just above the boot/start globals,
; since this is where space is allocated for it by the SizeSoundBuffer routine.
tst.w d1
bne.s @setRealFIFOBase
@setTempFIFOBase
move.l #BB_BASE,wSndFIFOBase(a3) ; set FIFO base for BootBeep
bra.s @setSndCntl
@setRealFIFOBase
movem.l a0,-(sp) ; (don't worry, the stack exists for this path)
movea.l BootGlobPtr,a0
adda.l StartGlobals.sgTopOff(a0),a0
move.l a0,wSndFIFOBase(a3) ; the REAL sound FIFO base
movem.l (sp)+,a0
@setSndCntl ; Set up the Singer control registers
move.w #((%0100<<wRGain)|\ ; set gain
(%0100<<wLGain)|\
(%0<<wInSelRight)|\ ; select line-in
(%0<<wInSelLeft)|\
(%0<<wMute)|\ ; do not mute output
(%00000<<wWordAOut))\ ; MUST be 0 for Singer to function
,wSndSingerCtl1(a3)
move.w #((%0000<<wDigOut)|\ ; digital out lines not used
(%0000<<wRAtten)|\ ; no output attenutation (will be set later)
(%0000<<wLAtten)|\
(%0000<<wWordBOut))\ ; MUST be 0 for Singer to function
,wSndSingerCtl2(a3)
@setSCR ; Set up the sound control register
move.b #((%01<<wSampleRate)|\ ; 22 kHz sample rate
(%00<<wFIFOSize)|\ ; 1K elements in FIFO
(1<<wSingerClk)|\ ; enable Singer clock
(1<<wSingerPower))\
,wSndControl(a3) ; set new sound control reg
; Set the volume
@setVol lsl.b #5,d0 ; shift the sound volume into the upper 3 bits
move.b d0,ascVolControl(a3) ; and set the volume
; Mask sound interrupts
move.b #1,bmIntControlA(a3) ; mask interrupts
move.b #1,bmIntControlB(a3)
; Clear the FIFOs
ori.b #$80,ascFifoControl(a3) ; toggle the clear FIFO bit
andi.b #$7F,ascFifoControl(a3)
; Set Play mode
move.b #$00,ascPlayRecA(a3) ; disable recording
move.b #$01,ascMode(a3) ; enable sound play
RTS6
ENDIF ; {hasPratt}
End