Annotation of uae/amiga/source/uae.audio.asm, revision 1.1

1.1     ! root        1: ;*** ScR *** *** NOTESff ***
        !             2: 
        !             3: ;*  There is still room For improvements in the softint's. For example,
        !             4: ;* try If reducing Chip memory accesses increases speed. NOT high priority, though.
        !             5: ;*  This driver should probably have a DMA play mode For 1-4 stereo channels.
        !             6: ;*
        !             7: ;*  The sampler routines are just For fun. Since interrupts must NOT be disabled,
        !             8: ;* there are lots of clicks. But still, I have tried To sample at 22kHz While down-
        !             9: ;* loading files from a BBS On my A4000/040, AND it worked without any serial errors.
        !            10:   MC68020
        !            11: ;------------
        !            12: 
        !            13: VERSION   EQU 4
        !            14: REVISION  EQU 2
        !            15: DATE  Macro
        !            16:     Dc.b  "17.4.97"
        !            17:   ENDM
        !            18: VERS  Macro
        !            19:     Dc.b  "uae 4.2"
        !            20:   ENDM
        !            21: VSTRING Macro
        !            22:     VERS
        !            23:     Dc.b  " ("
        !            24:     DATE
        !            25:     Dc.b  ")",13,10,0
        !            26:   ENDM
        !            27: VERSTAG Macro
        !            28:     Dc.b  0,"$VER: "
        !            29:     VERS
        !            30:     Dc.b  " ("
        !            31:     DATE
        !            32:     Dc.b  ")",0
        !            33:   ENDM
        !            34: 
        !            35:   incdir  include:
        !            36: 
        !            37:   include hardware/all.i
        !            38: 
        !            39:   include exec/initializers.i
        !            40:   include exec/resident.i
        !            41:   include exec/alerts.i
        !            42:   include exec/memory.i
        !            43:   include graphics/gfxbase.i
        !            44:   include utility/utility.i
        !            45:   include utility/hooks.i
        !            46:   include devices/audio.i
        !            47:   include dos/dos.i
        !            48: 
        !            49: 
        !            50:   include lvos/exec_lib.i
        !            51:   include lvos/utility_lib.i
        !            52:   include lvos/dos_lib.i
        !            53:   include lvos/cardres_lib.i
        !            54: 
        !            55:   include devices/ahi.i
        !            56:   include libraries/ahi_sub.i
        !            57:   include lvos/ahi_sub_lib.i
        !            58: 
        !            59:   include resources/misc.i
        !            60:   include resources/card.i
        !            61:   include macros.i
        !            62: 
        !            63: _ciaa   EQU $bfe001
        !            64: _ciab   EQU $bfd000
        !            65: 
        !            66: PALFREQ   EQU 3546895
        !            67: NTSCFREQ  EQU 3579545
        !            68: MINPER    EQU 62
        !            69: 
        !            70: RECORDSAMPLES EQU 1024
        !            71: 
        !            72: 
        !            73: 
        !            74: ;* paula.audio extra tags
        !            75: AHIDB_Paula14Bit  EQU AHIDB_UserBase+0  * Boolean
        !            76: AHIDB_PaulaTable  EQU AHIDB_UserBase+1  * Boolean
        !            77: 
        !            78:  ;* paulaBase (private)
        !            79:   STRUCTURE paulaBase,LIB_SIZE
        !            80:   UBYTE pb_Flags
        !            81:   UBYTE pb_Pad1
        !            82:   UWORD pb_Pad2
        !            83:   APTR  pb_SysLib
        !            84:   ULONG pb_SegList
        !            85:   APTR  pb_GfxLib
        !            86:   APTR  pb_UtilLib
        !            87:   APTR  pb_DosLib
        !            88:   APTR  pb_MiscResource
        !            89:   APTR  pb_CardResource
        !            90:   LABEL paulaBase_SIZEOF
        !            91: 
        !            92:  ;* paula (private) ahiac_DriverData points to this structure.
        !            93:   STRUCTURE paula,0
        !            94:   UBYTE p_Flags
        !            95:   UBYTE p_Parallel      ;TRUE if pport allocated
        !            96:   UWORD p_DisableCount
        !            97:   APTR  p_audioport
        !            98:   APTR  p_audioreq
        !            99:   ULONG p_audiodev
        !           100:   APTR  p_DMAbuffer
        !           101:   APTR  p_ParBitsUser
        !           102:   APTR  p_ParPortUser
        !           103:   APTR  p_CardHandle
        !           104: 
        !           105:   STRUCT  p_PlayInt,IS_SIZE
        !           106:   STRUCT  p_PlaySoftInt,IS_SIZE
        !           107:   STRUCT  p_RecInt,IS_SIZE
        !           108:   STRUCT  p_RecSoftInt,IS_SIZE
        !           109: 
        !           110:   UWORD p_MonitorVolume
        !           111:   UWORD p_Input
        !           112: 
        !           113: ;*** IS_DATA for Play Interrupt (do not change order!)
        !           114:   LABEL p_PlayIntData
        !           115:   APTR  p_PlaySoftIntPtr
        !           116:   UWORD p_AudLen      ;don't change order
        !           117:   ULONG p_AudPer      ;
        !           118:   UWORD p_DoubleBufferFlag
        !           119:   APTR  p_AudPtr1A
        !           120:   APTR  p_AudPtr2A
        !           121:   APTR  p_AudPtr3A
        !           122:   APTR  p_AudPtr4A
        !           123:   APTR  p_AudPtr1B
        !           124:   APTR  p_AudPtr2B
        !           125:   APTR  p_AudPtr3B
        !           126:   APTR  p_AudPtr4B
        !           127: 
        !           128: ;*** IS_DATA for Play Software Interrupt (do not change order!)
        !           129:   LABEL p_PlaySoftIntData
        !           130:   APTR  p_PlayerHook
        !           131:   ULONG p_Reserved
        !           132:   APTR  p_AudioCtrlP
        !           133:   FPTR  p_PlayerEntry     ;p_PlayerHook->h_Entry
        !           134:   FPTR  p_PreTimer
        !           135:   FPTR  p_PostTimer
        !           136:   ULONG p_LoopTimes
        !           137:   APTR  p_MixHook
        !           138:   APTR  p_Mixbuffer
        !           139:   APTR  p_AudioCtrlM
        !           140:   FPTR  p_MixEntry      ;p_MixHook->h_Entry
        !           141:   APTR  p_AudPtrs
        !           142:   APTR  p_CalibrationTable
        !           143: 
        !           144: ;*** IS_DATA for Aura Record Interrupt (do not change order!)
        !           145:   LABEL p_RecIntDataAura
        !           146:   APTR  p_AuraAddress
        !           147: ;*** IS_DATA for Paula Record Interrupt (do not change order!)
        !           148:   LABEL p_RecIntData
        !           149:   APTR  p_RecFillPtr
        !           150:   UWORD p_RecFillCount
        !           151:   UWORD p_Pad3
        !           152:   APTR  p_RecBuffer1
        !           153:   APTR  p_RecBuffer2
        !           154:   APTR  p_RecSoftIntPtr
        !           155: 
        !           156:   LABEL p_RecordMessage
        !           157:   ULONG p_rmType
        !           158:   APTR  p_rmBuffer
        !           159:   ULONG p_rmLength
        !           160: 
        !           161:   STRUCT  p_CalibrationArray,256
        !           162:   LABEL paula_SIZEOF
        !           163: 
        !           164: ;* p_Flags
        !           165:   BITDEF  P,14BIT,0
        !           166: PB_STEREO EQU AHIACB_STEREO   ;=2
        !           167: PF_STEREO EQU AHIACF_STEREO
        !           168: 
        !           169: Start:
        !           170:   MOVEQ #-1,d0
        !           171:   RTS
        !           172: 
        !           173: RomTag:
        !           174:   Dc.W  RTC_MATCHWORD
        !           175:   Dc.L  RomTag
        !           176:   Dc.L  EndCode
        !           177:   Dc.B  RTF_AUTOINIT
        !           178:   Dc.B  VERSION       ;version
        !           179:   Dc.B  NT_LIBRARY
        !           180:   Dc.B  0       ;pri
        !           181:   Dc.L  LibName
        !           182:   Dc.L  IDString
        !           183:   Dc.L  InitTable
        !           184: 
        !           185: LibName:  Dc.b  "uae.audio",0
        !           186: IDString: VSTRING
        !           187: gfxName:  GRAPHICSNAME
        !           188: utilName: UTILITYNAME
        !           189: dosName:  DOSNAME
        !           190: miscName: MISCNAME
        !           191: cardName: Dc.b  "card.resource",0
        !           192: envVar:   Dc.b  "AHIpaulaFilterFreq",0
        !           193:   cnop  0,2
        !           194: 
        !           195: InitTable:
        !           196:   Dc.L  paulaBase_SIZEOF
        !           197:   Dc.L  funcTable
        !           198:   Dc.L  dataTable
        !           199:   Dc.L  initRoutine
        !           200: 
        !           201: funcTable:
        !           202:   Dc.l  Open
        !           203:   Dc.l  Close
        !           204:   Dc.l  Expunge
        !           205:   Dc.l  Null
        !           206: ;*
        !           207:   Dc.l  AHIsub_AllocAudio
        !           208:   Dc.l  AHIsub_FreeAudio
        !           209:   Dc.l  AHIsub_Disable
        !           210:   Dc.l  AHIsub_Enable
        !           211:   Dc.l  AHIsub_Start
        !           212:   Dc.l  AHIsub_Update
        !           213:   Dc.l  AHIsub_Stop
        !           214:   Dc.l  AHIsub_SetVol
        !           215:   Dc.l  AHIsub_SetFreq
        !           216:   Dc.l  AHIsub_SetSound
        !           217:   Dc.l  AHIsub_SetEffect
        !           218:   Dc.l  AHIsub_LoadSound
        !           219:   Dc.l  AHIsub_UnloadSound
        !           220:   Dc.l  AHIsub_GetAttr
        !           221:   Dc.l  AHIsub_HardwareControl
        !           222:   Dc.l  -1
        !           223: 
        !           224: dataTable:
        !           225:   INITBYTE  LN_TYPE,NT_LIBRARY
        !           226:   INITLONG  LN_NAME,LibName
        !           227:   INITBYTE  LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
        !           228:   INITWORD  LIB_VERSION,VERSION
        !           229:   INITWORD  LIB_REVISION,REVISION
        !           230:   INITLONG  LIB_IDSTRING,IDString
        !           231:   Dc.L    0
        !           232: 
        !           233: initRoutine:
        !           234:   MOVEM.l d1/a0/a1/a5/a6,-(sp)
        !           235:   MOVE.l  d0,a5
        !           236:   MOVE.l  a6,pb_SysLib(a5)
        !           237:   MOVE.l  a0,pb_SegList(a5)
        !           238:   LEA gfxName(pc),a1
        !           239:   MOVEQ #0,d0
        !           240:   call OpenLibrary
        !           241:   MOVE.l  d0,pb_GfxLib(a5)
        !           242:   BNE.b .gfxOK
        !           243:   ALERT AG_OpenLib!AO_GraphicsLib
        !           244:   MOVEQ #0,d0
        !           245:   BRA .exit
        !           246: .gfxOK
        !           247:   LEA utilName(pc),a1
        !           248:   MOVEQ #0,d0
        !           249:   call  OpenLibrary
        !           250:   MOVE.l  d0,pb_UtilLib(a5)
        !           251:   BNE.b .utilOK
        !           252:   ALERT AG_OpenLib!AO_UtilityLib
        !           253:   MOVEQ #0,d0
        !           254:   BRA .exit
        !           255: .utilOK
        !           256:   LEA dosName(pc),a1
        !           257:   MOVEQ #0,d0
        !           258:   call  OpenLibrary
        !           259:   MOVE.l  d0,pb_DosLib(a5)
        !           260:   BNE.b .dosOK
        !           261:   ALERT AG_OpenLib!AO_DOSLib
        !           262:   MOVEQ #0,d0
        !           263:   BRA .exit
        !           264: .dosOK
        !           265:   LEA miscName(pc),a1
        !           266:   call  OpenResource
        !           267:   MOVE.l  d0,pb_MiscResource(a5)
        !           268:   BNE.b .miscOK
        !           269:   ALERT AG_OpenRes!AO_MiscRsrc
        !           270:   MOVEQ #0,d0
        !           271:   BRA .exit
        !           272: .miscOK
        !           273:   LEA cardName(pc),a1
        !           274:   call  OpenResource
        !           275:   MOVE.l  d0,pb_CardResource(a5)    ;Don't fail on error
        !           276: 
        !           277:   MOVE.l  a5,d0
        !           278: .exit
        !           279:   MOVEM.l (sp)+,d1/a0/a1/a5/a6
        !           280:   RTS
        !           281: 
        !           282: Open:
        !           283:   MOVEQ #0,d0
        !           284:   ADDQ.w  #1,LIB_OPENCNT(a6)
        !           285:   BCLR.b  #LIBB_DELEXP,pb_Flags(a6)
        !           286:   MOVE.l  a6,d0
        !           287: .exit
        !           288:   RTS
        !           289: 
        !           290: Close:
        !           291:   MOVEQ #0,d0
        !           292:   SUBQ.w  #1,LIB_OPENCNT(a6)
        !           293:   BNE.b .exit
        !           294:   BTST.b  #LIBB_DELEXP,pb_Flags(a6)
        !           295:   BEQ.b .exit
        !           296:   BSR Expunge
        !           297: .exit
        !           298:   RTS
        !           299: 
        !           300: Expunge:
        !           301:   MOVEM.l d1/d2/a0/a1/a5/a6,-(sp)
        !           302:   MOVE.l  a6,a5
        !           303:   MOVE.l  pb_SysLib(a5),a6
        !           304:   TST.w LIB_OPENCNT(a5)
        !           305:   BEQ.b .notopen
        !           306:   BSET.b  #LIBB_DELEXP,pb_Flags(a5)
        !           307:   MOVEQ #0,d0
        !           308:   BRA.b .Expunge_end
        !           309: .notopen
        !           310:   MOVE.l  pb_GfxLib(a5),a1
        !           311:   call  CloseLibrary
        !           312: 
        !           313:   MOVE.l  pb_UtilLib(a5),a1
        !           314:   call  CloseLibrary
        !           315: 
        !           316:   MOVE.l  pb_DosLib(a5),a1
        !           317:   call  CloseLibrary
        !           318: 
        !           319:   MOVE.l  pb_SegList(a5),d2
        !           320:   MOVE.l  a5,a1
        !           321:   call  Remove
        !           322: 
        !           323:   MOVEQ #0,d0
        !           324:   MOVE.l  a5,a1
        !           325:   MOVE.w  LIB_NEGSIZE(a5),d0
        !           326:   SUB.l d0,a1
        !           327:   ADD.w LIB_POSSIZE(a5),d0
        !           328:   call  FreeMem
        !           329:   MOVE.l  d2,d0
        !           330: .Expunge_end
        !           331:   MOVEM.l (sp)+,d1/d2/a0/a1/a5/a6
        !           332:   RTS
        !           333: 
        !           334: Null:
        !           335:   MOVEQ #0,d0
        !           336:   RTS
        !           337: 
        !           338: ;* BeginIO(ioRequest)(a1) (From amiga.lib)
        !           339: BeginIO:
        !           340:   MOVE.l  a1,a0   ;probably not neccesary
        !           341:   push  a6
        !           342:   MOVE.l  IO_DEVICE(a1),a6
        !           343:   JSR -30(a6)
        !           344:   pop a6
        !           345:   RTS
        !           346: 
        !           347: ;****** [driver].audio/--background-- ****************************************
        !           348: ;*
        !           349: ;*   OVERVIEW
        !           350: ;*
        !           351: ;*       AUDIO ID NUMBERS
        !           352: ;*
        !           353: ;*       Just some notes about selecting ID numbers for different modes:
        !           354: ;*       It is up to the driver programmer to chose which modes should be
        !           355: ;*       available to the user. Take care when selecting.
        !           356: ;*       The upper word is the hardware ID, and can only be allocated by
        !           357: ;*       Martin Blom <[email protected]>. The lower word is free, but in
        !           358: ;*       order to allow enhancements, please only use bit 0 to 3 for modes!
        !           359: ;*       Set the remaining bits to zero.
        !           360: ;*       The ID is currently used by AHI_BestAudioIDA() to select a mode.
        !           361: ;*       In order for this to work, you have to follow some rules.
        !           362: ;*       7 Modes using tables should have higher IDs than modes that uses more
        !           363: ;*         CPU power.
        !           364: ;*       7 Mono modes should have higher IDs than stereo modes
        !           365: ;*       7 Stereo modes should have higher IDs than stereo modes with panning.
        !           366: ;*       Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
        !           367: ;*       currently available.
        !           368: ;*
        !           369: ;*       I do reserve the right to change the rules if I find them incorrect!
        !           370: ;*
        !           371: ;*****************************************************************************
        !           372: ;*
        !           373: ;*
        !           374: 
        !           375: ;****** [driver].audio/AHIsub_AllocAudio *************************************
        !           376: ;*
        !           377: ;*   NAME
        !           378: ;*       AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
        !           379: ;*
        !           380: ;*   SYNOPSIS
        !           381: ;*       result = AHIsub_AllocAudio( tags, audioctrl);
        !           382: ;*       D0                          A1    A2
        !           383: ;*
        !           384: ;*       ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
        !           385: ;*
        !           386: ;*   IMPLEMENTATION
        !           387: ;*       Allocate and initialize the audio hardware. Decide if and how you
        !           388: ;*       wish to use the mixing routines provided by 'ahi.device', by looking
        !           389: ;*       in the AHIAudioCtrlDrv structure and parsing the tag list for tags
        !           390: ;*       you support.
        !           391: ;*
        !           392: ;*       1) Use mixing routines with timing:
        !           393: ;*           You will need to be able to play any number of samples from
        !           394: ;*           about 80 up to 65535 with low overhead.
        !           395: ;*           7 Update AudioCtrl->ahiac_MixFreq to nearest value that your
        !           396: ;*             hardware supports.
        !           397: ;*           7 Return AHISF_MIXING|AHISF_TIMING.
        !           398: ;*       2) Use mixing routines without timing:
        !           399: ;*           If the hardware can't play samples with any length, use this
        !           400: ;*           alternative and provide timing yourself. The buffer must
        !           401: ;*           take less than about 20 ms to play, preferable less than 10!
        !           402: ;*           7 Update AudioCtrl->ahiac_MixFreq to nearest value that your
        !           403: ;*             hardware supports.
        !           404: ;*           7 Store the number of samples to mix each pass in
        !           405: ;*             AudioCtrl->ahiac_BuffSamples.
        !           406: ;*           7 Return AHISF_MIXING
        !           407: ;*           Alternatively, you can use the first method and call the
        !           408: ;*           mixing hook several times in a row to fill up a buffer.
        !           409: ;*           In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
        !           410: ;*           return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
        !           411: ;*           If the buffer is so large that it takes more than (approx.) 10 ms to
        !           412: ;*           play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
        !           413: ;*           should return FALSE.
        !           414: ;*       3) Don't use mixing routines:
        !           415: ;*           If your hardware can handle everything without using the CPU to
        !           416: ;*           mix the channels, you tell 'ahi.device' this by not setting
        !           417: ;*           neither the AHISB_MIXING nor the AHISB_TIMING bit.
        !           418: ;*
        !           419: ;*       If you can handle stereo output from the mixing routines, also set
        !           420: ;*       bit AHISB_KNOWSTEREO.
        !           421: ;*
        !           422: ;*       If you can handle hifi (32 bit) output from the mixing routines,
        !           423: ;*       set bit AHISB_KNOWHIFI.
        !           424: ;*
        !           425: ;*       If this driver can be used to record samples, set bit AHISB_CANRECORD,
        !           426: ;*       too (regardless if you use the mixing routines in AHI or not).
        !           427: ;*
        !           428: ;*       If the sound card has hardware to do DSP effects, you can set the
        !           429: ;*       AHISB_CANPOSTPROCESS bit. The output from the mixing routines will
        !           430: ;*       then be two separate buffers, one wet and one dry. You should then
        !           431: ;*       apply the Fx on the wet buffer, and post-mix the two buffers before
        !           432: ;*       you send the samples to the DAC. (V4)
        !           433: ;*
        !           434: ;*   INPUTS
        !           435: ;*       tags - pointer to a taglist.
        !           436: ;*       audioctrl - pointer to an AHIAudioCtrlDrv structure.
        !           437: ;*
        !           438: ;*   TAGS
        !           439: ;*       The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
        !           440: ;*       NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
        !           441: ;*
        !           442: ;*   RESULT
        !           443: ;*       Flags, defined in <libraries/ahi_sub.h>.
        !           444: ;*
        !           445: ;*   EXAMPLE
        !           446: ;*
        !           447: ;*   NOTES
        !           448: ;*       You don't have to clean up on failure, AHIsub_FreeAudio() will
        !           449: ;*       always be called.
        !           450: ;*
        !           451: ;*   BUGS
        !           452: ;*
        !           453: ;*   SEE ALSO
        !           454: ;*       AHIsub_FreeAudio(), AHIsub_Start()
        !           455: ;*
        !           456: ;*****************************************************************************
        !           457: ;*
        !           458: ;*
        !           459: 
        !           460: AHIsub_AllocAudio:
        !           461:   pushm d2-d7/a2-a6
        !           462:   MOVE.l  a6,a5
        !           463: 
        !           464:   MOVE.l  a1,d3
        !           465: 
        !           466: * Allocate the 'paula' structure (our variables)
        !           467:   MOVE.l  pb_SysLib(a5),a6
        !           468:   MOVE.l  #paula_SIZEOF,d0
        !           469:   MOVE.l  #MEMF_PUBLIC|MEMF_CLEAR,d1
        !           470:   call  AllocVec
        !           471:   MOVE.l  d0,ahiac_DriverData(a2)
        !           472:   BEQ .error_nopaula
        !           473:   MOVE.l  d0,a3
        !           474: 
        !           475: * Initialize some Fields...
        !           476:   MOVE.l  #-1,p_audiodev(a3)
        !           477:   MOVE.l  #-1,p_ParBitsUser(a3)
        !           478:   MOVE.l  #-1,p_ParPortUser(a3)
        !           479:   MOVE.l  a2,p_AudioCtrlP(a3)   ;player Hook
        !           480:   MOVE.l  a2,p_AudioCtrlM(a3)   ;mixer Hook
        !           481:   LEA p_PlaySoftInt(a3),a0
        !           482:   MOVE.l  a0,p_PlaySoftIntPtr(a3)
        !           483:   LEA p_RecSoftInt(a3),a0
        !           484:   MOVE.l  a0,p_RecSoftIntPtr(a3)
        !           485:   MOVE.l  #AHIST_S16S,p_rmType(a3)
        !           486:   MOVE.l  #RECORDSAMPLES,p_rmLength(a3)
        !           487: 
        !           488: * Translate Tags To flags
        !           489:   MOVEQ #0,d2
        !           490:   MOVE.l  pb_UtilLib(a5),a6
        !           491:   MOVE.l  #AHIDB_Paula14Bit,d0
        !           492:   MOVEQ #0,d1
        !           493:   MOVE.l  d3,a0       ;tag list
        !           494:   call  GetTagData
        !           495:   TST.l d0
        !           496:   BEQ.b .no14bit
        !           497:   MOVEQ #PF_14BIT,d2
        !           498: .no14bit
        !           499:   MOVE.l  ahiac_Flags(a2),d0
        !           500:   AND.b #PF_STEREO,d0     ;same as AHIACF_STEREO
        !           501:   OR.b  d2,d0
        !           502:   MOVE.b  p_Flags(a3),d1
        !           503:   AND.b #~(PF_STEREO|PF_14BIT),d1
        !           504:   OR.b  d0,d1
        !           505:   MOVE.b  d1,p_Flags(a3)
        !           506: 
        !           507: * Check If a table should be Used (14 bit calibration)
        !           508:   MOVE.l  #AHIDB_PaulaTable,d0
        !           509:   MOVEQ #0,d1
        !           510:   MOVE.l  d3,a0       ;tag list
        !           511:   call  GetTagData
        !           512:   TST.l d0
        !           513:   BEQ .notable
        !           514: 
        !           515: * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
        !           516: * AND initialize the table.
        !           517: * FIXIT: The calibration File should MOVE To a special chunk in
        !           518: * 'DEVS:AudioModes/PAULA'.
        !           519:   MOVE.l  pb_DosLib(a5),a6
        !           520:   LEA .calibname(pc),a0
        !           521:   MOVE.l  a0,d1
        !           522:   MOVE.l  #MODE_OLDFILE,d2
        !           523:   call  Open
        !           524:   MOVE.l  d0,d4
        !           525:   BEQ .nocalib
        !           526:   MOVE.l  d0,d1
        !           527:   LEA p_CalibrationArray(a3),a0
        !           528:   MOVE.l  a0,d2
        !           529:   MOVE.l  #256,d3
        !           530:   call  Read
        !           531:   CMP.l d0,d3
        !           532:   BEQ .tableloaded
        !           533: .nocalib
        !           534: ; Fill defaults
        !           535:   LEA p_CalibrationArray(a3),a0
        !           536:   MOVE.w  #254-1,d0
        !           537: .initcalib
        !           538:   MOVE.b  #$55,(a0)+
        !           539:   DBF d0,.initcalib
        !           540:   MOVE.b  #$7f,(a0)+
        !           541: .tableloaded
        !           542:   MOVE.l  d4,d1
        !           543:   BEQ.b .nofile
        !           544:   call  Close
        !           545: .nofile
        !           546:   MOVE.l  pb_SysLib(a5),a6
        !           547:   MOVE.l  #65536*2,d0
        !           548:   MOVE.l  #MEMF_PUBLIC,d1
        !           549:   call  AllocVec
        !           550:   MOVE.l  d0,p_CalibrationTable(a3)
        !           551:   BEQ.b .notable
        !           552:   MOVE.l  d0,a0     ;table
        !           553:   LEA p_CalibrationArray(a3),a1
        !           554:   BSR.w _CreateTable
        !           555: .notable
        !           556: 
        !           557: 
        !           558: * allocate audio.device
        !           559:   MOVE.l  pb_SysLib(a5),a6
        !           560:   call  CreateMsgPort
        !           561:   MOVE.l  d0,p_audioport(a3)
        !           562:   BEQ .error_noport
        !           563:   MOVEQ #ioa_SIZEOF,d0
        !           564:   MOVE.l  #MEMF_PUBLIC!MEMF_CLEAR,d1
        !           565:   call  AllocVec
        !           566:   MOVE.l  d0,p_audioreq(a3)
        !           567:   BEQ .error_noreqmem
        !           568:   MOVE.l  d0,a0
        !           569:   MOVE.l  p_audioport(a3),MN_REPLYPORT(a0)
        !           570:   CLR.w ioa_AllocKey(a0)
        !           571:   MOVE.b  #127,LN_PRI(a0)     ;steal it!
        !           572:   LEA .audiochannelarray(pc),a1
        !           573:   MOVE.l  a1,ioa_Data(a0)
        !           574:   MOVE.l  #1,ioa_Length(a0)
        !           575:   LEA .audioname(pc),a0
        !           576:   MOVEQ #0,d0
        !           577:   MOVE.l  p_audioreq(a3),a1
        !           578:   MOVEQ #0,d1
        !           579:   call  OpenDevice
        !           580:   MOVE.l  d0,p_audiodev(a3)
        !           581:   BNE .error_noaudiodev   ;somebody already owns the hardware (could be us!)
        !           582:   MOVE.l  p_audioreq(a3),a1           ;bernd#1
        !           583:   MOVE.w  #CMD_RESET,IO_COMMAND(a1)
        !           584:   BSR.w BeginIO       ;clear attach, stop sound.
        !           585:   MOVE.l  p_audioport(a3),a0
        !           586:   call  WaitPort
        !           587:   MOVE.l  p_audioport(a3),a0
        !           588:   call  GetMsg
        !           589: 
        !           590:   MOVE.l  pb_DosLib(a5),a6
        !           591:   MOVEQ #1,d1
        !           592:   call  Delay
        !           593: 
        !           594: * test If mode supports recording
        !           595:   BTST  #PB_14BIT,p_Flags(a3)
        !           596:   BNE .dontgetsampler     ;no record if 14 bit mode
        !           597: 
        !           598: * try To allocate parallel port
        !           599:   CLR.b p_Parallel(a3)
        !           600:   MOVE.l  pb_MiscResource(a5),a6
        !           601:   MOVEQ #MR_PARALLELBITS,d0
        !           602:   LEA IDString(pc),a1
        !           603:   JSR MR_ALLOCMISCRESOURCE(a6)
        !           604:   MOVE.l  d0,p_ParBitsUser(a3)
        !           605:   BNE .no_parrallel
        !           606:   MOVEQ #MR_PARALLELPORT,d0
        !           607:   LEA IDString(pc),a1
        !           608:   JSR MR_ALLOCMISCRESOURCE(a6)
        !           609:   MOVE.l  d0,p_ParPortUser(a3)
        !           610:   BNE .no_parrallel
        !           611: 
        !           612:   MOVE.b  #TRUE,p_Parallel(a3)
        !           613:   ;move.b #0,_ciaa+ciaddrb      ;make PB0-PB7 inputs
        !           614: .no_parrallel
        !           615: 
        !           616:  ;* allocate Aura sampler
        !           617:   CLR.l p_AuraAddress(a3)
        !           618:   MOVE.l  pb_CardResource(a5),d0
        !           619:   BEQ .no_aura
        !           620:   MOVE.l  d0,a6
        !           621:   call  GetCardMap
        !           622:   TST.l d0
        !           623:   BEQ .no_aura
        !           624:   MOVE.l  d0,a0
        !           625:   MOVE.l  cmm_IOMemory(a0),d2
        !           626:   BEQ .no_aura
        !           627: 
        !           628:   base  exec
        !           629:   MOVEQ #CardHandle_SIZEOF,d0
        !           630:   MOVE.l  #MEMF_PUBLIC|MEMF_CLEAR,d1
        !           631:   call  AllocVec
        !           632:   MOVE.l  d0,p_CardHandle(a3)
        !           633:   BEQ .no_aura
        !           634: 
        !           635:   MOVE.l  pb_CardResource(a5),a6
        !           636:   MOVE.l  d0,a1
        !           637:   MOVE.l  #IDString,LN_NAME(a1)
        !           638:   MOVE.b  #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
        !           639:   call  OwnCard
        !           640:   TST.l d0
        !           641:   BNE .no_aura
        !           642: 
        !           643:   MOVE.l  p_CardHandle(a3),a1
        !           644:   call  BeginCardAccess
        !           645:   TST.l d0
        !           646:   BEQ .no_aura
        !           647: 
        !           648:   MOVE.l  d2,p_AuraAddress(a3)
        !           649: .no_aura
        !           650: .dontgetsampler
        !           651: 
        !           652: 
        !           653:  ;* initialize interrupts (Only dummy function pointers at this time)
        !           654: 
        !           655:  ;* p_PlayInt (the main playback interrupt)
        !           656:   MOVE.b  #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
        !           657:   MOVE.l  #LibName,LN_NAME+p_PlayInt(a3)
        !           658:   MOVE.l  #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
        !           659:   LEA p_PlayIntData(a3),a1
        !           660:   MOVE.l  a1,IS_DATA+p_PlayInt(a3)
        !           661: 
        !           662:  ;* p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
        !           663:   MOVE.b  #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
        !           664:   MOVE.l  #LibName,LN_NAME+p_PlaySoftInt(a3)
        !           665:   MOVE.l  #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
        !           666:   LEA p_PlaySoftIntData(a3),a1
        !           667:   MOVE.l  a1,IS_DATA+p_PlaySoftInt(a3)
        !           668: 
        !           669:  ;* p_RecInt (the interrupt used for recording)
        !           670:   MOVE.b  #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
        !           671:   MOVE.l  #LibName,LN_NAME+p_RecInt(a3)
        !           672:   MOVE.l  #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
        !           673:   CLR.l IS_DATA+p_RecInt(a3)
        !           674: 
        !           675:  ;* p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
        !           676:   MOVE.b  #32,LN_PRI+p_RecSoftInt(a3)
        !           677:   MOVE.b  #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
        !           678:   MOVE.l  #LibName,LN_NAME+p_RecSoftInt(a3)
        !           679:   MOVE.l  #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
        !           680:   MOVE.l  a3,IS_DATA+p_RecSoftInt(a3)
        !           681: 
        !           682: ;* Make sure no interrupts occur until AHIsub_Start() is called
        !           683:   MOVE.w  #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,CUSTOM+INTENA
        !           684: 
        !           685: ;* Update ahiac_MixFreq to what the mixing/sampling frequency really is
        !           686:   MOVE.l  ahiac_MixFreq(a2),d1
        !           687:   BSR calcperiod
        !           688:   MOVE.l  d0,ahiac_MixFreq(a2)    ;store actual freq
        !           689: 
        !           690:   MOVEQ #AHISB_KNOWHIFI|AHISF_KNOWSTEREO|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
        !           691: .exit
        !           692:   popm  d2-d7/a2-a6
        !           693:   RTS
        !           694: 
        !           695: .error_noaudiodev
        !           696: .error_noreqmem
        !           697: .error_noport
        !           698: .error_nopaula
        !           699:   MOVEQ #AHISF_ERROR,d0
        !           700:   BRA.b .exit
        !           701: 
        !           702: .audiochannelarray
        !           703:   Dc.b  1+2+4+8
        !           704: .audioname
        !           705:   AUDIONAME
        !           706: .calibname
        !           707:   Dc.b  "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
        !           708:   Even
        !           709: .cardhandle:
        !           710:   Dc.l  0,0   ;ln_Succ, ln_Pred
        !           711:   Dc.b  0   ;ln_Type
        !           712:   Dc.b  0   ;ln_Pri
        !           713:   Dc.l  IDString  ;ln_Name
        !           714:   Dc.l  0,0,0   ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
        !           715:   Dc.b  (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
        !           716:   Even
        !           717: 
        !           718: ;in:
        !           719: ;* d1 MixFreq
        !           720: ;* a5 paulaBase
        !           721: ;out:
        !           722: ;* d0 New MixFreq
        !           723: ;* d1.w Period
        !           724: ;description:
        !           725: ;*  Calculate and return the best period and the actual frequency.
        !           726: calcperiod:
        !           727:        pushm d2-d5
        !           728:        move.l d1,d5
        !           729:        MOVE.l #0,d0
        !           730:        jsr $F0FFB0
        !           731:        MOVE.l d0,d1
        !           732:        MOVE.l #1,d0
        !           733:        jsr $F0FFB0
        !           734:        ; now, d0 contains the divisor UAE uses for its output frequency.
        !           735:        ; d1 contains the nominal output frequency of UAE.
        !           736:        ; Multiply the two and divide by desired frequency (which we'll
        !           737:        ; assume to be 44100 Hz), and we get the necessary divider
        !           738:        MOVE.l  pb_UtilLib(a5),a1
        !           739:        jsr _LVOUMult32(a1)
        !           740:        MOVE.l #44100,d5  ; @@@ potentially change this
        !           741:        MOVE.l d5,d1
        !           742:         jsr _LVOUDivMod32(a1)
        !           743:        MOVE.l  d0,d1
        !           744:         MOVE.l  d5,d0
        !           745:        popm  d2-d5
        !           746:        RTS
        !           747: 
        !           748: ;in:
        !           749: * d0  Frequency
        !           750: ;out:
        !           751: * d0  Closest frequency
        !           752: * d1  Index
        !           753: findfreq:
        !           754:   LEA uae(pc),a0
        !           755:   CMP.l (a0),d0
        !           756:   BLS.b .2
        !           757: .findfreq
        !           758:   CMP.l (a0)+,d0
        !           759:   BHI.b .findfreq
        !           760:   MOVE.l  -4(a0),d1
        !           761:   SUB.l d0,d1
        !           762:   SUB.l -8(a0),d0
        !           763:   CMP.l d1,d0
        !           764:   bhs.b .1
        !           765:   SUBQ.l  #4,a0
        !           766: .1
        !           767:   SUBQ.l  #4,a0
        !           768: .2
        !           769:   MOVE.l  (a0),d0
        !           770:   MOVE.l  a0,d1
        !           771:   SUB.l #uae,d1
        !           772:   LSR.l #2,d1
        !           773:   RTS
        !           774: 
        !           775: freqlist:
        !           776:   Dc.l  4410          ; CD/10
        !           777:   Dc.l  4800          ; DAT/10
        !           778:   Dc.l  5513          ; CD/8
        !           779:   Dc.l  6000          ; DAT/8
        !           780:   Dc.l  7350          ; CD/6
        !           781:   Dc.l  8000          ; 5- and A-Law, DAT/6
        !           782:   Dc.l  9600          ; DAT/5
        !           783:   Dc.l  11025         ; CD/4
        !           784:   Dc.l  12000         ; DAT/4
        !           785:   Dc.l  14700         ; CD/3
        !           786:   Dc.l  16000         ; DAT/3
        !           787:   Dc.l  17640         ; CD/2.5
        !           788:   Dc.l  18900
        !           789:   Dc.l  19200         ; DAT/2.5
        !           790:   Dc.l  22050         ; CD/2
        !           791:   Dc.l  24000         ; DAT/2
        !           792:   Dc.l  27429
        !           793: FREQUENCIES_OCS   EQU (*-freqlist)
        !           794:   Dc.l  29400         ; CD/1.5
        !           795: uae Dc.l  32000         ; DAT/1.5
        !           796:   ;dc.l 33075
        !           797:   ;dc.l 37800
        !           798:   Dc.l  44100         ; CD
        !           799:   ;dc.l 48000         ; DAT
        !           800: FREQUENCIES   EQU (*-uae)
        !           801:   Dc.l  -1
        !           802: 
        !           803: * _CreateTable directly stolen from Christian Buchner's CyberSound
        !           804: * audio SUB system (with permission).
        !           805: 
        !           806: * _CreateTable **************************************************************
        !           807: 
        !           808:     ; Parameters
        !           809: 
        !           810:     ; a0 = Table address
        !           811:     ; (MUST have enough space for 65536 UWORDS)
        !           812:     ; a1 = Additive Array
        !           813:     ; 256 UBYTEs
        !           814:     ;
        !           815:     ; the table is organized as follows:
        !           816:     ; 32768 UWORDS positive range, ascending order
        !           817:     ; 32768 UWORDS negative range, ascending order
        !           818:     ; access: (a0,d0.l*2)
        !           819:     ; where d0.w is signed word sample data
        !           820:     ; and the upper word of d0.l is *cleared!*
        !           821: 
        !           822: 
        !           823: _CreateTable  MOVEM.l a2/d2-d6,-(sp)
        !           824: 
        !           825:     LEA 128(a1),a2
        !           826: 
        !           827:     MOVE.l  a2,a1     ; count the number of steps
        !           828:     MOVEQ #128-1,d0   ; in the positive range
        !           829:     MOVEQ #0,d5
        !           830: .countpositive  MOVE.b  (a1)+,d1
        !           831:     EXT.w d1
        !           832:     EXT.l d1
        !           833:     ADD.l d1,d5
        !           834:     DBRA  d0,.countpositive ; d5=number of steps
        !           835:     MOVE.l  #32768,d6   ; reset stretch counter
        !           836: 
        !           837:     MOVE.l  a2,a1     ; middle value in calibdata
        !           838:     MOVE.w  #32768-1,d0   ; number of positive values -1
        !           839:     MOVEQ #0,d1     ; HI value
        !           840:     MOVEQ #0,d2     ; LO value
        !           841:     MOVEQ #0,d3     ; counter
        !           842: .fetchnext2 MOVE.b  (a1)+,d4    ; add calibtable to counter
        !           843:     EXT.w d4
        !           844:     ADD.w d4,d3
        !           845: .outerloop2 TST.w d3
        !           846:     BGT.s .positive2
        !           847: .negative2  ADDQ.w  #1,d1     ; increment HI value
        !           848:     SUB.w d4,d2     ; reset LO value
        !           849:     BRA.s .fetchnext2
        !           850: .positive2  MOVE.b  d1,(a0)+    ; store HI and LO value
        !           851:     MOVE.b  d2,(a0)+
        !           852:     SUB.l d5,d6     ; stretch the table
        !           853:     BPL.s .repeat2    ; to 32768 entries
        !           854:     ADD.l #32768,d6
        !           855:     ADDQ.w  #1,d2     ; increment LO value
        !           856:     SUBQ.w  #1,d3     ; decrement counter
        !           857: .repeat2  DBRA  d0,.outerloop2
        !           858: 
        !           859:     MOVE.l  a2,a1     ; count the number of steps
        !           860:     MOVEQ #128-1,d0   ; in the negative range
        !           861:     MOVEQ #0,d5
        !           862: .countnegative  MOVE.b  -(a1),d1
        !           863:     EXT.w d1
        !           864:     EXT.l d1
        !           865:     ADD.l d1,d5
        !           866:     DBRA  d0,.countnegative ; d5=number of steps
        !           867:     MOVE.l  #32768,d6   ; reset stretch counter
        !           868: 
        !           869:     ADD.l #2*32768,a0   ; place at the end of the table
        !           870:     MOVE.l  a2,a1     ; middle value in calibdata
        !           871:     MOVE.w  #32768-1,d0   ; number of negative values -1
        !           872:     MOVEQ #-1,d1      ; HI value
        !           873:     MOVEQ #-1,d2      ; LO value
        !           874:     MOVEQ #0,d3     ; counter
        !           875: .fetchnext1 MOVE.b  -(a1),d4    ; add calibtable to counter
        !           876:     EXT.w d4
        !           877:     ADD.w d4,d3
        !           878:     ADD.w d4,d2     ; maximize LO value
        !           879: .outerloop1 TST.w d3
        !           880:     BGT.s .positive1
        !           881: .negative1  SUBQ.w  #1,d1
        !           882:     BRA.s .fetchnext1
        !           883: .positive1  MOVE.b  d2,-(a0)    ; store LO and HI value
        !           884:     MOVE.b  d1,-(a0)
        !           885:     SUB.l d5,d6     ; stretch the table
        !           886:     BPL.s .repeat1    ; to 32768 entries
        !           887:     ADD.l #32768,d6
        !           888:     SUBQ.w  #1,d2     ; decrement lo value
        !           889:     SUBQ.w  #1,d3     ; decrement counter
        !           890: .repeat1  DBRA  d0,.outerloop1
        !           891: 
        !           892:     MOVEM.l (sp)+,a2/d2-d6
        !           893:     RTS
        !           894: 
        !           895: 
        !           896: ****** [driver].audio/AHIsub_FreeAudio **************************************
        !           897: *
        !           898: *   NAME
        !           899: *       AHIsub_FreeAudio -- Deallocates the audio hardware.
        !           900: *
        !           901: *   SYNOPSIS
        !           902: *       AHIsub_FreeAudio( audioctrl );
        !           903: *                         A2
        !           904: *
        !           905: *       void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
        !           906: *
        !           907: *   IMPLEMENTATION
        !           908: *       Deallocate the audio hardware AND other resources allocated in
        !           909: *       AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
        !           910: *       'ahi.device' before this Call is made.
        !           911: *
        !           912: *   INPUTS
        !           913: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !           914: *
        !           915: *   NOTES
        !           916: *       It must be safe To Call this routine Even If AHIsub_AllocAudio()
        !           917: *       was never called, failed OR called more than once.
        !           918: *
        !           919: *   SEE ALSO
        !           920: *       AHIsub_AllocAudio()
        !           921: *
        !           922: *****************************************************************************
        !           923: *
        !           924: *
        !           925: 
        !           926: AHIsub_FreeAudio:
        !           927:   pushm d2-d7/a2-a6
        !           928: 
        !           929:   MOVE.l  a6,a5
        !           930:   MOVE.l  pb_SysLib(a5),a6
        !           931: 
        !           932:   MOVE.l  ahiac_DriverData(a2),d0
        !           933:   BEQ .nopaula
        !           934:   MOVE.l  d0,a3
        !           935: 
        !           936:   MOVE.l  p_CalibrationTable(a3),d0
        !           937:   BEQ.b .notable
        !           938:   MOVE.l  d0,a1
        !           939:   call  FreeVec
        !           940: .notable
        !           941:   TST.l p_audiodev(a3)
        !           942:   BNE.b .noaudiodev
        !           943:   MOVE.l  p_audioreq(a3),a1         ;bernd#1
        !           944:   MOVE.w  #CMD_RESET,IO_COMMAND(a1) ;Restore audio interrupts
        !           945:   BSR.w BeginIO
        !           946:   MOVE.l  p_audioport(a3),a0
        !           947:   call  WaitPort
        !           948:   MOVE.l  p_audioport(a3),a0
        !           949:   call  GetMsg
        !           950:   MOVE.l  p_audioreq(a3),a1
        !           951:   SUBQ.l  #1,p_audiodev(a3)
        !           952:   call  CloseDevice
        !           953: .noaudiodev
        !           954:   MOVE.l  p_audioreq(a3),d0
        !           955:   BEQ.b .noaudioreq
        !           956:   MOVE.l  d0,a1
        !           957:   call  FreeVec
        !           958: .noaudioreq
        !           959:   MOVE.l  p_audioport(a3),d0
        !           960:   BEQ.b .noaudioport
        !           961:   MOVE.l  d0,a0
        !           962:   call  DeleteMsgPort
        !           963: .noaudioport
        !           964:   MOVE.l  pb_CardResource(a5),d0
        !           965:   BEQ .noaura
        !           966:   MOVE.l  d0,a6
        !           967:   MOVE.l  p_CardHandle(a3),d0
        !           968:   BEQ .noaura
        !           969:   MOVE.l  d0,a1
        !           970:   call  EndCardAccess
        !           971:   MOVE.l  p_CardHandle(a3),a1
        !           972:   MOVEQ #CARDF_REMOVEHANDLE,d0
        !           973:   call  ReleaseCard
        !           974: .noaura
        !           975:   MOVE.l  pb_SysLib(a5),a6
        !           976:   MOVE.l  p_CardHandle(a3),d0
        !           977:   BEQ .nocardhandle
        !           978:   MOVE.l  d0,a1
        !           979:   call  FreeVec
        !           980: .nocardhandle
        !           981:   MOVE.l  pb_MiscResource(a5),a6
        !           982:   TST.l p_ParPortUser(a3)
        !           983:   BNE.b .noparport
        !           984:   MOVEQ #MR_PARALLELPORT,d0
        !           985:   JSR MR_FREEMISCRESOURCE(a6)
        !           986: .noparport
        !           987:   TST.l p_ParBitsUser(a3)
        !           988:   BNE.b .noparbits
        !           989:   MOVEQ #MR_PARALLELBITS,d0
        !           990:   JSR MR_FREEMISCRESOURCE(a6)
        !           991: .noparbits
        !           992:   MOVE.l  pb_SysLib(a5),a6
        !           993:   MOVE.l  a3,a1
        !           994:   CLR.l ahiac_DriverData(a2)
        !           995:   call  FreeVec
        !           996: .nopaula
        !           997:   MOVEQ #0,d0
        !           998:   popm  d2-d7/a2-a6
        !           999:   RTS
        !          1000: 
        !          1001: 
        !          1002: ****** [driver].audio/AHIsub_Disable ****************************************
        !          1003: *
        !          1004: *   NAME
        !          1005: *       AHIsub_Disable -- Temporary turn Off audio interrupt/task
        !          1006: *
        !          1007: *   SYNOPSIS
        !          1008: *       AHIsub_Disable( audioctrl );
        !          1009: *                       A2
        !          1010: *
        !          1011: *       void AHIsub_Disable( struct AHIAudioCtrlDrv * );
        !          1012: *
        !          1013: *   IMPLEMENTATION
        !          1014: *       If you are lazy, Then Call exec.library/Disable().
        !          1015: *       If you are smart, only Disable your own interrupt OR task.
        !          1016: *
        !          1017: *   INPUTS
        !          1018: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          1019: *
        !          1020: *   NOTES
        !          1021: *       This Call should be guaranteed To preserve all registers.
        !          1022: *       This Call nests.
        !          1023: *
        !          1024: *   SEE ALSO
        !          1025: *       AHIsub_Enable(), exec.library/Disable()
        !          1026: *
        !          1027: *****************************************************************************
        !          1028: *
        !          1029: *
        !          1030: 
        !          1031: AHIsub_Disable:
        !          1032:   push  a3
        !          1033:   MOVE.l  ahiac_DriverData(a2),a3
        !          1034:   ADDQ.w  #1,p_DisableCount(a3)
        !          1035:   MOVE.w  #INTF_AUD0,CUSTOM+INTENA
        !          1036: ;  moveq #2,d0
        !          1037: ;  moveq #0,d1
        !          1038: ;  jsr.l $f0ffb0
        !          1039:   pop a3
        !          1040:   RTS
        !          1041: 
        !          1042: ****** [driver].audio/AHIsub_Enable *****************************************
        !          1043: *
        !          1044: *   NAME
        !          1045: *       AHIsub_Enable -- Turn On audio interrupt/task
        !          1046: *
        !          1047: *   SYNOPSIS
        !          1048: *       AHIsub_Enable( audioctrl );
        !          1049: *                      A2
        !          1050: *
        !          1051: *       void AHIsub_Enable( struct AHIAudioCtrlDrv * );
        !          1052: *
        !          1053: *   IMPLEMENTATION
        !          1054: *       If you are lazy, Then Call exec.library/Enable().
        !          1055: *       If you are smart, only Enable your own interrupt OR task.
        !          1056: *
        !          1057: *   INPUTS
        !          1058: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          1059: *
        !          1060: *   NOTES
        !          1061: *       This Call should be guaranteed To preserve all registers.
        !          1062: *       This Call nests.
        !          1063: *
        !          1064: *   SEE ALSO
        !          1065: *       AHIsub_Disable(), exec.library/Enable()
        !          1066: *
        !          1067: *****************************************************************************
        !          1068: *
        !          1069: *
        !          1070: 
        !          1071: AHIsub_Enable:
        !          1072:   push  a3
        !          1073:   MOVE.l  ahiac_DriverData(a2),a3
        !          1074:   SUBQ.w  #1,p_DisableCount(a3)
        !          1075:   BNE.b .exit
        !          1076:   MOVE.w  #INTF_SETCLR!INTF_AUD0,CUSTOM+INTENA
        !          1077: ;  moveq #2,d0
        !          1078: ;  moveq #1,d1
        !          1079: ;  jsr.l $f0ffb0
        !          1080: .exit
        !          1081:   pop a3
        !          1082:   RTS
        !          1083: 
        !          1084: ****** [driver].audio/AHIsub_Start ******************************************
        !          1085: *
        !          1086: *   NAME
        !          1087: *       AHIsub_Start -- Starts PlayBack OR recording
        !          1088: *
        !          1089: *   SYNOPSIS
        !          1090: *       error = AHIsub_Start( flags, audioctrl );
        !          1091: *       D0                    D0     A2
        !          1092: *
        !          1093: *       ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
        !          1094: *
        !          1095: *   IMPLEMENTATION
        !          1096: *       What To do depends what you returned in AHIsub_AllocAudio().
        !          1097: *
        !          1098: *     * First, assume bit AHISB_PLAY in flags is set. This means that you
        !          1099: *       should begin PlayBack.
        !          1100: *
        !          1101: *     - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
        !          1102: *
        !          1103: *       A) Allocate a mixing Buffer of ahiac_BuffSize bytes. The Buffer must
        !          1104: *          be long aligned!
        !          1105: *       B) Create/Start an interrupt OR task that will do 1-6 over AND over
        !          1106: *          again Until AHIsub_Stop() is called. Note that it is NOT a good
        !          1107: *          idea To do the actual mixing AND conversion in a real hardware
        !          1108: *          interrupt. Signal a task OR create a Software Interrupt To do
        !          1109: *          the number crunching.
        !          1110: *
        !          1111: *       1) Call the user Hook ahiac_PlayerFunc with the following parameters:
        !          1112: *                  A0 - (struct Hook *)
        !          1113: *                  A2 - (struct AHIAudioCtrlDrv *)
        !          1114: *                  A1 - Set To Null.
        !          1115: *
        !          1116: *       2) [Call the ahiac_PreTimer Function. If it returns True (Z will be
        !          1117: *          cleared so you don't have To test d0), skip Step 3 AND 4. This
        !          1118: *          is Used To avoid overloading the CPU. This Step is optional.
        !          1119: *          A2 is assumed To Point To struct AHIAudioCtrlDrv. All registers
        !          1120: *          except d0 are preserved.  (V4)]
        !          1121: *
        !          1122: *       3) Call the mixing Hook (ahiac_MixerFunc) with the following
        !          1123: *          parameters:
        !          1124: *                  A0 - (struct Hook *)           - The Hook itself
        !          1125: *                  A2 - (struct AHIAudioCtrlDrv *)
        !          1126: *                  A1 - (WORD *[])                - The mixing Buffer.
        !          1127: *          Note that ahiac_MixerFunc preserves ALL registers.
        !          1128: *          The user Hook ahiac_SoundFunc will be called by the mixing
        !          1129: *          routine when a sample have been processed, so you don't have To
        !          1130: *          worry about that.
        !          1131: *          How the Buffer will be filled is indicated by ahiac_Flags.
        !          1132: *          It is always filled with signed 16-bit (32 bit If AHIDBB_HIFI in
        !          1133: *          in ahiac_Flags is set) words, Even If PlayBack is 8 bit. If
        !          1134: *          AHIDBB_STEREO is set (in ahiac_Flags), Data For left AND right
        !          1135: *          channel are interleaved:
        !          1136: *           1st sample left channel,
        !          1137: *           1st sample right channel,
        !          1138: *           2nd sample left channel,
        !          1139: *           ...,
        !          1140: *           ahiac_BuffSamples:th sample left channel,
        !          1141: *           ahiac_BuffSamples:th sample right channel.
        !          1142: *          If AHIDBB_STEREO is cleared, the mono Data is stored:
        !          1143: *           1st sample,
        !          1144: *           2nd sample,
        !          1145: *           ...,
        !          1146: *           ahiac_BuffSamples:th sample.
        !          1147: *          Note that neither AHIDBB_STEREO nor AHIDBB_HIFI will be set If
        !          1148: *          you didn't report that you understand these flags when
        !          1149: *          AHI_AllocAudio() was called.
        !          1150: *
        !          1151: *          For AHI V2, the Type of Buffer is also available in ahiac_BuffType.
        !          1152: *          It is suggested that you Use this value instead. ahiac_BuffType
        !          1153: *          can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S AND AHIST_S32S.
        !          1154: *
        !          1155: *       4) Convert the Buffer If needed AND feed it To the audio hardware.
        !          1156: *          Note that you may have To clear CPU caches If you are using DMA
        !          1157: *          To play the Buffer, AND the Buffer is NOT allocated in non-
        !          1158: *          cachable RAM.
        !          1159: *
        !          1160: *       5) [Call the ahiac_PostTimer Function. A2 is assumed To Point To
        !          1161: *          struct AHIAudioCtrlDrv. All registers are preserved.  (V4)]
        !          1162: *
        !          1163: *       6) Wait Until the whole Buffer has been played, Then Repeat.
        !          1164: *
        !          1165: *       Use double buffering If possible!
        !          1166: *
        !          1167: *       You may DECREASE ahiac_BuffSamples slightly, For example To force an
        !          1168: *       Even number of samples To be mixed. By doing this you will make
        !          1169: *       ahiac_PlayerFunc To be called at wrong frequency so be careful!
        !          1170: *       Even If ahiac_BuffSamples is defined ULONG, it will never be greater
        !          1171: *       than 65535.
        !          1172: *
        !          1173: *       ahiac_BuffSize is the Largest size of the mixing Buffer that will be
        !          1174: *       needed Until AHIsub_Stop() is called.
        !          1175: *
        !          1176: *       ahiac_MaxBuffSamples is the Maximum number of samples that will be
        !          1177: *       mixed (Until AHIsub_Stop() is called). You can Use this value If you
        !          1178: *       need To allocate DMA buffers.
        !          1179: *
        !          1180: *       ahiac_MinBuffSamples is the minimum number of samples that will be
        !          1181: *       mixed. Most drivers will ignore it.
        !          1182: *
        !          1183: *       If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
        !          1184: *       ahiac_BuffSize is large enough To hold two buffers. The mixing Buffer
        !          1185: *       will be filled with the wet Buffer first, immediately followed by the
        !          1186: *       dry Buffer. I.e., ahiac_BuffSamples sample Frames wet Data, Then
        !          1187: *       ahiac_BuffSamples sample Frames dry Data. The DSP fx should only be
        !          1188: *       applied To the wet Buffer, AND the two buffers should Then be added
        !          1189: *       together. (V4)
        !          1190: *
        !          1191: *     - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
        !          1192: *       except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
        !          1193: *       ahiac_PlayerFreq times per second, clocked by timers On your Sound
        !          1194: *       card OR by using 'realtime.library'. No other AMIGA resources may
        !          1195: *       be Used For timing (like direct CIA timers).
        !          1196: *       ahiac_MinBuffSamples AND ahiac_MaxBuffSamples are undefined If
        !          1197: *       AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit NOT set).
        !          1198: *
        !          1199: *     - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
        !          1200: *       the AHISB_TIMING bit set, Then just Start PlayBack. Don't forget To
        !          1201: *       Call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
        !          1202: *       own timing hardware OR 'realtime.library' may be Used. Note that
        !          1203: *       ahiac_MixerFunc, ahiac_BuffSamples, ahiac_MinBuffSamples,
        !          1204: *       ahiac_MaxBuffSamples AND ahiac_BuffSize are undefined. ahiac_MixFreq
        !          1205: *       is the frequency the user wants To Use For recording, If you support
        !          1206: *       that.
        !          1207: *
        !          1208: *     * Second, assume bit AHISB_RECORD in flags is set. This means that you
        !          1209: *       should Start To sample. Create a interrupt OR task that does the
        !          1210: *       following:
        !          1211: *
        !          1212: *       Allocate a Buffer (you chose size, but try To keep it reasonable
        !          1213: *       small To avoid delays - it is suggested that RecordFunc is called
        !          1214: *       at least 4 times/second For the lowers sampling rate, AND more often
        !          1215: *       For higher rates), AND fill it with the sampled Data. The Buffer must
        !          1216: *       be long aligned, AND it's size must be evenly divisible by four.
        !          1217: *       The Format should always be AHIST_S16S (Even with 8 bit mono samplers),
        !          1218: *       which means:
        !          1219: *           1st sample left channel,
        !          1220: *           1st sample right channel (same as prev. If mono),
        !          1221: *           2nd sample left channel,
        !          1222: *           ... etc.
        !          1223: *       Each sample is a signed word (WORD). The sample rate should be equal
        !          1224: *       To the mixing rate.
        !          1225: *
        !          1226: *       Call the ahiac_SamplerFunc Hook with the following parameters:
        !          1227: *           A0 - (struct Hook *)           - The Hook itself
        !          1228: *           A2 - (struct AHIAudioCtrlDrv *)
        !          1229: *           A1 - (struct AHIRecordMessage *)
        !          1230: *       The message should be filled as follows:
        !          1231: *           ahirm_Type - Set To AHIST_S16S.
        !          1232: *           ahirm_Buffer - A Pointer To the filled Buffer.
        !          1233: *           ahirm_Samples - How many sample Frames stored.
        !          1234: *       You must NOT destroy the Buffer Until Next time the Hook is called.
        !          1235: *
        !          1236: *       Repeat Until AHIsub_Stop() is called.
        !          1237: *
        !          1238: *     * Note that both bits may be set when this Function is called.
        !          1239: *
        !          1240: *   INPUTS
        !          1241: *       flags - See <libraries/ahi_sub.h>.
        !          1242: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          1243: *
        !          1244: *   RESULT
        !          1245: *       Returns AHIE_OK If successful, Else an error code as defined
        !          1246: *       in <devices/ahi.h>. AHIsub_Stop() will always be called, Even
        !          1247: *       If this Call failed.
        !          1248: *
        !          1249: *   NOTES
        !          1250: *       The driver must be able To Handle multiple calls To this routine
        !          1251: *       without preceding calls To AHIsub_Stop().
        !          1252: *
        !          1253: *   SEE ALSO
        !          1254: *       AHIsub_Update(), AHIsub_Stop()
        !          1255: *
        !          1256: *****************************************************************************
        !          1257: *
        !          1258: *
        !          1259: *
        !          1260: 
        !          1261: AHIsub_Start:
        !          1262:   pushm d2-d7/a2-a6
        !          1263: 
        !          1264:   MOVE.l  d0,d7
        !          1265:   LEA CUSTOM,a4
        !          1266:   MOVE.l  ahiac_DriverData(a2),a3
        !          1267: 
        !          1268:   BTST  #AHISB_PLAY,d0
        !          1269:   BEQ .dont_play
        !          1270: 
        !          1271: **
        !          1272: *** AHISB_PLAY
        !          1273: **
        !          1274:   MOVEQ #AHISF_PLAY,d0
        !          1275:   call  AHIsub_Stop     ;Stop current playback if any.
        !          1276:   call  AHIsub_Update     ;fill variables
        !          1277: 
        !          1278:   MOVE.l  a6,a5
        !          1279:   MOVE.l  pb_SysLib(a5),a6
        !          1280: 
        !          1281:   MOVE.l  ahiac_BuffSize(a2),d0
        !          1282:   MOVE.l  #MEMF_PUBLIC|MEMF_CLEAR,d1
        !          1283:   call  AllocVec
        !          1284:   MOVE.l  d0,p_Mixbuffer(a3)
        !          1285:   BEQ .error_nomem
        !          1286: 
        !          1287:   MOVE.l  ahiac_MixFreq(a2),d1
        !          1288:   BSR.w calcperiod
        !          1289:   MOVE.l  d1,p_AudPer(a3)
        !          1290:         MOVE.l #0,flag
        !          1291:         CMP.w #$7f,d1 ;use old routines
        !          1292:         BGE .10
        !          1293:         MOVE.l #1,flag
        !          1294: .10
        !          1295: * The init*bit? routines allocates p_DMAbuffer, sets up p_AudPtr, sets the Volume,
        !          1296: * stores the correct interrupt routines in p_PlayInt's AND p_PlaySoftInt's IS_CODE.
        !          1297: 
        !          1298:   PEA .1(pc)
        !          1299:   MOVE.b  p_Flags(a3),d0
        !          1300:   AND.b #PF_STEREO!PF_14BIT,d0
        !          1301:   BEQ.w init16bitM
        !          1302:   CMP.b #PF_STEREO,d0
        !          1303:   BEQ.w init16bitS
        !          1304:   CMP.b #PF_14BIT,d0
        !          1305:   BEQ.w init14bitM
        !          1306:   BRA.w init14bitS
        !          1307: .1
        !          1308:   TST.l d0
        !          1309:   BNE .exit
        !          1310: 
        !          1311: * Install play interrupt
        !          1312:   LEA p_PlayInt(a3),a1
        !          1313:   MOVEQ #INTB_AUD0,d0
        !          1314:   call  SetIntVector
        !          1315:   CLR.w p_DisableCount(a3)
        !          1316: 
        !          1317:   MOVE.w  #INTF_SETCLR!INTF_AUD0,INTENA(a4)  ;enable
        !          1318:   MOVE.w  #INTF_SETCLR!INTF_AUD0,INTREQ(a4)  ;start
        !          1319:   MOVE.l  a5,a6
        !          1320: 
        !          1321: 
        !          1322: .dont_play
        !          1323:   BTST  #AHISB_RECORD,d7
        !          1324:   BEQ .dont_record
        !          1325: **
        !          1326: *** AHISB_RECORD
        !          1327: **
        !          1328:   BTST  #PB_14BIT,p_Flags(a3)   ;Sanity check...
        !          1329:   BNE .error_unknown
        !          1330: 
        !          1331:   MOVEQ #AHISF_RECORD,d0
        !          1332:   call  AHIsub_Stop     ;Stop current recording if any.
        !          1333: 
        !          1334:   MOVE.l  a6,a5
        !          1335:   MOVE.l  pb_SysLib(a5),a6
        !          1336: 
        !          1337:   MOVE.l  #RECORDSAMPLES*4,d0
        !          1338:   MOVE.l  #MEMF_PUBLIC,d1
        !          1339:   call  AllocVec
        !          1340:   MOVE.l  d0,p_RecBuffer1(a3)
        !          1341:   BEQ .error_nomem
        !          1342: 
        !          1343:   MOVE.l  d0,p_RecFillPtr(a3)
        !          1344:   MOVE.w  #RECORDSAMPLES,p_RecFillCount(a3)
        !          1345: 
        !          1346:   MOVE.l  #RECORDSAMPLES*4,d0
        !          1347:   MOVE.l  #MEMF_PUBLIC,d1
        !          1348:   call  AllocVec
        !          1349:   MOVE.l  d0,p_RecBuffer2(a3)
        !          1350:   BEQ .error_nomem
        !          1351: 
        !          1352:   MOVE.l  ahiac_MixFreq(a2),d1
        !          1353:   BSR.w calcperiod
        !          1354:   LSR.w #1,d1       ;Period/2 => Frequency72
        !          1355:   MOVE.w  d1,AUD2PER(a4)
        !          1356:   MOVE.w  d1,AUD3PER(a4)
        !          1357:   MOVE.w  p_MonitorVolume(a3),AUD2VOL(a4)
        !          1358:   MOVE.w  p_MonitorVolume(a3),AUD3VOL(a4)
        !          1359: 
        !          1360: * Install Record interrupt
        !          1361:   MOVE.w  p_Input(a3),d0
        !          1362:   BEQ .parsampler
        !          1363:   CMP.w #1,d0
        !          1364:   BEQ .aurasampler
        !          1365:   BRA .error_unknown
        !          1366: .parsampler
        !          1367:   TST.b p_Parallel(a3)      ;Parrallel port allocated?
        !          1368:   BEQ .error_unknown
        !          1369:   LEA p_RecIntData(a3),a1
        !          1370:   MOVE.l  a1,IS_DATA+p_RecInt(a3)
        !          1371:   MOVE.l  #RecordInterrupt,IS_CODE+p_RecInt(a3)
        !          1372:   BRA .setrecint
        !          1373: .aurasampler
        !          1374:   TST.l p_AuraAddress(a3)   ;Aura sampler allocated?
        !          1375:   BEQ .error_unknown
        !          1376:   LEA p_RecIntDataAura(a3),a1
        !          1377:   MOVE.l  a1,IS_DATA+p_RecInt(a3)
        !          1378:   MOVE.l  #RecordInterruptAura,IS_CODE+p_RecInt(a3)
        !          1379: .setrecint
        !          1380:   LEA p_RecInt(a3),a1
        !          1381:   MOVEQ #INTB_AUD3,d0
        !          1382:   call  SetIntVector
        !          1383: 
        !          1384:   MOVE.w  #DMAF_AUD2!DMAF_AUD3,DMACON(a4)   ;disable DMA
        !          1385:   MOVE.w  #INTF_SETCLR!INTF_AUD3,INTENA(a4) ;enable
        !          1386:   MOVE.w  #INTF_SETCLR!INTF_AUD3,INTREQ(a4) ;start
        !          1387: 
        !          1388: .dont_record
        !          1389: .return
        !          1390: 
        !          1391: 
        !          1392:   MOVEQ #AHIE_OK,d0
        !          1393: .exit
        !          1394:   popm  d2-d7/a2-a6
        !          1395:   RTS
        !          1396: .error_nomem
        !          1397:   MOVEQ #AHIE_NOMEM,d0
        !          1398:   BRA.b .exit
        !          1399: .error_unknown
        !          1400:   MOVEQ #AHIE_UNKNOWN,d0
        !          1401:   BRA.b .exit
        !          1402: 
        !          1403: 
        !          1404: ;in:
        !          1405: * a2  AudioCtrl
        !          1406: * a3  paula
        !          1407: * a4  CUSTOM
        !          1408: * a5  paulaBase
        !          1409: * a6  ExecBase
        !          1410: 
        !          1411: init16bitM:
        !          1412:   MOVE.l  #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
        !          1413:   MOVE.l  #SoftInt_16bitM,IS_CODE+p_PlaySoftInt(a3)
        !          1414: 
        !          1415:   MOVE.l  ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
        !          1416: 
        !          1417:   ADDQ.l  #1,d0
        !          1418:   BCLR  #0,d0       ;force even
        !          1419:   MOVE.l  d0,d2       ;d2 = channel size
        !          1420:   LSL  #1,d2
        !          1421: ;  move.l d0,ahiac_BuffSamples(a2)
        !          1422:   LSL.l   #1,d0       ;Double buffer
        !          1423:   LSL.l   #1,d0       ;it's actually 16 bits
        !          1424:   MOVE.l  #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
        !          1425:   call  AllocVec
        !          1426:   MOVE.l  d0,p_DMAbuffer(a3)
        !          1427:   BEQ .nomem
        !          1428: 
        !          1429:   MOVE.l  d0,p_AudPtr1A(a3)
        !          1430:   MOVE.l  d0,p_AudPtr2A(a3)
        !          1431:   ADD.l d2,d0
        !          1432:   MOVE.l  d0,p_AudPtr1B(a3)
        !          1433:   MOVE.l  d0,p_AudPtr2B(a3)
        !          1434: 
        !          1435:   MOVEQ #0,d0
        !          1436:   RTS
        !          1437: .nomem
        !          1438:   MOVEQ #AHIE_NOMEM,d0
        !          1439:   RTS
        !          1440: 
        !          1441: ;in:
        !          1442: * a2  AudioCtrl
        !          1443: * a3  paula
        !          1444: * a5  paulaBase
        !          1445: * a6  ExecBase
        !          1446: init16bitS:
        !          1447:   MOVE.l  #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
        !          1448:   MOVE.l  #SoftInt_16bitS,IS_CODE+p_PlaySoftInt(a3)
        !          1449: 
        !          1450:   MOVE.l  ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
        !          1451:   ADDQ.l  #1,d0
        !          1452:   BCLR  #0,d0       ;force even
        !          1453:   MOVE.l  d0,d2       ;d2 = channel size
        !          1454:   LSL  #1,d2
        !          1455: ;  move.l d0,ahiac_BuffSamples(a2)
        !          1456: 
        !          1457:   LSL.l #2,d0       ;Double buffer + Stereo
        !          1458:   LSL.l   #1,d0       ;it's actually 16 bits
        !          1459:   MOVE.l  #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
        !          1460:   call  AllocVec
        !          1461:   MOVE.l  d0,p_DMAbuffer(a3)
        !          1462:   BEQ .nomem
        !          1463: 
        !          1464:   MOVE.l  d0,p_AudPtr1A(a3)
        !          1465:   ADD.l d2,d0
        !          1466:   MOVE.l  d0,p_AudPtr2A(a3)
        !          1467:   ADD.l d2,d0
        !          1468:   MOVE.l  d0,p_AudPtr1B(a3)
        !          1469:   ADD.l d2,d0
        !          1470:   MOVE.l  d0,p_AudPtr2B(a3)
        !          1471: 
        !          1472:   MOVEQ #0,d0
        !          1473:   RTS
        !          1474: .nomem
        !          1475:   MOVEQ #AHIE_NOMEM,d0
        !          1476:   RTS
        !          1477: 
        !          1478: ;in:
        !          1479: * a2  AudioCtrl
        !          1480: * a3  paula
        !          1481: * a5  paulaBase
        !          1482: * a6  ExecBase
        !          1483: init14bitM:
        !          1484:   MOVE.l  #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
        !          1485:   LEA SoftInt_14bitM(pc),a0
        !          1486:   TST.l p_CalibrationTable(a3)
        !          1487:   BEQ.b .nocalib
        !          1488:   LEA SoftInt_14CbitM(pc),a0
        !          1489: .nocalib
        !          1490:   MOVE.l  a0,IS_CODE+p_PlaySoftInt(a3)
        !          1491: 
        !          1492:   MOVE.l  ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
        !          1493:   ADDQ.l  #1,d0
        !          1494:   BCLR  #0,d0       ;force even
        !          1495:   MOVE.l  d0,d2       ;d2 = channel size
        !          1496: 
        !          1497:   LSL.l #2,d0       ;Double buffer + 2W8 bit
        !          1498:   MOVE.l  #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
        !          1499:   call  AllocVec
        !          1500:   MOVE.l  d0,p_DMAbuffer(a3)
        !          1501:   BEQ .nomem
        !          1502: 
        !          1503:   MOVE.l  d0,p_AudPtr1A(a3)
        !          1504:   MOVE.l  d0,p_AudPtr2A(a3)
        !          1505:   ADD.l d2,d0
        !          1506:   MOVE.l  d0,p_AudPtr4A(a3)
        !          1507:   MOVE.l  d0,p_AudPtr3A(a3)
        !          1508:   ADD.l d2,d0
        !          1509:   MOVE.l  d0,p_AudPtr1B(a3)
        !          1510:   MOVE.l  d0,p_AudPtr2B(a3)
        !          1511:   ADD.l d2,d0
        !          1512:   MOVE.l  d0,p_AudPtr4B(a3)
        !          1513:   MOVE.l  d0,p_AudPtr3B(a3)
        !          1514: 
        !          1515:   MOVE.w  #64,AUD0VOL(a4)
        !          1516:   MOVE.w  #64,AUD1VOL(a4)
        !          1517:   MOVE.w  #1,AUD2VOL(a4)
        !          1518:   MOVE.w  #1,AUD3VOL(a4)
        !          1519: 
        !          1520:   MOVEQ #0,d0
        !          1521:   RTS
        !          1522: .nomem
        !          1523:   MOVEQ #AHIE_NOMEM,d0
        !          1524:   RTS
        !          1525: 
        !          1526: ;in:
        !          1527: * a2  AudioCtrl
        !          1528: * a3  paula
        !          1529: * a5  paulaBase
        !          1530: * a6  ExecBase
        !          1531: init14bitS:
        !          1532:   MOVE.l  #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
        !          1533:   LEA SoftInt_14bitS(pc),a0
        !          1534:   TST.l p_CalibrationTable(a3)
        !          1535:   BEQ .nocalib
        !          1536:   ;lea  SoftInt_14CbitS(pc),a0         changed for uae
        !          1537: .nocalib
        !          1538:   MOVE.l  a0,IS_CODE+p_PlaySoftInt(a3)
        !          1539: 
        !          1540: 
        !          1541:   MOVE.l  ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
        !          1542:         ASL.l #2,d0
        !          1543:         MOVE.l d0,ahiac_MaxBuffSamples(a2)
        !          1544:   ADDQ.l  #1,d0
        !          1545:   BCLR  #0,d0       ;force even
        !          1546:   MOVE.l  d0,d2       ;d2 = channel size
        !          1547: 
        !          1548:   LSL.l #3,d0       ;Double buffer + 2W8 bit + Stereo
        !          1549:   MOVE.l  #MEMF_CHIP!MEMF_PUBLIC|MEMF_CLEAR,d1
        !          1550:   call  AllocVec
        !          1551:   MOVE.l  d0,p_DMAbuffer(a3)
        !          1552:   BEQ .nomem
        !          1553: 
        !          1554:   MOVE.l  d0,p_AudPtr1A(a3)
        !          1555:   ADD.l d2,d0
        !          1556:   MOVE.l  d0,p_AudPtr2A(a3)
        !          1557:   ADD.l d2,d0
        !          1558:   MOVE.l  d0,p_AudPtr3A(a3)
        !          1559:   ADD.l d2,d0
        !          1560:   MOVE.l  d0,p_AudPtr4A(a3)
        !          1561:   ADD.l d2,d0
        !          1562:   MOVE.l  d0,p_AudPtr1B(a3)
        !          1563:   ADD.l d2,d0
        !          1564:   MOVE.l  d0,p_AudPtr2B(a3)
        !          1565:   ADD.l d2,d0
        !          1566:   MOVE.l  d0,p_AudPtr3B(a3)
        !          1567:   ADD.l d2,d0
        !          1568:   MOVE.l  d0,p_AudPtr4B(a3)
        !          1569: 
        !          1570:   MOVE.w  #$4849,AUD0VOL(a4)        ;changed for uae
        !          1571:   MOVE.w  #64,AUD1VOL(a4)
        !          1572:   MOVE.w  #1,AUD2VOL(a4)
        !          1573:   MOVE.w  #1,AUD3VOL(a4)
        !          1574: 
        !          1575:   MOVEQ #0,d0
        !          1576:   RTS
        !          1577: .nomem
        !          1578:   MOVEQ #AHIE_NOMEM,d0
        !          1579:   RTS
        !          1580: 
        !          1581: ****** [driver].audio/AHIsub_Update *****************************************
        !          1582: *
        !          1583: *   NAME
        !          1584: *       AHIsub_Update -- Update some variables
        !          1585: *
        !          1586: *   SYNOPSIS
        !          1587: *       AHIsub_Update( flags, audioctrl );
        !          1588: *                      D0     A2
        !          1589: *
        !          1590: *       void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
        !          1591: *
        !          1592: *   IMPLEMENTATION
        !          1593: *       All you have To do is To update some variables:
        !          1594: *       Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
        !          1595: *       ahiac_BuffSamples (AND perhaps ahiac_PlayerFreq If you Use it).
        !          1596: *       Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc AND
        !          1597: *           ahiac_PlayerFreq.
        !          1598: *       Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc AND ahiac_PlayerFreq.
        !          1599: *
        !          1600: *   INPUTS
        !          1601: *       flags - Currently no flags defined.
        !          1602: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          1603: *
        !          1604: *   RESULT
        !          1605: *
        !          1606: *   NOTES
        !          1607: *       This Call must be safe from interrupts.
        !          1608: *
        !          1609: *   SEE ALSO
        !          1610: *       AHIsub_Start()
        !          1611: *
        !          1612: *****************************************************************************
        !          1613: *
        !          1614: *
        !          1615: *
        !          1616: 
        !          1617: AHIsub_Update:
        !          1618:   pushm d2-d7/a2-a6
        !          1619: 
        !          1620:   call  AHIsub_Disable    ;make sure we don't get an interrupt
        !          1621:           ;while updating our local variables
        !          1622:   MOVE.l  ahiac_DriverData(a2),a3
        !          1623: 
        !          1624:   MOVE.l  ahiac_PlayerFunc(a2),a0
        !          1625:   MOVE.l  a0,p_PlayerHook(a3)
        !          1626:   MOVE.l  h_Entry(a0),p_PlayerEntry(a3)
        !          1627: 
        !          1628:   MOVE.l  ahiac_BuffSamples(a2),d0
        !          1629:   MOVE.w  d0,p_AudLen(a3)
        !          1630:   SUBQ.l  #1,d0
        !          1631:   MOVE.l  d0,p_LoopTimes(a3)  ;See softints. (Unrolled)
        !          1632: 
        !          1633:   MOVE.l  ahiac_MixerFunc(a2),a0
        !          1634:   MOVE.l  a0,p_MixHook(a3)
        !          1635:   MOVE.l  h_Entry(a0),p_MixEntry(a3)
        !          1636: 
        !          1637:   MOVE.l  ahiac_PreTimer(a2),p_PreTimer(a3)
        !          1638:   MOVE.l  ahiac_PostTimer(a2),p_PostTimer(a3)
        !          1639: 
        !          1640:   call  AHIsub_Enable
        !          1641:   MOVEQ #0,d0
        !          1642:   popm  d2-d7/a2-a6
        !          1643:   RTS
        !          1644: 
        !          1645: 
        !          1646: ****** [driver].audio/AHIsub_Stop *******************************************
        !          1647: *
        !          1648: *   NAME
        !          1649: *       AHIsub_Stop -- Stops PlayBack.
        !          1650: *
        !          1651: *   SYNOPSIS
        !          1652: *       AHIsub_Stop( flags, audioctrl );
        !          1653: *                    D0     A2
        !          1654: *
        !          1655: *       void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
        !          1656: *
        !          1657: *   IMPLEMENTATION
        !          1658: *       Stop PlayBack AND/OR recording, remove all resources allocated by
        !          1659: *       AHIsub_Start().
        !          1660: *
        !          1661: *   INPUTS
        !          1662: *       flags - See <libraries/ahi_sub.h>.
        !          1663: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          1664: *
        !          1665: *   NOTES
        !          1666: *       It must be safe To Call this routine Even If AHIsub_Start() was never
        !          1667: *       called, failed OR called more than once.
        !          1668: *
        !          1669: *   SEE ALSO
        !          1670: *       AHIsub_Start()
        !          1671: *
        !          1672: *****************************************************************************
        !          1673: *
        !          1674: *
        !          1675: 
        !          1676: AHIsub_Stop:
        !          1677:   pushm d2-d7/a2-a6
        !          1678: 
        !          1679:   LEA CUSTOM,a4
        !          1680:   MOVE.l  a6,a5
        !          1681:   MOVE.l  pb_SysLib(a5),a6
        !          1682:   MOVE.l  ahiac_DriverData(a2),a3
        !          1683: 
        !          1684:   push  d0
        !          1685:   BTST  #AHISB_PLAY,d0
        !          1686:   BEQ .dontplay
        !          1687: 
        !          1688: **
        !          1689: *** AHISB_PLAY
        !          1690: **
        !          1691:   MOVEQ #2,d0
        !          1692:   MOVEQ #0,d1
        !          1693:   jsr.l $F0FFB0
        !          1694:   MOVEQ #3,d0
        !          1695:   MOVEQ #0,d3
        !          1696:   jsr.l $F0FFB0
        !          1697:   MOVEQ #4,d0
        !          1698:   MOVEQ #0,d3
        !          1699:   jsr.l $F0FFB0
        !          1700: 
        !          1701:   MOVEQ #0,d0
        !          1702:   MOVE.w  d0,AUD0VOL(a4)
        !          1703:   MOVE.w  d0,AUD1VOL(a4)
        !          1704:   MOVE.w  d0,AUD2VOL(a4)
        !          1705:   MOVE.w  d0,AUD3VOL(a4)
        !          1706:   MOVE.w  #DMAF_AUDIO,DMACON(a4)    ;disable audio DMA
        !          1707: 
        !          1708:   MOVE.w  #INTF_AUD0,INTENA(a4)
        !          1709:   MOVE.w  #INTF_AUD0,INTREQ(a4)   ;Clear any waiting interrupts
        !          1710:   MOVE.l  #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
        !          1711:   LEA p_PlayInt(a3),a1
        !          1712:   MOVEQ #INTB_AUD0,d0
        !          1713:   call  SetIntVector
        !          1714: 
        !          1715:   MOVE.l  p_DMAbuffer(a3),d0
        !          1716:   BEQ.b .nodmamem
        !          1717:   MOVE.l  d0,a1
        !          1718:   CLR.l p_DMAbuffer(a3)
        !          1719:   call  FreeVec
        !          1720: .nodmamem
        !          1721:   MOVE.l  p_Mixbuffer(a3),d0
        !          1722:   BEQ.b .nomixmem
        !          1723:   MOVE.l  d0,a1
        !          1724:   CLR.l p_Mixbuffer(a3)
        !          1725:   call  FreeVec
        !          1726: .nomixmem
        !          1727: 
        !          1728: .dontplay
        !          1729:   pop d0
        !          1730:   BTST  #AHISB_RECORD,d0
        !          1731:   BEQ .dontrecord
        !          1732: 
        !          1733: **
        !          1734: *** AHISB_RECORD
        !          1735: **
        !          1736:   BTST  #PB_14BIT,p_Flags(a3)   ;Sanity check...
        !          1737:   BNE .dontrecord
        !          1738: 
        !          1739:   MOVE.w  #INTF_AUD3,INTENA(a4)
        !          1740:   MOVE.w  #INTF_AUD3,INTREQ(a4)   ;Clear any waiting interrupts
        !          1741: 
        !          1742:   MOVE.l  #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
        !          1743:   LEA p_RecInt(a3),a1
        !          1744:   MOVEQ #INTB_AUD3,d0
        !          1745:   call  SetIntVector
        !          1746: 
        !          1747:   MOVE.w  #0,AUD2VOL(a4)
        !          1748:   MOVE.w  #0,AUD3VOL(a4)
        !          1749: 
        !          1750:   MOVE.l  p_RecBuffer1(a3),d0
        !          1751:   BEQ.b .norecmem1
        !          1752:   MOVE.l  d0,a1
        !          1753:   CLR.l p_RecBuffer1(a3)
        !          1754:   call  FreeVec
        !          1755: .norecmem1
        !          1756:   MOVE.l  p_RecBuffer2(a3),d0
        !          1757:   BEQ.b .norecmem2
        !          1758:   MOVE.l  d0,a1
        !          1759:   CLR.l p_RecBuffer2(a3)
        !          1760:   call  FreeVec
        !          1761: .norecmem2
        !          1762: .dontrecord
        !          1763: .return
        !          1764:   MOVEQ #0,d0
        !          1765:   popm  d2-d7/a2-a6
        !          1766:   RTS
        !          1767: 
        !          1768: ****** [driver].audio/AHIsub_#? *********************************************
        !          1769: *
        !          1770: *   NAME
        !          1771: *       AHIsub_SetEffect -- Set effect.
        !          1772: *       AHIsub_SetFreq -- Set frequency.
        !          1773: *       AHIsub_SetSound -- Set Sound.
        !          1774: *       AHIsub_SetVol -- Set Volume AND stereo panning.
        !          1775: *       AHIsub_LoadSound -- Prepare a Sound For PlayBack.
        !          1776: *       AHIsub_UnloadSound -- Discard a Sound.
        !          1777: *
        !          1778: *   SYNOPSIS
        !          1779: *       See functions in 'ahi.device'.
        !          1780: *
        !          1781: *   IMPLEMENTATION
        !          1782: *       If AHIsub_AllocAudio() did NOT Return with bit AHISB_MIXING set,
        !          1783: *       all user calls To these Function will be routed To the driver.
        !          1784: *
        !          1785: *       If AHIsub_AllocAudio() did Return with bit AHISB_MIXING set, the
        !          1786: *       calls will first be routed To the driver, AND only handled by
        !          1787: *       'ahi.device' If the driver returned AHIS_UNKNOWN. This way it is
        !          1788: *       possible To ADD effects that the Sound card handles On its own, like
        !          1789: *       Filter AND echo effects.
        !          1790: *
        !          1791: *       For what each Function does, see the autodocs For 'ahi.device'.
        !          1792: *
        !          1793: *   INPUTS
        !          1794: *       See functions in 'ahi.device'.
        !          1795: *
        !          1796: *   NOTES
        !          1797: *       See functions in 'ahi.device'.
        !          1798: *
        !          1799: *   SEE ALSO
        !          1800: *       ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
        !          1801: *       ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
        !          1802: *       ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
        !          1803: *
        !          1804: *
        !          1805: *****************************************************************************
        !          1806: *
        !          1807: *
        !          1808: 
        !          1809: AHIsub_SetVol:
        !          1810: AHIsub_SetFreq:
        !          1811: AHIsub_SetSound:
        !          1812: AHIsub_SetEffect:
        !          1813: AHIsub_LoadSound:
        !          1814: AHIsub_UnloadSound:
        !          1815:   MOVEQ #AHIS_UNKNOWN,d0
        !          1816:   RTS
        !          1817: 
        !          1818: ****** [driver].audio/AHIsub_GetAttr ****************************************
        !          1819: *
        !          1820: *   NAME
        !          1821: *       AHIsub_GetAttr -- Returns information about audio modes OR driver
        !          1822: *
        !          1823: *   SYNOPSIS
        !          1824: *       AHIsub_GetAttr( attribute, argument, Default, taglist, audioctrl );
        !          1825: *       D0              D0         D1        D2       A1       A2
        !          1826: *
        !          1827: *       LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
        !          1828: *                            struct AHIAudioCtrlDrv * );
        !          1829: *
        !          1830: *   IMPLEMENTATION
        !          1831: *       Return the attribute based On a tag List AND an AHIAudioCtrlDrv
        !          1832: *       structure, which are the same that will be passed To
        !          1833: *       AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
        !          1834: *       unknown To you, Return the Default.
        !          1835: *
        !          1836: *   INPUTS
        !          1837: *       attribute - Is really a Tag AND can be one of the following:
        !          1838: *           AHIDB_Bits - Return how many output bits the tag List will
        !          1839: *               result in.
        !          1840: *           AHIDB_MaxChannels - Return the resulting number of channels.
        !          1841: *           AHIDB_Frequencies - Return how many mixing/sampling frequencies
        !          1842: *               you support
        !          1843: *           AHIDB_Frequency - Return the argument:th frequency
        !          1844: *                Example: You support 3 frequencies 32, 44.1 AND 48 kHz.
        !          1845: *                   If argument is 1, Return 44100.
        !          1846: *           AHIDB_Index - Return the Index which gives the frequency closest
        !          1847: *               To argument.
        !          1848: *               Example: You support 3 frequencies 32, 44.1 AND 48 kHz.
        !          1849: *                   If argument is 40000, Return 1 (=> 44100).
        !          1850: *           AHIDB_Author - Return Pointer To name of driver author:
        !          1851: *               "Martin 'Leviticus' Blom"
        !          1852: *           AHIDB_Copyright - Return Pointer To copyright notice, including
        !          1853: *               the ')' character: "?????1996 Martin Blom" OR "Public Domain"
        !          1854: *           AHIDB_Version - Return Pointer version string, normal AMIGA
        !          1855: *               Format: "paula 1.5 (18.2.96)\r\n"
        !          1856: *           AHIDB_Annotation - Return Pointer To an annotation string, which
        !          1857: *               can be several lines.
        !          1858: *           AHIDB_Record - Are you a sampler, too? Return True OR False.
        !          1859: *           AHIDB_FullDuplex - Return True OR False.
        !          1860: *           AHIDB_Realtime - Return True OR False.
        !          1861: *           AHIDB_MaxPlaySamples - Normally, Return the Default. See
        !          1862: *               AHIsub_AllocAudio(), section 2.
        !          1863: *           AHIDB_MaxRecordSamples - Return the size of the Buffer you fill
        !          1864: *               when recording.
        !          1865: *
        !          1866: *           The following are associated with AHIsub_HardwareControl() AND are
        !          1867: *           new For V2.
        !          1868: *           AHIDB_MinMonitorVolume
        !          1869: *           AHIDB_MaxMonitorVolume - Return the lower/upper limit For
        !          1870: *               AHIC_MonitorVolume. If unsupported but always 1.0, Return
        !          1871: *               1.0 For both.
        !          1872: *           AHIDB_MinInputGain
        !          1873: *           AHIDB_MaxInputGain - Return the lower/upper limit For
        !          1874: *               AHIC_InputGain. If unsupported but always 1.0, Return 1.0 For
        !          1875: *               both.
        !          1876: *           AHIDB_MinOutputVolume
        !          1877: *           AHIDB_MaxOutputVolume - Return the lower/upper limit For
        !          1878: *               AHIC_OutputVolume.
        !          1879: *           AHIDB_Inputs - Return how many inputs you have.
        !          1880: *           AHIDB_Input - Return a short string describing the argument:th
        !          1881: *               input. Number 0 should be the Default one. Example strings
        !          1882: *               can be "Line 1", "Mic", "Optical" OR whatever.
        !          1883: *           AHIDB_Outputs - Return how many outputs you have.
        !          1884: *           AHIDB_Output - Return a short string describing the argument:th
        !          1885: *               output. Number 0 should be the Default one. Example strings
        !          1886: *               can be "Line 1", "Headphone", "Optical" OR whatever.
        !          1887: *       argument - extra info For some attributes.
        !          1888: *       Default - What you should Return For unknown attributes.
        !          1889: *       taglist - Pointer To a tag List that eventually will be fed To
        !          1890: *           AHIsub_AllocAudio(), OR Null.
        !          1891: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure that eventually
        !          1892: *           will be fed To AHIsub_AllocAudio(), OR Null.
        !          1893: *
        !          1894: *   NOTES
        !          1895: *
        !          1896: *   SEE ALSO
        !          1897: *       AHIsub_AllocAudio(), AHIsub_HardwareControl(),
        !          1898: *       ahi.device/AHI_GetAudioAttrsA()
        !          1899: *
        !          1900: *****************************************************************************
        !          1901: *
        !          1902: *
        !          1903: 
        !          1904: AHIsub_GetAttr:
        !          1905:   pushm a3/a5-a6
        !          1906:   MOVE.l  a6,a5
        !          1907:   MOVE.l  pb_UtilLib(a5),a6
        !          1908: 
        !          1909:  IFD  MC020
        !          1910:   TST.l a1
        !          1911:  Else
        !          1912:   CMP.l #0,a1
        !          1913:  ENDC
        !          1914:   BEQ .notaglist      ;no tag list!
        !          1915: 
        !          1916:   MOVE.l  a1,a3
        !          1917: 
        !          1918:   pushm d0-d1
        !          1919: 
        !          1920:   MOVE.l  #AHIDB_Paula14Bit,d0
        !          1921:   MOVEQ #FALSE,d1
        !          1922:   MOVE.l  a3,a0
        !          1923:   call  GetTagData
        !          1924:   TST.l d0
        !          1925:   BNE .2
        !          1926: 
        !          1927: * Only For AHIDB_Paula14Bit False (== recording available)
        !          1928:   popm  d0-d1
        !          1929: 
        !          1930:   CMP.l #AHIDB_Record,d0
        !          1931:   BNE.b .not_record1
        !          1932:   MOVEQ #TRUE,d0
        !          1933:   BRA .exit
        !          1934: .not_record1
        !          1935:   CMP.l #AHIDB_FullDuplex,d0
        !          1936:   BNE.b .not_fullduplex1
        !          1937:   MOVEQ #TRUE,d0
        !          1938:   BRA .exit
        !          1939: .not_fullduplex1
        !          1940:   CMP.l #AHIDB_MaxRecordSamples,d0
        !          1941:   BNE.b .not_mrs1
        !          1942:   MOVE.l  #RECORDSAMPLES,d0
        !          1943:   BRA .exit
        !          1944: .not_mrs1
        !          1945:   CMP.l #AHIDB_MinMonitorVolume,d0
        !          1946:   BNE.b .not_minmonvol1
        !          1947:   MOVEQ #0,d0
        !          1948:   BRA .exit
        !          1949: .not_minmonvol1
        !          1950:   CMP.l #AHIDB_MaxMonitorVolume,d0
        !          1951:   BNE.b .not_maxmonvol1
        !          1952:   MOVE.l  #$10000,d0
        !          1953:   BRA .exit
        !          1954: .not_maxmonvol1
        !          1955:   CMP.l #AHIDB_MinInputGain,d0
        !          1956:   BNE.b .not_mingain1
        !          1957:   MOVE.l  #$10000,d0
        !          1958:   BRA .exit
        !          1959: .not_mingain1
        !          1960:   CMP.l #AHIDB_MaxInputGain,d0
        !          1961:   BNE.b .not_maxgain1
        !          1962:   MOVE.l  #$10000,d0
        !          1963:   BRA .exit
        !          1964: .not_maxgain1
        !          1965:   CMP.l #AHIDB_Inputs,d0
        !          1966:   BNE.b .not_inputs
        !          1967:   MOVEQ #2,d0
        !          1968:   BRA .exit
        !          1969: .not_inputs
        !          1970:   CMP.l #AHIDB_Input,d0
        !          1971:   BNE.b .not_input
        !          1972:   LSL.l #2,d1
        !          1973:   MOVE.l  .inputs(pc,d1.w),d0
        !          1974:   BRA .exit
        !          1975: .not_input
        !          1976:   BRA .3
        !          1977: .inputs:
        !          1978:   Dc.l  .input0
        !          1979:   Dc.l  .input1
        !          1980: 
        !          1981: .2
        !          1982: * Only For AHIDB_Paula14Bit True (== no recording)
        !          1983:   popm  d0-d1
        !          1984:   CMP.l #AHIDB_Record,d0
        !          1985:   BNE.b .not_record2
        !          1986:   MOVEQ #FALSE,d0
        !          1987:   BRA .exit
        !          1988: .not_record2
        !          1989:   CMP.l #AHIDB_FullDuplex,d0
        !          1990:   BNE.b .not_fullduplex2
        !          1991:   MOVEQ #FALSE,d0
        !          1992:   BRA .exit
        !          1993: .not_fullduplex2
        !          1994: 
        !          1995: .3
        !          1996: * Common Tags (AHIDB_14bit)
        !          1997: 
        !          1998:   CMP.l #AHIDB_Bits,d0
        !          1999:   BNE.b .not_bits
        !          2000:   MOVE.l  #AHIDB_Paula14Bit,d0
        !          2001:   MOVEQ #FALSE,d1
        !          2002:   MOVE.l  a3,a0
        !          2003:   call  GetTagData
        !          2004:   TST.l d0
        !          2005:   BEQ.b .no14bit
        !          2006:   MOVEQ #14,d0
        !          2007:   skipw
        !          2008: .no14bit
        !          2009:   MOVEQ #8,d0
        !          2010:   BRA .exit
        !          2011: .not_bits
        !          2012: .notaglist
        !          2013:   CMP.l #AHIDB_Frequencies,d0
        !          2014:   BNE.b .not_freqs
        !          2015:   MOVE.l  #FREQUENCIES,d0
        !          2016:   lsr.l #2,d0
        !          2017:   BRA .exit
        !          2018: .not_freqs
        !          2019: 
        !          2020:   CMP.l #AHIDB_Frequency,d0
        !          2021:   BNE.b .not_freq
        !          2022:   ADD.w d1,d1
        !          2023:   ADD.w d1,d1
        !          2024:   LEA uae(pc),a0
        !          2025: ; move.l  (a0,d1.w),d1
        !          2026: ; bsr calcperiod
        !          2027:   MOVE.l  (a0,d1.w),d0
        !          2028:   BRA .exit
        !          2029: .not_freq
        !          2030:   CMP.l #AHIDB_Index,d0
        !          2031:   BNE.b .not_index
        !          2032:   MOVE.l  d1,d0
        !          2033:   BSR findfreq
        !          2034:   MOVE.l  d1,d0
        !          2035:   BRA .exit
        !          2036: .not_index
        !          2037:   CMP.l #AHIDB_Author,d0
        !          2038:   BNE.b .not_author
        !          2039:   LEA .author(pc),a0
        !          2040:   MOVE.l  a0,d0
        !          2041:   BRA .exit
        !          2042: .not_author
        !          2043:   CMP.l #AHIDB_Copyright,d0
        !          2044:   BNE.b .not_copyright
        !          2045:   LEA .copyright(pc),a0
        !          2046:   MOVE.l  a0,d0
        !          2047:   BRA .exit
        !          2048: .not_copyright
        !          2049:   CMP.l #AHIDB_Version,d0
        !          2050:   BNE.b .not_version
        !          2051:   LEA IDString(pc),a0
        !          2052:   MOVE.l  a0,d0
        !          2053:   BRA .exit
        !          2054: .not_version
        !          2055:   CMP.l #AHIDB_Annotation,d0
        !          2056:   BNE.b .not_anno
        !          2057:   LEA .anno(pc),a0
        !          2058:   MOVE.l  a0,d0
        !          2059:   BRA .exit
        !          2060: .not_anno
        !          2061:   CMP.l #AHIDB_Realtime,d0
        !          2062:   BNE.b .not_realtime
        !          2063:   MOVEQ #TRUE,d0
        !          2064:   BRA .exit
        !          2065: .not_realtime
        !          2066:   CMP.l #AHIDB_Outputs,d0
        !          2067:   BNE.b .not_outputs
        !          2068:   MOVEQ #1,d0
        !          2069:   BRA .exit
        !          2070: .not_outputs
        !          2071:   CMP.l #AHIDB_Output,d0
        !          2072:   BNE.b .not_output
        !          2073:   LEA .output(pc),a0
        !          2074:   MOVE.l  a0,d0
        !          2075:   BRA .exit
        !          2076: .not_output
        !          2077: 
        !          2078: * Unknown attribute, Return Default.
        !          2079:   MOVE.l  d2,d0
        !          2080: .exit
        !          2081:   popm  a3/a5-a6
        !          2082:   RTS
        !          2083: .author   Dc.b  "Martin 'Leviticus' Blom",0
        !          2084: .copyright  Dc.b  "Public Domain",0
        !          2085: .anno   Dc.b  "14 bit routines by Christian Buchner.",0
        !          2086: .input0   Dc.b  "Parallel port sampler",0
        !          2087: .input1   Dc.b  "Aura sampler",0
        !          2088: .output   Dc.b  "Line",0
        !          2089:   Even
        !          2090: 
        !          2091: 
        !          2092: ****** [driver].audio/AHIsub_HardwareControl ********************************
        !          2093: *
        !          2094: *   NAME
        !          2095: *       AHIsub_HardwareControl -- Modify Sound card settings
        !          2096: *
        !          2097: *   SYNOPSIS
        !          2098: *       AHIsub_HardwareControl( attribute,  argument, audioctrl );
        !          2099: *       D0                      D0          D1        A2
        !          2100: *
        !          2101: *       LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
        !          2102: *
        !          2103: *   IMPLEMENTATION
        !          2104: *       Set OR Return the state of a particular hardware component. AHI uses
        !          2105: *       AHIsub_GetAttr() To supply the user with limits AND what Tags are
        !          2106: *       available.
        !          2107: *
        !          2108: *   INPUTS
        !          2109: *       attribute - Is really a Tag AND can be one of the following:
        !          2110: *           AHIC_MonitorVolume - Set the input monitor Volume To argument.
        !          2111: *           AHIC_MonitorVolume_Query - Return the current input monitor
        !          2112: *               Volume (argument is ignored).
        !          2113: *
        !          2114: *           AHIC_InputGain - Set the input gain To argument. (V2)
        !          2115: *           AHIC_InputGain_Query (V2)
        !          2116: *
        !          2117: *           AHIC_OutputVolume - Set the output Volume To argument. (V2)
        !          2118: *           AHIC_OutputVolume_Query (V2)
        !          2119: *
        !          2120: *           AHIC_Input - Use the argument:th input source (Default is 0). (V2)
        !          2121: *           AHIC_Input_Query (V2)
        !          2122: *
        !          2123: *           AHIC_Output - Use the argument:th output destination (Default
        !          2124: *               is 0). (V2)
        !          2125: *           AHIC_Output_Query (V2)
        !          2126: *
        !          2127: *       argument - What value attribute should be set To.
        !          2128: *       audioctrl - Pointer To an AHIAudioCtrlDrv structure.
        !          2129: *
        !          2130: *   RESULT
        !          2131: *       Return the state of selected attribute. If you were asked To set
        !          2132: *       something, Return True. If attribute is unknown To you OR unsupported,
        !          2133: *       Return False.
        !          2134: *
        !          2135: *   NOTES
        !          2136: *       This Call must be safe from interrupts.
        !          2137: *
        !          2138: *   SEE ALSO
        !          2139: *       ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
        !          2140: *
        !          2141: *****************************************************************************
        !          2142: *
        !          2143: *
        !          2144: 
        !          2145: AHIsub_HardwareControl:
        !          2146:   CMP.l #AHIC_MonitorVolume,d0
        !          2147:   BNE.b .dontsetmonvol
        !          2148:   MOVE.l  ahiac_DriverData(a2),a1
        !          2149:   LSR.l #8,d1
        !          2150:   LSR.l #2,d1
        !          2151:   MOVE.w  d1,p_MonitorVolume(a1)
        !          2152:   BRA.b .exit
        !          2153: .dontsetmonvol
        !          2154:   CMP.l #AHIC_MonitorVolume_Query,d0
        !          2155:   BNE.b .dontgetmonvol
        !          2156:   MOVE.l  ahiac_DriverData(a2),a1
        !          2157:   MOVEQ #0,d0
        !          2158:   MOVE.w  p_MonitorVolume(a1),d0
        !          2159:   LSL.l #8,d0
        !          2160:   LSL.l #2,d0
        !          2161:   BRA.b .quit
        !          2162: .dontgetmonvol
        !          2163:   CMP.l #AHIC_Input,d0
        !          2164:   BNE.b .dontsetinput
        !          2165:   MOVE.l  ahiac_DriverData(a2),a1
        !          2166:   MOVE.w  d1,p_Input(a1)
        !          2167:   BRA.b .exit
        !          2168: .dontsetinput
        !          2169:   CMP.l #AHIC_Input_Query,d0
        !          2170:   BNE.b .dontgetinput
        !          2171:   MOVE.l  ahiac_DriverData(a2),a1
        !          2172:   MOVEQ #0,d0
        !          2173:   MOVE.w  p_Input(a1),d0
        !          2174:   BRA.b .quit
        !          2175: .dontgetinput
        !          2176:   MOVEQ #FALSE,d0
        !          2177: .quit
        !          2178:   RTS
        !          2179: .exit
        !          2180:   MOVEQ #TRUE,d0
        !          2181:   RTS
        !          2182: 
        !          2183: 
        !          2184: 
        !          2185: 
        !          2186: 
        !          2187: 
        !          2188: 
        !          2189: ;----------------------------------------------------------------------------
        !          2190: 
        !          2191: Interrupt_Dummy:
        !          2192:   MOVE.w  #INTF_AUD0!INTF_AUD1!INTF_AUD2!INTF_AUD3,INTREQ(a0)
        !          2193: SoftInt_Dummy:
        !          2194:   RTS
        !          2195: 
        !          2196: ;in:
        !          2197: * d0  scratch
        !          2198: * d1  INTENAR && INTREQR
        !          2199: * a0  CUSTOM
        !          2200: * a1  &(paulaBase->p_RecIntData)
        !          2201: * a5  &RecordInterrupt
        !          2202: * a6  ExecBase
        !          2203: RecordInterrupt:
        !          2204: 
        !          2205: * This Function will be executed up To 28000 times per second - that's once per
        !          2206: * rasterline! It has To be as fast as possible.
        !          2207: 
        !          2208:   MOVE.w  #INTF_AUD2!INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
        !          2209:   MOVEQ #0,d0
        !          2210:   ;move.b _ciaa+ciaprb,d0     ;read parallel port
        !          2211:  IFD  MC020
        !          2212:   ;move.l convtable(pc,d0.w*4),d0   ;1 unsigned byte -> 2 signed words
        !          2213:  Else
        !          2214:   ADD.w d0,d0
        !          2215:   ADD.w d0,d0
        !          2216:   ;move.l convtable(pc,d0.w),d0
        !          2217:  ENDC
        !          2218:   MOVE.w  d0,AUD2DAT(a0)      ;right
        !          2219:   MOVE.w  d0,AUD3DAT(a0)      ;left
        !          2220: 
        !          2221:   MOVE.l  (a1),a5       ;p_RecFillPtr
        !          2222:   MOVE.l  d0,(a5)+      ;store sample in buffer
        !          2223:   MOVE.l  a5,(a1)+      ;update pointer
        !          2224:   SUBQ.w  #1,(a1)       ;p_ReqFillCount
        !          2225:   BEQ ri_Filled     ;branch if buffer filled
        !          2226:   RTS
        !          2227: 
        !          2228: ;convtable
        !          2229: ;CNT  SET 0
        !          2230: ; REPT  256
        !          2231: ; dc.b  CNT-128,CNT-128,CNT-128,CNT-128
        !          2232: ; SET CNT+1
        !          2233: ; ENDR
        !          2234: 
        !          2235: ;in:
        !          2236: * d0  scratch
        !          2237: * d1  INTENAR && INTREQR
        !          2238: * a0  CUSTOM
        !          2239: * a1  &(paulaBase->p_RecIntDataAura)
        !          2240: * a5  &RecordInterrupt
        !          2241: * a6  ExecBase
        !          2242: RecordInterruptAura:
        !          2243:   MOVE.w  #INTF_AUD2!INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
        !          2244:   MOVE.l  (a1)+,a5
        !          2245:   MOVE.l  (a5),d0       ;read aura sampler
        !          2246:   EOR.l #$80008000,d0
        !          2247:   MOVE.l  (a1),a5       ;p_RecFillPtr
        !          2248:   MOVE.l  d0,(a5)+      ;store sample in buffer
        !          2249:   MOVE.l  a5,(a1)+      ;update pointer
        !          2250: 
        !          2251:   MOVE.w  d0,d1
        !          2252:   LSR.w #8,d0
        !          2253:   MOVE.b  d0,d1
        !          2254: 
        !          2255:   MOVE.w  d1,AUD2DAT(a0)      ;right
        !          2256:   MOVE.w  d1,AUD3DAT(a0)      ;left
        !          2257: 
        !          2258:   SUBQ.w  #1,(a1)       ;p_ReqFillCount
        !          2259:   BEQ ri_Filled     ;branch if buffer filled
        !          2260:   RTS
        !          2261: 
        !          2262: ri_Filled:
        !          2263: 
        !          2264: * This part is only executed every RECORDSAMPLES:th time... No need To hurry.
        !          2265: 
        !          2266:   MOVE.l  8(a1),d0      ;p_RecBuffer2->
        !          2267:   MOVE.l  4(a1),8(a1)     ;p_RecBuffer1->p_RecBuffer2
        !          2268:   MOVE.l  d0,4(a1)      ;            ->p_RecBuffer1
        !          2269:   MOVE.l  d0,-4(a1)     ;p_RecFillPtr
        !          2270:   MOVE.w  #RECORDSAMPLES,(a1)   ;p_ReqFillCount
        !          2271:   MOVE.l  12(a1),a1     ;p_RecSoftIntPtr
        !          2272:   JMP _LVOCause(a6)
        !          2273: 
        !          2274: 
        !          2275: ;in:
        !          2276: * d0  scratch
        !          2277: * d1  scratch
        !          2278: * a0  scratch
        !          2279: * a1  paulaBase
        !          2280: * a5  scratch
        !          2281: RecordSoftInt:
        !          2282: 
        !          2283: * This Function is NOT executed many times per second AND is therefore NOT
        !          2284: * fully optimized... ;)
        !          2285:   push  a2
        !          2286:   MOVE.w  p_MonitorVolume(a1),CUSTOM+AUD2VOL
        !          2287:   MOVE.w  p_MonitorVolume(a1),CUSTOM+AUD3VOL
        !          2288:   MOVE.l  p_RecBuffer2(a1),p_rmBuffer(a1)
        !          2289:   MOVE.l  p_AudioCtrlP(a1),a2
        !          2290:   LEA p_RecordMessage(a1),a1
        !          2291:   MOVE.l  ahiac_SamplerFunc(a2),a0
        !          2292:   MOVE.l  h_Entry(a0),a5
        !          2293:   JSR (a5)
        !          2294:   pop a2
        !          2295:   RTS
        !          2296: 
        !          2297: ;in:
        !          2298: * d0  scratch
        !          2299: * d1  INTENAR && INTREQR
        !          2300: * a0  CUSTOM
        !          2301: * a1  &(paulaBase->p_PlayIntData)
        !          2302: * a5  &AudioInterrupt
        !          2303: * a6  ExecBase
        !          2304: 
        !          2305: AudioInterrupt2:        ;Two hardware channels used
        !          2306:        MOVEM.l a2/d2/d3,-(sp)
        !          2307:        MOVEQ #1,d3       ; Enable UAE-side AHI
        !          2308:                moveq #0,d2
        !          2309:        MOVE.w  4(a1),d2      ; Length
        !          2310:        MOVE.l  6(a1),d1      ; Period
        !          2311:        LEA.l   12(a1),a2
        !          2312:        NOT.w 10(a1)        ;double buffering
        !          2313:        BEQ.b .1
        !          2314:        ADD.w #4*4,a2
        !          2315: .1
        !          2316:        LEA p_AudPtrs-p_PlaySoftIntPtr(a1),a5;
        !          2317: 
        !          2318:        MOVE.l  a2,(a5)
        !          2319:        MOVE.l  (a2)+,a0
        !          2320:        MOVEQ #3,d0
        !          2321:        jsr  $F0FFB0      ; Left channel
        !          2322:        MOVE.l  (a2)+,a0
        !          2323:        MOVEQ #4,d0
        !          2324:        jsr  $F0FFB0      ; Right channel
        !          2325: 
        !          2326:         moveq #2,d0
        !          2327:        moveq #1,d1
        !          2328:        jsr  $F0FFB0      ; Enable AHI.
        !          2329: 
        !          2330:        MOVE.l  (a1),a1       ;p_PlaySoftInt
        !          2331:        MOVEM.l (sp)+,a2/d2/d3
        !          2332:        MOVE.w  #INTF_AUD0,$DFF09C    ;Clear the interrupt
        !          2333:        JMP _LVOCause(a6)     ;start PlaySoftInt
        !          2334: 
        !          2335: AudioInterrupt4:        ;Four hardware channels used
        !          2336: 
        !          2337:   MOVEM.l (a1)+,d0/d1     ;p_PlaySoftIntPtr,p_AudLen/p_AudPer
        !          2338: 
        !          2339: 
        !          2340: 
        !          2341:   MOVE.l  d1,AUD1LEN(a0)
        !          2342:   MOVE.l  d1,AUD2LEN(a0)
        !          2343:   MOVE.l  d1,AUD3LEN(a0)
        !          2344: 
        !          2345:         MOVE.l  d1,AUD0LEN(a0)
        !          2346:   NOT.l (a1)+       ;double buffering
        !          2347: 
        !          2348:   LEA p_AudPtrs-p_AudPtr1A(a1),a5
        !          2349:   BEQ.b .1
        !          2350: 
        !          2351:   ADD.w #4*4,a1
        !          2352: 
        !          2353: .1
        !          2354: 
        !          2355: 
        !          2356:   MOVE.l  a1,(a5)
        !          2357:   MOVE.l  (a1)+,AUD0LC(a0)
        !          2358:   MOVE.l  (a1)+,AUD1LC(a0)
        !          2359:   MOVE.l  (a1)+,AUD2LC(a0)
        !          2360:   MOVE.l  (a1)+,AUD3LC(a0)
        !          2361:   MOVE.l  d0,a1       ;p_PlaySoftInt
        !          2362:         MOVE.w  #INTF_AUD0,INTREQ(a0)   ;Clear the interrupt
        !          2363: 
        !          2364:   JMP _LVOCause(a6)     ;start PlaySoftInt
        !          2365: 
        !          2366: ;in:
        !          2367: * d0  scratch
        !          2368: * d1  scratch
        !          2369: * a0  scratch
        !          2370: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2371: * a5  scratch
        !          2372: 
        !          2373: SoftInt_16bitM:
        !          2374:   pushm a2/a3/a4/a6
        !          2375:   MOVE.l  a1,a5
        !          2376:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2377:   JSR (a3)        ;call Player Hook
        !          2378:   JSR (a4)        ;call PreTimer
        !          2379:   BNE .exit
        !          2380:   MOVEM.l (a5),d0/a0/a1/a2/a3/a5
        !          2381:   JSR (a3)        ;call Mixer Hook
        !          2382: 
        !          2383: * convert AND transfer Buffer
        !          2384:   MOVE.l  (a5),a0
        !          2385: .loop
        !          2386:   MOVE.w  (a1)+,(a0)+
        !          2387: 
        !          2388: ;  MOVE.w  (a1)+,(a0)+
        !          2389:   DBF d0,.loop
        !          2390: .exit
        !          2391:   JSR (a6)        ;call PostTimer, a2 ok
        !          2392:   popm  a2/a3/a4/a6
        !          2393:   MOVE.w  #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,CUSTOM+DMACON
        !          2394:   RTS
        !          2395: 
        !          2396: ;in:
        !          2397: * d0  scratch
        !          2398: * d1  scratch
        !          2399: * a0  scratch
        !          2400: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2401: * a5  scratch
        !          2402: 
        !          2403: SoftInt_16bitS:
        !          2404:   pushm a2/a3/a4/a6
        !          2405:   MOVE.l  a1,a5
        !          2406:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2407:   JSR (a3)        ;call Player Hook
        !          2408:   JSR (a4)        ;call PreTimer
        !          2409:   BNE .exit
        !          2410:   MOVEM.l (a5),d0/a0/a1/a2/a3/a5
        !          2411:   JSR (a3)        ;call Mixer Hook
        !          2412: 
        !          2413: * convert AND transfer Buffer
        !          2414:   MOVEM.l (a5),a0/a3
        !          2415: .loop
        !          2416: ; REPT 2
        !          2417: ;left
        !          2418:   MOVE.w  (a1)+,(a3)+
        !          2419: ;right
        !          2420:   MOVE.w  (a1)+,(a0)+
        !          2421: ; ENDR
        !          2422:   DBF d0,.loop
        !          2423: .exit
        !          2424:   JSR (a6)        ;call PostTimer, a2 ok
        !          2425:   popm  a2/a3/a4/a6
        !          2426:   MOVE.w  #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,CUSTOM+DMACON
        !          2427:   RTS
        !          2428: 
        !          2429: ;in:
        !          2430: * d0  scratch
        !          2431: * d1  scratch
        !          2432: * a0  scratch
        !          2433: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2434: * a5  scratch
        !          2435: 
        !          2436: SoftInt_14bitM:
        !          2437:   pushm a2/a3/a4/a6
        !          2438:   MOVE.l  a1,a5
        !          2439:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2440:   JSR (a3)        ;call Player Hook
        !          2441:   JSR (a4)        ;call PreTimer
        !          2442:   BNE .exit
        !          2443:   MOVEM.l (a5),d0/a0/a1/a2/a3/a5
        !          2444:   JSR (a3)        ;call Mixer Hook
        !          2445: 
        !          2446: * convert AND transfer Buffer
        !          2447:   MOVEM.l (a5),a0/a3/a4/a5    ;a3/a4 unused
        !          2448: .loop
        !          2449:  REPT 2
        !          2450:   MOVE.b  (a1)+,(a0)+
        !          2451:   MOVE.b  (a1)+,d1
        !          2452:   LSR.b #2,d1
        !          2453:   MOVE.b  d1,(a5)+
        !          2454:  ENDR
        !          2455:   DBF d0,.loop
        !          2456: .exit
        !          2457:   JSR (a6)        ;call PostTimer, a2 ok
        !          2458:   popm  a2/a3/a4/a6
        !          2459:   MOVE.w  #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
        !          2460:   RTS
        !          2461: 
        !          2462: ;in:
        !          2463: * d0  scratch
        !          2464: * d1  scratch
        !          2465: * a0  scratch
        !          2466: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2467: * a5  scratch
        !          2468: 
        !          2469: SoftInt_14CbitM:
        !          2470:   pushm a2/a3/a4/a6
        !          2471:   MOVE.l  a1,a5
        !          2472:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2473:   JSR (a3)        ;call Player Hook
        !          2474:   JSR (a4)        ;call PreTimer
        !          2475:   BNE .exit
        !          2476:   MOVEM.l (a5),d0/a0/a1/a2/a3/a4/a5
        !          2477:   JSR (a3)        ;call Mixer Hook
        !          2478: 
        !          2479: * convert AND transfer Buffer, using the table
        !          2480:   MOVE.l  (a4),a0
        !          2481:   MOVE.l  12(a4),a4
        !          2482:   MOVEQ #0,d1
        !          2483: .loop
        !          2484: 
        !          2485:  REPT 2
        !          2486:  IFD  MC020
        !          2487:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2488:   MOVE.w  (a5,d1.l*2),d1
        !          2489:  Else
        !          2490:   MOVEQ #0,d1
        !          2491:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2492:   ADD.w d1,d1
        !          2493:   MOVE.w  (a5,d1.l),d1
        !          2494:  ENDC
        !          2495:   MOVE.b  d1,(a4)+      ;low byte
        !          2496:   LSR.w #8,d1
        !          2497:   MOVE.b  d1,(a0)+      ;high byte
        !          2498:  ENDR
        !          2499:   DBF d0,.loop
        !          2500: .exit
        !          2501:   JSR (a6)        ;call PostTimer, a2 ok
        !          2502:   popm  a2/a3/a4/a6
        !          2503:        MOVE.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
        !          2504:   RTS
        !          2505: 
        !          2506: ;in:
        !          2507: * d0  scratch
        !          2508: * d1  scratch
        !          2509: * a0  scratch
        !          2510: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2511: * a5  scratch
        !          2512: 
        !          2513: SoftInt_14bitS:
        !          2514:   pushm a2/a3/a4/a6
        !          2515:   MOVE.l  a1,a5
        !          2516: 
        !          2517:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2518:   JSR (a3)        ;call Player Hook
        !          2519:   JSR (a4)        ;call PreTimer
        !          2520:   BNE .exit
        !          2521:   MOVEM.l (a5),d0/a0/a1/a2/a3/a5
        !          2522:   JSR (a3)        ;call Mixer Hook
        !          2523:   push  a2
        !          2524: * convert AND transfer Buffer
        !          2525: * TODO: Use a table!
        !          2526: 
        !          2527:   MOVEM.l (a5),a0/a2/a3/a5
        !          2528:         ;move.l d2,-(a7)
        !          2529: 
        !          2530: .loop
        !          2531:  REPT 2
        !          2532: ;left
        !          2533: 
        !          2534:         ;add.b #1,check
        !          2535:   MOVE.b  (a1)+,(a2)+                      ;used for uae
        !          2536:   MOVE.b  (a1)+,(a3)+
        !          2537:         ;move.b check,(a2)+
        !          2538: ;right
        !          2539:   MOVE.b  (a1)+,(a0)+
        !          2540:   MOVE.b  (a1)+,(a5)+
        !          2541:  ENDR
        !          2542:   DBF d0,.loop
        !          2543:         ;movem.l (a7)+,d2
        !          2544:   pop a2
        !          2545: .exit
        !          2546:   JSR (a6)        ;call PostTimer, a2 ok
        !          2547:   popm  a2/a3/a4/a6
        !          2548:   ;move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
        !          2549:   RTS
        !          2550: 
        !          2551: ;in:
        !          2552: * d0  scratch
        !          2553: * d1  scratch
        !          2554: * a0  scratch
        !          2555: * a1  &(paulaBase->p_PlaySoftIntData)
        !          2556: * a5  scratch
        !          2557: 
        !          2558: SoftInt_14CbitS:
        !          2559:   pushm a2/a3/a4/a6
        !          2560:   MOVE.l  a1,a5
        !          2561:   MOVEM.l (a5)+,a0/a1/a2/a3/a4/a6
        !          2562:   JSR (a3)        ;call Player Hook
        !          2563:   JSR (a4)        ;call PreTimer
        !          2564:   BNE .exit
        !          2565:   MOVEM.l (a5),d0/a0/a1/a2/a3/a4/a5
        !          2566:   JSR (a3)        ;call Mixer Hook
        !          2567:   push  a2
        !          2568: * convert AND transfer Buffer, using the table
        !          2569:   MOVEM.l (a4),a0/a2/a3/a4
        !          2570:   MOVEQ #0,d1
        !          2571: .loop
        !          2572:  REPT 2
        !          2573: 
        !          2574: ;left
        !          2575:  IFD  MC020
        !          2576:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2577:   MOVE.w  (a5,d1.l*2),d1
        !          2578:  Else
        !          2579:   MOVEQ #0,d1
        !          2580:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2581:   ADD.w d1,d1
        !          2582:   MOVE.w  (a5,d1.l),d1
        !          2583:  ENDC
        !          2584:   MOVE.b  d1,(a3)+      ;low byte
        !          2585:   LSR.w #8,d1
        !          2586:   MOVE.b  d1,(a2)+      ;high byte
        !          2587: 
        !          2588: ;right
        !          2589:  IFD  MC020
        !          2590:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2591:   MOVE.w  (a5,d1.l*2),d1
        !          2592:  Else
        !          2593:   MOVEQ #0,d1
        !          2594:   MOVE.w  (a1)+,d1      ;fetch 16 bit sample
        !          2595:   ADD.w d1,d1
        !          2596:   MOVE.w  (a5,d1.l),d1
        !          2597:  ENDC
        !          2598:   MOVE.b  d1,(a4)+      ;low byte
        !          2599:   LSR.w #8,d1
        !          2600:   MOVE.b  d1,(a0)+      ;high byte
        !          2601:  ENDR
        !          2602: 
        !          2603:   DBF d0,.loop
        !          2604:   pop a2
        !          2605: .exit
        !          2606:   JSR (a6)        ;call PostTimer
        !          2607:   popm  a2/a3/a4/a6
        !          2608:   ;move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,CUSTOM+DMACON
        !          2609:   RTS
        !          2610: flag    Dc.l 0
        !          2611: EndCode:
        !          2612: check        Dc.b 0
        !          2613:  END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.