mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-28 13:52:37 +00:00
2084 lines
85 KiB
Plaintext
2084 lines
85 KiB
Plaintext
;
|
||
; 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 Zydeco’s. <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 HORROR’s. <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 Zydeco’s.
|
||
; <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 HORROR’s.
|
||
; <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 we’re 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
|
||
|