supermario/base/SuperMarioProj.1994-02-09/OS/IoPrimitives/SndPrimitives.a

2084 lines
85 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; 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